Claude Code 的”记忆”问题
每次启动 Claude Code,它都是一张白纸——不记得昨天帮你修了什么 Bug,不记得你偏好什么代码风格,不记得项目的架构决策。
这是 LLM 的天然限制:没有持久记忆。
但 Claude Code 通过多层记忆机制来弥补这个问题。理解这些机制,能让我们更高效地和它协作。
记忆的层次
Claude Code 的记忆系统分为四个层次:
| 层次 | 持久性 | 范围 | 来源 |
|---|---|---|---|
| 对话上下文 | 会话内 | 当前对话 | 自动维护 |
| CLAUDE.md | 永久 | 项目/用户 | 手动编写 |
| 自动记忆 | 永久 | 项目 | Claude Code 自动生成 |
| 工具输出缓存 | 会话内 | 当前对话 | 自动缓存 |
┌─────────────────────────────────────────────┐
│ 第 4 层:对话上下文(最短暂) │
│ 当前会话的所有对话和工具调用 │
├─────────────────────────────────────────────┤
│ 第 3 层:工具输出缓存 │
│ 本次会话中读取过的文件内容等 │
├─────────────────────────────────────────────┤
│ 第 2 层:自动记忆 │
│ Claude Code 自动记录的项目信息 │
├─────────────────────────────────────────────┤
│ 第 1 层:CLAUDE.md(最持久) │
│ 手动编写的项目记忆文件 │
└─────────────────────────────────────────────┘
第 1 层:对话上下文
工作原理
对话上下文是最直接的”记忆”——Claude Code 记住当前会话中的所有交互:
你: 读取 src/utils/format.ts
Claude: [读取文件内容]
你: 给 formatDate 函数添加时区支持
Claude: [修改文件,它记得文件内容]
你: 运行测试确认
Claude: [运行测试,它记得刚才的修改]
上下文窗口限制
对话上下文受限于模型的上下文窗口大小:
| 模型 | 上下文窗口 | 大约等于 |
|---|---|---|
| Claude Sonnet | 200K tokens | ~150K 字 |
| Claude Opus | 200K tokens | ~150K 字 |
当对话内容超过窗口大小时,早期内容会被压缩。
压缩机制
Claude Code 的上下文压缩策略:
- 保留最近 N 轮对话的完整内容
- 将早期对话压缩为摘要
- 保留关键信息(文件修改记录、重要决策)
- 丢弃冗余信息(重复的文件读取、中间过程)
压缩后的上下文大概是这样的:
[压缩摘要]
- 之前讨论了 src/utils/format.ts 的重构
- 已完成:添加了 formatDate 的时区支持
- 已完成:更新了相关测试
- 待处理:formatNumber 函数还需要国际化支持
[最近的完整对话]
你: 现在来处理 formatNumber 的国际化
Claude: 好的,让我先看看当前的实现...
手动触发压缩
当你感觉 Claude Code 开始”忘事”,可以手动压缩:
/compact
这会立即触发压缩,释放上下文空间。
也可以带参数指定压缩的重点:
/compact 保留关于数据库迁移的所有讨论
第 2 层:CLAUDE.md
CLAUDE.md 是最重要的持久记忆机制。我们在前面的文章中已经详细讨论过,这里补充几个和记忆相关的要点。
作为”长期记忆”
CLAUDE.md 相当于 Claude Code 的”长期记忆”——每次启动都会读取,确保它始终了解项目的基本信息。
# 项目记忆
## 架构决策记录
- 2026-01: 从 REST 迁移到 GraphQL(原因:减少 over-fetching)
- 2026-02: 引入 Redis 缓存层(原因:API 响应时间从 500ms 降到 50ms)
- 2026-03: 采用 Monorepo 结构(原因:共享代码和统一构建)
## 已知问题
- Safari 下 CSS Grid 有兼容性问题,使用 Flexbox 替代
- PostgreSQL 全文搜索在中文场景下需要 pg_jieba 扩展
记忆的更新
CLAUDE.md 需要手动维护。一个好的习惯是在做重大决策后立即更新:
我们刚决定把认证从 JWT 改为 Session-based。
请更新 CLAUDE.md 中的架构决策记录。
第 3 层:自动记忆
Claude Code 有一个自动记忆功能,会在交互过程中自动记录重要信息。
自动记忆的内容
Claude Code 会自动记住:
- 你纠正过的错误(“不要用 var,用 const”)
- 你表达过的偏好(“我喜欢函数式风格”)
- 项目的特殊规则(“这个项目不用分号”)
记忆存储位置
自动记忆存储在 ~/.claude/memory/ 目录下:
~/.claude/
└── memory/
├── project-abc123.json # 项目级记忆
├── project-def456.json # 另一个项目
└── global.json # 全局记忆
查看和管理记忆
/memory
这会显示当前项目的自动记忆内容。
记忆的触发
当你纠正 Claude Code 的行为时,它会自动记住:
你: 帮我写一个函数
Claude: [使用 function 关键字]
你: 我们项目用箭头函数,不用 function 声明
Claude: 明白了,我会记住这个偏好。
下次在同一个项目中,Claude Code 会自动使用箭头函数。
第 4 层:工具输出缓存
文件读取缓存
在同一个会话中,Claude Code 不会重复读取同一个文件:
你: 读取 src/config.ts
Claude: [读取文件,缓存内容]
你: src/config.ts 中有什么配置项?
Claude: [使用缓存的内容回答,不再读取文件]
缓存失效
当文件被修改后,缓存会自动失效:
你: 修改 src/config.ts,添加新配置
Claude: [修改文件]
你: 现在 src/config.ts 的内容是什么?
Claude: [重新读取文件,因为缓存已失效]
长会话的记忆策略
问题:上下文膨胀
一个 2 小时的开发会话,上下文可能增长到:
系统提示: ~5K tokens
CLAUDE.md: ~2K tokens
对话历史: ~100K tokens ← 主要消耗
工具输出: ~50K tokens ← 文件内容等
─────────────────────────
总计: ~157K tokens
接近 200K 的窗口限制,响应会变慢,早期内容会被压缩。
策略 1:定期压缩
每完成一个小任务后,手动压缩:
/compact 保留最近的数据库迁移讨论
策略 2:分会话处理
不同的任务用不同的会话:
# 会话 1:处理前端
claude
> 重构 Header 组件
> /exit
# 会话 2:处理后端
claude
> 优化 API 性能
> /exit
策略 3:用 CLAUDE.md 传递上下文
在会话之间,通过更新 CLAUDE.md 传递重要信息:
在结束这个会话之前,请把我们讨论的架构决策更新到 CLAUDE.md 中。
下一个会话启动时,Claude Code 会自动读取更新后的 CLAUDE.md。
策略 4:摘要中转
在会话结束前,让 Claude Code 生成摘要:
总结一下我们这次会话做了什么,还有什么没完成的。
把摘要保存下来,下次会话开始时粘贴给 Claude Code:
上次会话的摘要:
[粘贴摘要]
请继续未完成的工作。
项目记忆 vs 用户记忆
项目记忆
和特定项目绑定的记忆:
~/.claude/memory/project-abc123.json
内容示例:
{
"projectId": "abc123",
"projectPath": "/home/user/my-project",
"memories": [
{
"type": "preference",
"content": "使用箭头函数而非 function 声明",
"createdAt": "2026-03-01T10:00:00Z"
},
{
"type": "correction",
"content": "import 语句按字母顺序排列",
"createdAt": "2026-03-05T14:30:00Z"
},
{
"type": "knowledge",
"content": "项目使用 pnpm 而非 npm",
"createdAt": "2026-03-08T09:15:00Z"
}
]
}
用户记忆
跨项目的全局记忆:
~/.claude/memory/global.json
内容示例:
{
"memories": [
{
"type": "preference",
"content": "代码注释使用中文",
"createdAt": "2026-02-15T10:00:00Z"
},
{
"type": "preference",
"content": "commit message 使用英文,遵循 Conventional Commits",
"createdAt": "2026-02-20T11:00:00Z"
}
]
}
记忆的有效利用
1. 主动告诉 Claude Code 重要信息
不要等它犯错再纠正,主动告诉它:
在这个项目中:
1. 我们使用 Tailwind CSS 4.x,不用 CSS Modules
2. 状态管理用 Zustand,不用 Redux
3. 测试框架是 Vitest,不是 Jest
4. API 请求用 ky,不用 axios
2. 纠正时要明确
# 不好:模糊的纠正
不对,换一种方式
# 好:明确的纠正
不要用 class 组件,我们项目只用函数组件 + Hooks。
这是项目规范,请记住。
3. 利用 CLAUDE.md 减少重复纠正
如果你发现自己反复纠正同一个问题,把它写进 CLAUDE.md:
## 常见误区(Claude Code 请注意)
- 不要使用 moment.js,使用 date-fns
- 不要使用 lodash,使用原生方法
- 不要使用 class 组件
- CSS 不要用 px,使用 rem
4. 定期清理过时记忆
自动记忆可能包含过时的信息。定期检查和清理:
/memory
如果发现过时的记忆,可以告诉 Claude Code:
之前记录的"使用 Jest 测试框架"已经过时了,
我们已经迁移到 Vitest。请更新记忆。
记忆系统的局限
1. 不能跨会话传递对话内容
每次新会话,对话历史都是空的。只有 CLAUDE.md 和自动记忆会保留。
2. 自动记忆不是 100% 可靠
Claude Code 可能会遗漏一些重要信息,或者记住不重要的信息。CLAUDE.md 是更可靠的记忆方式。
3. 压缩会丢失细节
上下文压缩后,早期对话的细节会丢失。如果某些信息很重要,在压缩前明确告诉 Claude Code 保留。
4. 记忆有容量限制
CLAUDE.md 太长会消耗过多 Token。自动记忆也有存储上限。保持记忆精简是关键。
实战:构建高效的记忆体系
第一步:写好 CLAUDE.md
这是记忆体系的基础。参考前面的文章,写一份精简但全面的 CLAUDE.md。
第二步:建立纠正习惯
每次 Claude Code 做错了什么,明确纠正并要求它记住:
不对,这个项目的 API 路径前缀是 /api/v2 而不是 /api/v1。
请记住这个规则。
第三步:会话管理
- 短任务:一个会话搞定
- 中等任务:一个会话,中间
/compact一两次 - 长任务:分多个会话,用 CLAUDE.md 传递上下文
第四步:定期维护
每周花 5 分钟:
- 检查 CLAUDE.md 是否需要更新
- 查看自动记忆是否有过时内容
- 确认项目约定是否有变化
记忆优化清单
| 优化项 | 效果 | 操作 |
|---|---|---|
| 编写 CLAUDE.md | 每次会话都有基础上下文 | 一次性投入 |
| 主动告知偏好 | 减少纠正次数 | 新项目开始时 |
| 定期 /compact | 保持响应速度 | 每 30 分钟 |
| 分会话处理 | 避免上下文溢出 | 切换任务时 |
| 清理过时记忆 | 避免错误指导 | 每周一次 |
| 会话结束前总结 | 便于下次继续 | 每次会话结束 |
记忆是智能的基础。Claude Code 的记忆系统虽然不完美,但通过合理的配置和使用习惯,我们可以让它在每次对话中都表现得像一个”了解项目的老同事”。好的记忆管理不是让 AI 记住一切,而是让它记住正确的事情。
相关文章
评论
加载中...
评论
加载中...