第 10 章 Memory 功能

Memory 要解决的问题

每次开启新会话,Claude Code 对上次发生的事情一无所知。这对短任务问题不大,但对长期使用的人来说很麻烦——你得反复解释项目背景、重申偏好、重新介绍约定。

Memory 的目的是让这些信息持久化,下次用的时候不用再说一遍。

Memory 是一些 Markdown 文件

Claude Code 的 memory 没有数据库,没有向量检索,就是几个 markdown 文件。你可以直接用 /memory 打开来编辑,加、删、改都行。

这个设计的好处是透明:你能看到 memory 里存了什么,能直接控制它,不是一个不透明的黑箱在背后记住一些东西。

memory 文件有五个层级:

  1. 个人 memory:~/.claude/CLAUDE.md,只对你自己生效,跨所有项目
  2. 项目共享 memory:项目根目录的 CLAUDE.md,提交到仓库,团队可见
  3. 项目个人 memory:项目根目录的 CLAUDE.local.md,不提交,只对你自己在这个项目里生效
  4. 企业 memory:通过管理平台下发的 CLAUDE.md,组织级别的统一约束
  5. team memory:通过 API 同步,团队所有成员共享(需要启用对应 feature)

系统启动时会把这些文件加载进上下文,所以 agent 能"知道"这些信息。

后台自动提取

除了手工编辑,会话结束后系统会自动做一次 memory 提取——把这次会话里值得长期保留的内容写入 memory 文件。

提取不是每轮都发生,而是有触发条件:会话累计消耗超过 10,000 tokens 之后才开始考虑,此后每增加 5,000 tokens 且至少发生 3 次工具调用就触发一次。这两个条件组合在一起,估计的是"这次会话发生了足够多的事情,值得提取"。

提取本身是由一个 forked subagent 在后台做的,不阻塞主对话。提取出来的内容会被整理进一个固定的模板结构——从 Session Title 到 Files and Functions 到 Worklog,一共 10 个段落,总预算 12,000 tokens。这个模板决定了"记什么、怎么组织",也解释了为什么自动提取的 memory 风格总是很统一。

为什么提取用 subagent,而不是简单地截取文本

直接把对话的最后几轮截下来存进 memory,实现最简单,但效果差。

有价值的信息往往散落在整个会话里:第 5 轮发现了一个重要约定,第 15 轮确认了一个技术决策,第 28 轮遇到了一个坑。简单截取只能拿到最近的内容,拿不到这些散落的关键点。

用 subagent 做提取的好处是:它能读完整个会话历史,判断什么值得保留、以什么形式保留,而不只是截取最近几轮。提取结果更准确,代价是比简单截取更耗资源。

Memory 不是万能的

Memory 文件会被加载进每次会话的上下文,但这也意味着它占用 token。如果 memory 文件很大、包含大量不相关的历史记录,反而会稀释上下文,让 agent 在噪声里找有用信息。

保持 memory 文件精炼、定期清理不再相关的内容,是让 memory 真正好用的关键。系统已经开始在这方面做尝试——有一个叫 auto-dream 的后台机制,会自动修剪过期的 memory 和合并重复条目——但目前还在早期阶段,大部分维护工作仍然得靠你自己判断。