Lucent's Blog

当时明月在 曾照彩云归

人生不相见,动如参与商。


Claude Code 为什么“不会忘”?深入拆解它的记忆系统与上下文压缩机制

很多人第一次使用 Claude Code 时,都会有一种很奇怪的感觉:

它好像真的“记得”我之前做过什么。

你让它连续改几个小时代码,它仍然知道:

  • 当前在修哪个 Bug

  • 刚刚改过哪些文件

  • 哪个方案已经失败过

  • 下一步应该继续做什么

甚至隔了很久回到项目里,它还能接上之前的工作。

但问题是:

大模型的上下文窗口再大,也不可能无限大。 一个真实的软件项目,往往会包含:

  • 几十到上百个文件

  • 数十轮对话

  • 大量工具调用

  • 很长的日志、报错和代码片段

如果把所有内容都塞进 Prompt,模型迟早会“失忆”。

所以 Claude Code 真正厉害的地方,并不是上下文窗口有多长,而是它实现了一套完整的:

  • 记忆系统(Memory)

  • 多层上下文管理

  • 自动压缩(Compact)

  • 项目级长期知识

这篇文章,我们就来完整拆解 Claude Code 是如何做到“看起来像真的记住了一切”的。

一、为什么单纯扩大上下文窗口没有意义

很多人会认为:

上下文窗口越大,模型就越聪明。

但实际上,大窗口只能解决一部分问题。

假设你正在让模型帮你开发一个 Web 项目。

前 20 轮里,你们已经完成了:

  • 登录页

  • JWT 验证

  • 用户信息缓存

  • 接口封装

然后你继续让它:

  • 修改路由

  • 修复权限 Bug

  • 调整 UI

  • 写测试

当上下文越来越长时,会出现几个问题:

  1. Token 成本不断上升

  2. 推理速度越来越慢

  3. 早期信息开始被边缘化

  4. 模型会逐渐“忘记”前面已经做过什么

于是你会看到这种经典场景:

  • 模型重新建议一个已经被否定过的方案

  • 又一次修改已经修好的文件

  • 忘记用户已经说过“不要动 tests 目录”

  • 又把登录逻辑重写一遍

所以真正的问题不是“窗口够不够大”,而是:

哪些内容应该被永久记住?哪些内容应该被压缩?哪些内容应该被丢掉?

Claude Code 的答案,就是把上下文拆成多层记忆。

二、Claude Code 的六层记忆架构

Claude Code 并不是简单地维护一份聊天记录,而是把信息分成六层。

大致可以理解为:

  1. 当前输入

  2. 最近几轮对话

  3. Tool 调用结果

  4. Session Memory

  5. Project Memory

  6. 长期用户偏好

其中真正关键的是中间两层:

  • Session Memory

  • Project Memory

它们分别解决“当前正在做什么”和“这个项目是什么”两个问题。

三、Session Memory:让模型知道“现在做到哪里了”

Session Memory 可以理解成“当前工作记忆”。

它并不会保存所有聊天记录,而是会把当前任务压缩成一个简洁、结构化的状态。

例如:

当前任务:为登录系统增加 refresh token

已完成:

- Login.tsx 已接入 JWT 登录

- auth.ts 已增加 token 校验

- 用户信息已写入 localStorage

失败尝试:

- 尝试使用 cookie 持久化,但跨域失败

下一步:

- 增加 refresh token 接口

- 在 axios 拦截器中自动刷新

这类信息会被长期保留在当前会话里。

因此即使原始聊天记录已经被压缩、裁剪,模型仍然知道:

  • 目前做到哪里

  • 哪些文件改过

  • 哪些方案不能再试

  • 下一步该做什么

这也是为什么 Claude Code 很少会突然“重新开始”。

因为它真正依赖的,不是完整聊天记录,而是 Session Memory。

四、Project Memory:让模型记住整个项目

如果说 Session Memory 是“当前任务记忆”,那么 Project Memory 就是“项目长期记忆”。

它保存的是更稳定、更长期的信息,例如:

  • 项目的技术栈

  • 目录结构

  • 用户的编码习惯

  • 项目里的约定

  • 常见文件位置

例如一个项目可能会被记录成:

项目:后台管理系统

技术栈:Next.js + Tailwind + Prisma

目录规则:

- API 放在 /src/api

- 页面放在 /src/pages

- 公共组件放在 /src/components

项目约束:

- 必须使用 TypeScript

- 不允许修改 tests 目录

- 所有样式优先使用 Tailwind

有了这层信息,模型下一次进入项目时,不需要重新扫描整个仓库。

它已经知道:

  • 应该去哪找代码

  • 应该用什么方式写

  • 哪些地方不能碰

所以它表现得更像一个真正长期参与项目的工程师。

五、双轨注入:为什么 Claude Code 不会把所有东西都塞进 Prompt

Claude Code 有一个非常关键的设计:

双轨注入(Dual Injection)

也就是把不同类型的信息,放到不同位置。

第一轨:稳定信息

长期不变的信息,会被放到系统提示或者 CLAUDE.md 一类的位置。

例如:

  • 项目技术栈

  • 长期规则

  • 用户偏好

  • 目录结构

比如:

- 始终使用 TypeScript

- 所有接口放在 /src/api

- 不允许修改 tests 目录

- Tailwind 优先于 CSS 文件

这些内容不会频繁变化,因此不需要每一轮都重新生成。

第二轨:动态信息

动态变化的信息,会被放到当前对话上下文里。

例如:

  • 最近修改了哪些文件

  • 当前正在修什么 Bug

  • 哪个报错刚刚出现

  • 哪个工具刚刚运行过

例如:

最近修改:

- Login.tsx

- auth.ts

当前问题:

- refresh token 在 token 过期后没有自动刷新

这样一来:

  • 稳定信息不会被重复浪费 Token

  • 动态信息又能保持实时更新

这也是 Claude Code 在长会话里依然很稳定的原因。

六、Claude Code 如何决定“什么值得记住”

模型并不会把所有内容都记下来。

Claude Code 会先做一次筛选。

它会判断:

  • 这条信息是否与当前任务有关

  • 是否可能在未来再次被引用

  • 是否属于长期规则

  • 是否只是一次性的临时内容

例如下面这些内容,大概率会被保留:

  • 当前正在修的 Bug

  • 最近修改过的文件

  • 用户明确提出的约束

  • 项目结构和技术栈

  • 已经验证过的结论

而下面这些内容,则会被丢弃:

  • 一次性的闲聊

  • 无意义的长日志

  • 重复的工具输出

  • 已经失败且不会再用的尝试

例如:

npm install 输出了 300 行日志

这类内容通常不会被保留。

真正会留下来的,往往只是:

安装失败,原因是 react-router-dom 版本冲突

Claude Code 会尽可能把“信息”留下,而不是把“原文”留下。

七、Compact:Claude Code 是如何压缩上下文的

Claude Code 内部有一套完整的 Compact 机制。

当上下文开始接近上限时,它不会突然丢掉前面的消息,而是逐步压缩。

视频里提到了四个层级:

  • Snip Compact

  • Micro Compact

  • Context Collapse

  • Auto Compact

1. Snip Compact

最轻量的压缩。

它只是把明显无意义的内容删掉。

例如:

  • 重复日志

  • 大段重复代码

  • 已经出现过的报错

  • 连续几轮没有变化的内容

例如:

省略:重复的 npm install 输出

省略:重复的 stack trace

这个阶段,整体结构几乎不会变化。

2. Micro Compact

进一步压缩。

它会把几轮对话、多个工具输出、连续的修改过程,压缩成一个简洁摘要。

例如原本是:

打开 auth.ts

修改 Login.tsx

修复 JWT 校验

添加 localStorage

测试登录成功

压缩后会变成:

已完成登录流程与 JWT 验证,用户信息已持久化。

3. Context Collapse

当上下文已经非常长时,会触发“上下文折叠”。

此时系统只会保留:

  • 当前任务

  • 最近修改

  • Project Memory

  • Session Memory

  • 最关键的少量上下文

其它内容会被折叠成一个高度摘要。

例如:

之前已完成:

- 登录模块

- 权限模块

- 路由守卫

当前继续处理 refresh token

虽然详细过程没了,但任务状态仍然保留。

4. Auto Compact

Claude Code 会自动判断什么时候需要压缩。

触发条件通常包括:

  • Token 使用量过高

  • 上下文接近窗口上限

  • 最近几轮新增了大量工具输出

也就是说,用户通常不会感知到“压缩”这件事。

系统会在后台自动完成。

八、多阶段压缩:为什么 Claude Code 的摘要比普通 AI 更可靠

很多 AI 的压缩方式很粗暴:

直接把几十轮对话压成一句话。

这样很容易漏掉关键内容。

Claude Code 更像是在做“多阶段整理”。

它大致会经历:

  1. 完整读取上下文

  2. 提取重点

  3. 生成结构化摘要

  4. 再进一步压缩

可以理解成:

原始对话

→ 工作记录

→ Session Memory

→ 超短摘要

这样做的好处是:

  • 不容易遗漏关键文件

  • 不会忘记失败尝试

  • 能保留“下一步该做什么”

  • 压缩后仍然能继续工作

Claude Code 看起来“不会忘”,本质上是因为它先把重要内容存进记忆,再删除原始上下文。

九、四阶段记忆整理流程

Claude Code 内部还有一个非常像“知识管理”的流程:

  1. Direct

  2. Gather

  3. Consolidate

  4. Prune & Index

Direct

先记录所有发生的事。

包括:

  • 用户说了什么

  • 修改了哪些文件

  • Tool 返回了什么

  • 模型做了哪些决定

Gather

收集与当前任务相关的内容。

例如:

  • 最近修改的文件

  • 最近运行的命令

  • 当前 Bug 对应的报错

Consolidate

把这些内容整理成结构化记忆。

例如:

当前任务:修复 refresh token

已修改:Login.tsx、auth.ts

当前阻塞:跨域导致 cookie 无法使用

下一步:改用 Authorization Header

Prune & Index

最后删除无意义内容,并建立索引。

这样未来模型需要时,可以快速找到:

  • 哪个文件之前改过

  • 哪个问题之前出现过

  • 哪个方案之前已经失败

十、为什么 Claude Code 比普通聊天机器人更像“项目搭档”

普通聊天机器人往往只能看到当前几轮消息。

一旦对话变长,就会:

  • 忘记约束

  • 忘记文件

  • 忘记任务进度

而 Claude Code 的行为更像一个真正的工程师:

  • 有工作日志

  • 有项目文档

  • 有长期记忆

  • 会自动整理和压缩信息

它并不是“记住了所有聊天记录”。

它真正记住的是:

  • 项目是什么

  • 当前做到哪里

  • 哪些内容重要

  • 哪些内容可以丢掉

这也是 Claude Code 最大的秘密。

它不是在“存聊天记录”,而是在“持续维护项目状态”。

十一、Claude Code 的真正未来

未来的大模型,不会只是拥有越来越大的上下文窗口。

真正重要的是:

  • 有长期记忆

  • 能主动整理知识

  • 能理解项目结构

  • 能知道“下一步该做什么”

Claude Code 展示的,其实已经不是传统意义上的“聊天 AI”,而更像是一种:

持续参与项目、不断整理上下文、长期陪伴开发的 AI 工程师。

而记忆系统,正是这一切的基础。

下一篇

从 Claude Code 源码里,我看到了下一代 Agent 的真正形态 不是更聪明的模型,而是更成熟的系统。 最近看了 Claude Code 源码。 npm 包里还原出的完整 TypeScript 源码, 4756 个文件。 刚看到这个数字的时候,我的第一反应不是“太夸张了”,而是: Clau…

阅读