📦 本文属于「Claude Code 源码解析」系列 · 记忆系统篇
最近 Claude Code 的源码被”意外公开”,我花了几天时间看了一部分。一开始其实挺懵的,代码量大、名词多,看几分钟就容易劝退。但慢慢找到方法之后,反而越看越有意思,也确实学到了一些对自己项目很有用的东西。
一开始我以为 Claude Code 的核心竞争力在模型本身,但看完之后发现,真正厉害的是工程设计。它不是”更聪明”,而是”更会做事”。模型只是大脑,Claude Code 做的是把这个大脑组织成一个完整的系统,让它能持续工作、记忆、修正。
我们平时聊天,看起来是”一问一答”,但在系统内部,其实是一整套流程:用户输入 → 模型思考 → 可能调用工具 → 最后输出结果。只有这整个流程结束之后,系统才会触发”额外动作”,比如记录记忆或整理历史。记忆不是随时在发生,而是在”任务结束”这个时间点统一处理的。
Claude Code 的记忆不是简单把聊天记录存下来,而是分两步做。第一步是即时记录:每次任务结束后,系统快速判断有没有值得长期保存的信息,有就写入记忆目录,但有路径限制、防重复执行和并发控制。第二步是定期整理,也就是 autoDream,不会频繁触发,有一组条件串行把关:全局开关、时间间隔、会话数量、锁状态,全部满足才执行。
更有意思的是,整合不在当前对话里完成,而是启动一个子 Agent 在后台做。主 Agent 继续和用户交互,子 Agent 读历史、整理、更新记忆结构。这样既不影响体验,也方便做权限隔离。
如果两个进程同时尝试整理记忆,就会冲突。Claude Code 的做法很经典:用文件当锁。先检查锁是否存在,没有就写入自己的 PID,写完再读一遍确认是不是自己拿到了锁,不是就直接退出。
有个容易被忽略的细节:整理失败时会把”上次整理时间”回滚。否则系统会误以为已经整理过,以后永远不再触发。这种失败回滚的设计,是很多工程系统稳定性的关键。
记忆系统有一个核心文件,类似目录(MEMORY.md),里面只放索引,每项对应一个独立文件。内容分散在子文件里。原因很现实:上下文有限,全加载进去又慢又乱。策略是”先给目录,需要时再加载具体内容”,做了一层轻量级检索。
autoDream 整理记忆时,不是简单追加,而是有步骤:先看已有记忆避免重复,找新信息,合并或更新,最后删除过时内容。很多系统只会”越记越多”,但不会”清理错误”,长期下去信息越来越脏。Claude Code 把”删除旧信息”明确作为一个步骤来处理,这点我觉得特别重要。
源码里有个反复出现的思路:先做成本低的判断,再做昂贵的操作。触发 autoDream 时先检查开关、时间间隔这些简单条件,通过之后才去扫描文件、加锁、启动子 Agent。这个原则可以直接用在日常开发里,尤其是多步骤流程。
我自己在做 SAGE-Code,这套设计给了我几个改进方向:记忆不只是”存”,要有整理和清理机制;耗时操作放后台用子 Agent 处理;通过条件控制触发时机,不让所有逻辑每次都执行。
一开始看这类源码很容易产生挫败感。但你不需要一次看懂全部,只要抓住一个模块彻底搞明白,就已经很有收获了。别从头读,也别试图全部看懂。选一个具体功能切进去,顺着调用链往上追,一边看一边画流程。这样读,不但不会劝退,反而会越看越有感觉。