Claude Code 的源码被公开后,有人直奔最有趣的部分——记忆系统本身。
记忆架构:Markdown 文件的 v1 设计
Claude Code 把记忆存成明文 Markdown 文件,路径是 ~/.claude/projects/<项目名>/memory/。每个项目一个文件夹,每次对话结束后可写文件,文件在会话之间持久化。这就是整个持久化模型。
根目录有一个 MEMORY.md 索引文件。每次新会话开始时,Claude 读取这个索引,了解存在哪些记忆。正是这里埋着 Anthropic 从未公开的硬性限制。
两道硬限制,静默失效
MEMORY.md 在源码里硬编码了两道限制:
200 行上限。 索引超过 200 行时,系统静默截断。它会在被截断内容后面追加一条警告,但这条警告只有在手动翻文件时才能看到。Claude 在对话里看到的是干净的 system prompt,根本不知道索引被切过。
25KB 上限。 单独一个字节数限制,处理每行特别长的边缘情况。
失败模式是静默的。你刚写到第 201 行,最旧的记忆从索引底部掉落。Claude 下次新会话时完全不知道那些记忆存在过。它不会报错,不会告诉你,只是忘了。
记忆被区分为四种明确类型:
- User memories:记录你是谁——角色、专业领域、偏好、沟通方式。仅本人可见。
- Feedback memories:记录你给过的指导——修正、验证过的方法、需要停止做的事。
- Project memories:记录代码库里正在发生的事——截止日期、决策、从代码本身推导不出的架构上下文。
- Reference memories:存储指向外部系统的指针——bug 追踪在哪里、该关注哪个 Slack 频道。
源码里写得很明确:如果一个信息能通过 grep 或 git 从当前代码库推导出来,就不应该被存为记忆。
每次对话的检索:Sonnet 侧调用,5 文件上限
每次对话中,Claude Code 会单独调用一次 Claude Sonnet,只为了弄清楚哪些记忆文件与当前查询相关。
流程是:扫描所有记忆文件,提取文件名和描述,发送这个清单给 Sonnet,让它选出最相关的文件。每次最多返回 5 个文件。
这是一个语义相关步骤,但它的依据只是文件名和一句话描述。不是 embeddings,不是向量搜索,只是一个语言模型在读列表然后做判断。
还有一个 memoryFreshnessText() 函数,对超过一天的旧记忆生成"过时警告"。警告内容是:"此记忆是 X 天前的快照。记忆是时间点观察,不是实时状态。关于代码行为或 file:line 引用的声明可能已过时。"
这条警告直接加在记忆内容前面,Claude 看到时就知道这条记忆可能是错的。但从外部没有办法知道具体哪条记忆触发了这个警告。
会话结束后有一个 extract-memories agent 在后台运行——回顾刚才发生了什么,自动提炼记忆。这意味着有两样东西在同时往记忆目录写东西:主 agent 在会话中写,后台提取器在会话结束后写。
那个让系统崩溃的场景
你用 Claude Code 在一个真实项目上工作了三个月。它已经学会了:
- 你的偏好和工作方式
- 1 月做出的架构决策
- 那个不稳定的 endpoint 在测试时不应该被信任
- 你的团队对 hotfix 跳过 PR review
然后你写到了第 201 条。
索引静默截断。最旧的记忆从底部掉落。Claude 下次新会话时,满眼是干净的上下文,根本不知道那些记忆存在过。
接下来发生的是:
- Claude 写了一个测试,命中那个不稳定的 endpoint
- Claude 再次问你关于 PR review 政策的问题
- Claude 反驳你们几个月前共同同意的架构
它不是在幻觉。它没坏。它只是忘了。而且它没有办法告诉你它忘了。
Freshness warnings 让这更糟——它们只对被加载的记忆触发。如果一条记忆在截断中丢失了,它根本不会被加载。没有警告,没有信号。Claude 不知道自己不知道。
mem0 的修复方案
mem0 是一个专门为生产级 AI agent 设计的记忆层。它用向量存储替代扁平 Markdown 文件。记忆被 embedding,检索是语义搜索。没有索引文件可以截断,没有 200 行上限,没有 5 文件限制,没有静默截断。6 个月前的记忆如果与当前工作相关,就会浮出来。
mem0 的 Claude Code 插件安装方式是:
/plugin marketplace add mem0ai/mem0
/plugin install mem0@mem0-plugins
安装之后,语义搜索、跨会话召回和完整的记忆管理都启用:add_memory、search_memories、update_memory、delete_memory。
Anthropic 给了一个正确但有天花板的设计——对于刚起步的项目,扁平 Markdown 加四类分类足够用。但"200 行静默截断"这个 failure mode 很危险:它不是报错,是慢性数据丢失,用户完全感知不到。Agent 记忆系统的工程难度不在于存,在于边界条件下的行为要可预期。mem0 的解法本质上是把记忆存算分离——用专用向量存储替代文件,做对了。