Claude Code 的记忆进化:Auto Memory 与 PreCompact Hook 完全解析
问题的起源
用 Claude Code 写代码的人都遇到过一个痛点:Context Window 满了怎么办?
每个 session 的上下文是有限的。当对话太长,Claude Code 会自动压缩(compaction)旧的对话内容,只保留摘要。问题是——压缩意味着丢失细节。你花了半小时调试的那个诡异 bug,压缩后可能就剩一句"修复了 XX 问题"。
下次开新 session?更惨,Claude 完全不记得之前发生了什么。
这就引出了两个核心问题:
- 跨 session 记忆:Claude 怎么记住上次学到的东西?
- Compaction 保护:压缩前怎么保存完整上下文?
Claude Code 最近给出了自己的答案。
Auto Memory:Claude 自己写笔记
机制
Auto Memory 是 Claude Code 新增的自动记忆系统。跟用户手动维护的 CLAUDE.md 不同,Auto Memory 是 Claude 自己写给自己的笔记。
在工作过程中,Claude 会自动记录:
- 项目模式:构建命令、测试约定、代码风格
- 调试心得:棘手问题的解决方案、常见错误原因
- 架构笔记:关键文件、模块关系、重要抽象
- 用户偏好:沟通风格、工作流习惯、工具选择
存储结构
每个项目有独立的记忆目录:
~/.claude/projects/<project>/memory/
├── MEMORY.md # 索引文件,每次 session 自动加载前 200 行
├── debugging.md # 调试模式详细笔记
├── api-conventions.md # API 设计决策
└── ... # 其他主题文件
<project> 路径基于 Git 仓库根目录,同一 repo 的所有子目录共享一个记忆目录。
加载策略
这是设计上比较聪明的地方:
MEMORY.md:前 200 行自动注入系统 prompt,每次 session 都能看到- 主题文件(如
debugging.md):不自动加载,Claude 按需读取
这样既保证了核心记忆的连续性,又不会浪费宝贵的 Context Window。
优点
🟢 零维护成本——用户不需要手动记录项目细节 🟢 Per-project 隔离——不同项目互不污染 🟢 分层设计——索引轻量加载,详细内容按需读取 🟢 越用越聪明——调试过的坑不会再踩第二次
潜在问题
🔴 200 行硬限制——超过的部分不会自动加载,可能丢失重要信息 🔴 质量不可控——Claude 自己决定记什么,可能记了无用的、漏掉关键的 🔴 错误记忆——如果写入了错误信息,后续 session 会一直被误导 🔴 膨胀问题——长期使用后文件越来越多,需要人工清理 🔴 不透明——用户可能不知道 Claude 记了什么,除非主动去翻目录 🔴 Context 成本——每次启动都加载 200 行,占用 Context Window
管理方式
可以通过以下方式管理 Auto Memory:
/memory命令打开文件选择器,直接编辑- 直接告诉 Claude:“记住我们用 pnpm 不用 npm”
- 手动编辑
~/.claude/projects/<project>/memory/下的文件
也可以通过环境变量控制开关:
export CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 # 强制关闭
export CLAUDE_CODE_DISABLE_AUTO_MEMORY=0 # 强制开启
PreCompact Hook:在压缩前抢救上下文
Auto Memory 解决了"记什么"的问题,但还有一个场景它管不到——Compaction 瞬间的完整上下文保存。
这个问题的解决方案来自社区。Twitter 用户 @zarazhangrui 分享了一个巧妙的做法。
原始方案:/handover 命令
Zara 最初创建了一个自定义 slash command /handover:
- 用户在 session 结束前手动执行
- Claude 回顾整个对话,生成一份"交班报告"(
HANDOVER.md) - 内容包括:做了什么、成功/失败的部分、关键决策、踩过的坑、下一步计划
这本质上是医院护士换班时的 handover notes——确保下一个人知道所有重要信息。
进化方案:PreCompact Hook 自动化
社区用户 @pauloportella_ 提出了关键改进:“turn this into a pre auto compact hook and it will do it automatically”。
这个方案利用了 Claude Code 的 Hooks 系统——在特定生命周期事件触发时自动执行用户定义的脚本。
配置方式
在 .claude/settings.local.json 中注册 Hook:
{
"hooks": {
"PreCompact": [
{
"matcher": "auto",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/pre-compact-handover.py"
}
]
}
]
}
}
执行流程
当 Claude Code 检测到 Context Window 即将满载,自动触发 compaction 时:
- PreCompact Hook 触发——在压缩执行之前
- 脚本从 stdin 接收 JSON,包含
session_id、transcript_path(完整对话记录路径)等 - 读取
transcript_path获取完整的、未压缩的对话内容 - 调用
claude -p启动一个新的 Claude 实例,专门生成 handover 摘要 - 保存为
HANDOVER-YYYY-MM-DD.md - Compaction 正常执行,压缩旧内容
关键细节
matcher 的作用:
PreCompact 事件的 matcher 支持两个值:
"auto":只在系统自动 compaction 时触发(Context Window 快满了)"manual":只在用户手动执行/compact命令时触发"*"或省略:两种都匹配
Zara 选择了 "auto"——只有系统自动压缩时才生成 handover,手动压缩时不触发(因为手动压缩说明用户有意为之,不需要抢救上下文)。
独立实例的设计:
用 claude -p 启动新实例来生成摘要,而不是在当前 session 里做,原因是:
- 当前 session 的 Context Window 已经快满了,没有空间再做摘要
- 独立实例有完整的 Context 空间来处理对话记录
Hooks 系统全貌
PreCompact 只是 Claude Code Hooks 系统的一个事件。完整的生命周期事件包括:
| 事件 | 触发时机 |
|---|---|
SessionStart | Session 开始或恢复 |
UserPromptSubmit | 用户提交 prompt |
PreToolUse | 工具调用执行前(可拦截) |
PostToolUse | 工具调用成功后 |
PreCompact | Context 压缩前 |
Stop | Claude 完成回复 |
SessionEnd | Session 结束 |
Hook 支持三种处理器类型:
- Command:执行 shell 脚本
- Prompt:发送 prompt 给模型做单轮评估
- Agent:启动子代理,可使用工具验证条件
详细文档:Hooks 完整参考 | Hooks 入门指南
两种方案的关系
Auto Memory 和 PreCompact Hook 解决的是不同层面的问题:
🔵 Auto Memory:日常积累——Claude 在工作过程中持续记录有价值的知识,跨 session 可用 🟢 PreCompact Hook:紧急抢救——在 Context 被压缩的那一刻,保存完整的工作状态
它们不是竞争关系,而是互补的:
- Auto Memory 是长期记忆,记录的是"知识"
- PreCompact Handover 是工作快照,记录的是"状态"
最佳实践是两者结合使用——Auto Memory 让 Claude 越来越了解你的项目,PreCompact Hook 确保你永远不会因为 Context 压缩而丢失工作进度。
参考链接
如果这篇文章对你有帮助,欢迎请我喝杯咖啡,支持我继续创作更多内容。
Buy me a coffee