你用 AI 编程超过一周,会发现一个尴尬的问题:每次开新会话,Claude 像失忆了一样。你得重新解释“我是谁”“我在做什么项目”“上次我们约定好不要一次性丢多道题”。
这就像你雇了一个非常聪明的助理,但他每天早上来上班时完全不记得昨天的事。每天第一件事是给他重新看一遍员工手册。
记忆系统就是这本员工手册。它让 Claude 在新会话开始时自动读到关键信息,不需要你每次复述。
本文以 Jason 的真实记忆系统为原型,逐层拆解设计思路。读完你会知道为什么需要三层分类、每条记忆怎么追溯来源、以及什么该放进记忆文件而不是 CLAUDE.md。
- 你已经读过 记忆系统,知道 CLAUDE.md 是 Claude Code 启动时自动读取的上下文文件
- 你已经在实际项目中用过 Claude Code 至少一周,遇到过“新会话不记得之前约定”的痛点
类比:记忆像什么
Section titled “类比:记忆像什么”想像你的手机通讯录。你不会记住每个朋友的电话号码,你只记住他们在通讯录里。打电话时,手机自动按名字找到号码。
Claude Code 的记忆系统完全一样。你不需要让 Claude 记住所有细节(那会塞满上下文窗口,费 token 又费钱),你只需要让它知道去哪找。
更精确的类比是图书馆的索引卡片。你走进图书馆不会把所有书翻一遍,而是先查索引卡片,找到目标书所在的书架和位置,然后直接走过去拿。MEMORY.md 就是这个索引卡片柜,memory/ 下的每个文件就是书架上的一本书。
三层稀疏记忆
Section titled “三层稀疏记忆”这是整个系统最核心的设计。所有记忆文件分三层:
A 层:始终加载(约 13 个文件)
Section titled “A 层:始终加载(约 13 个文件)”每个新会话,Claude Code 都会读取 CLAUDE.md。Jason 的全局 CLAUDE.md 底部有一行强制指令:
## 强制加载的记忆索引@~/.claude/projects/-Users-jason-intern-journal/memory/MEMORY.md这一行告诉 Claude:每次启动都读 MEMORY.md。而 MEMORY.md 就是 A 层索引——列出了约 13 个始终适用的记忆文件:
- 用户背景(零基础,解释从日常类比开始)
- 教学节奏(小段讲解 + 即时一问,禁一次性丢多题)
- bash sigpipe 陷阱(避免
cat | head误报失败) - 公开输出无业务上下文
- 等等
共同特征:任何项目、任何任务都适用,不依赖具体技术栈或项目名。
B 层:关键词触发(约 5 个文件)
Section titled “B 层:关键词触发(约 5 个文件)”MEMORY.md 里写了一条规则:
命中公司基建关键词(公司代码平台 / 内网 npm / 泳道 / AIGC 网关 / Bedrock / 图床 / MDM)→ Read MEMORY-COMPANY.md
Claude 读到这条规则后,不会主动去读 MEMORY-COMPANY.md。只有当前对话中出现这些关键词(比如用户说“帮我推到图床”),Claude 才会触发 Read 操作。
为什么这样设计?B 层记忆是公司的具体技术栈和流程,只在用到时才加载,不浪费通用任务上下文的 token。
C 层:项目名触发(约 7 个文件)
Section titled “C 层:项目名触发(约 7 个文件)”类似 B 层,但触发条件是项目名:
命中项目名(prize / quanzhiping / activity-planner / 视频评价 agent 等)→ Read MEMORY-PROJECTS.md
C 层是项目专属记忆——某个项目里的特殊约定、历史决策、踩坑记录。只有在该项目的会话中才需要加载。
为什么要分层?
Section titled “为什么要分层?”直观的数字对比:
- 如果所有记忆文件每会话都加载:约 25 个文件,每个平均 30 行,总计约 750 行。这会吃掉上下文窗口的很大一部分,而且大部分内容当前任务根本用不上。
- 三层设计后:A 层约 13 个始终加载,B 和 C 层的约 12 个文件按需加载。一个不涉及公司基建、不在特定项目的通用任务,只需要读 A 层。
核心原则:让 Claude 知道信息存在哪里,但不占用上下文空间去存储那些用不到的信息。 这一设计哲学的更多背景详见设计哲学。
类比:CPU 缓存层级
Section titled “类比:CPU 缓存层级”如果你了解一点计算机原理,这和 CPU 的 L1/L2/L3 缓存很像:
- L1 缓存(A 层):每次都查,速度最快但容量最小
- L2 缓存(B/C 层):按需查询,容量稍大但需要额外加载时间
- 主内存:所有其他信息,需要时再搜索
每条记忆的来源可追溯
Section titled “每条记忆的来源可追溯”打开 memory/ 下的任意文件,看它的 YAML frontmatter:
---name: 避免 cat | head 类管道模式(SIGPIPE 陷阱)description: 用 Read 工具或原生命令参数代替管道,避免 SIGPIPE 误报type: feedbackoriginSessionId: a2b1fbf6-9f69-4b79-84a0-e692088aef18---originSessionId 是一个关键字段。它不是随便编的——它是 Claude Code 会话的唯一标识。
这意味着每条记忆都能追溯到“谁、在什么时候、因为什么”产生的。用 Jason 系统里的实际例子:
feedback_teaching_style.md的 originSessionId 是4ca6864d-...,对应那次 OpenClaw Hook 学习中 Jason 说“用带我学习然后提问的方式,而不是现在这种直接出题目”feedback_bash_sigpipe.md的 originSessionId 是a2b1fbf6-...,对应那次 daily-learn 跑了cat manifest.json | python3 -m json.tool | head -40被 SIGPIPE 误导
为什么要追溯?
Section titled “为什么要追溯?”三个月后你看到一条记忆规则“禁止 cat | head”,你可能不记得为什么。打开文件,看到 Why 段:“2026-05-08 daily-learn 跑 cat manifest.json | python3 -m json.tool | head -40 就被这个坑了——JSON 完全有效,命令‘失败’了”。
这就是记忆不是死规则,而是活教训。每条记忆都带着当时的具体场景和问题,让你(和 Claude)能理解规则背后的意图,而不只是机械执行。
记忆即 git 历史
Section titled “记忆即 git 历史”这是 Jason 系统里最有创意的设计决策:记忆文件不存数据库、不用外部存储,直接放在 git 仓库里,和代码一样用 git 管理。
memory/ 目录是 intern-journal 仓库的一部分(通过 symlink 暴露给 Claude Code)。每次修改记忆都走正常的 git commit。
这意味着你可以用 git 回答这些问题:
# "我四月份学到了什么?"git log --after=2026-04-01 --before=2026-05-01 -- dotfiles/home-claude/memory/
# "关于 sigpipe 的记忆是什么时候加的?"git log -- dotfiles/home-claude/memory/global/feedback_bash_sigpipe.md
# "最近一个月新增了哪些规则?"git log --oneline --since="1 month ago" -- dotfiles/home-claude/memory/每次 git log 的输出就是你的学习时间线。commit message 本身也是记忆的一部分——比如 026c5d9 GitHub 整理 Phase 8 复盘:写入 gh CLI 陷阱到 memory,这条 commit 告诉你这条记忆是 “Phase 8 复盘” 时产生的。
为什么不用数据库或笔记软件?
Section titled “为什么不用数据库或笔记软件?”- 数据库:需要额外维护,和你的日常 git 工作流脱节
- 笔记软件:没有版本历史,改了就丢了之前的样子
- git:你已经在用它管理代码,记忆跟代码一样待遇——有历史、可回溯、可协同
更重要的是:git blame 能告诉你每条记忆是 “谁”(哪次对话)在 “什么时候” 添加的,以及 “为什么”(commit message)。这跟 originSessionId 形成双重可追溯链。
添加新记忆前先 grep 三个索引
Section titled “添加新记忆前先 grep 三个索引”记忆系统最大的敌人不是遗忘,而是矛盾积累。
比如:你之前有一条规则 “学习类任务默认走带学+提问模式”。过了两个月,你遇到一个场景觉得 “直接出题更快”,于是加了一条 “快速学习场景可以批量出题”。这两条规则不矛盾吗?什么时候用哪条?
Jason 系统里有一条硬规则,写在了 MEMORY.md 的最底部:
新事实出现时:先 grep 三个索引文件看有没有冲突条目,再决定更新还是新增。
三个索引文件是:
MEMORY.md(A 层索引)MEMORY-COMPANY.md(B 层索引)MEMORY-PROJECTS.md(C 层索引)
操作流程:
- grep 检查冲突:新规则的关键词是否已经出现在任何索引中?
- 如果已存在:打开冲突文件,更新它。可能补充例外情况,可能改写表达让它更精确,可能发现规则已过时需要删除。
- 如果不存在:创建新文件,在合适的索引中注册。
这防止了最常见的问题:两个互相矛盾的规则同时存在,Claude 读到时不知道该遵守哪个,用户自己也忘了哪个更“正确”。
一个实际例子
Section titled “一个实际例子”Jason 最初有一条规则:feat 分支结束后删掉工作树。后来他发现有时需要回来查上下文,决定保留工作树。这次不是加一条”有时保留工作树”的新规则——而是直接修改了原规则文件,把”删除”改成”保留一周后再删”。更新,不叠加。
记忆 vs CLAUDE.md — 该放哪里?
Section titled “记忆 vs CLAUDE.md — 该放哪里?”这是新手最困惑的问题。两个文件 Claude 都会读,为什么要分开?
| 放 CLAUDE.md | 放 Memory |
|---|---|
| 每次会话都读 | 需要时按关键词触发 |
| 影响 Claude 的即时行为 | 提供背景知识和长期教训 |
| 短(1-2 句) | 可以写 Why 和完整场景 |
| “做什么” | “为什么这样做” |
以 “教学节奏” 规则为例:
CLAUDE.md 里写的(短规则):
- 教学节奏:学习类任务默认"小段讲解+即时一问+等回答",禁一次性丢多题Memory 里写的(完整背景):
学习类任务默认走"带学+提问"模式:1. 每轮讲一个小概念2. 讲完立刻问一个小题3. 等用户答完再讲下一段
Why:用户明确反馈过这个偏好(intern-journal 项目,OpenClaw Hook 学习 Step 9 时)"用带我学习然后提问的方式,而不是现在这种直接出题目"是原话。经验法则:
- 需要 Claude 每次启动都知道 的行为指令 → 放 CLAUDE.md
- 需要 Claude 在特定场景下查阅 的背景知识 → 放 Memory
- 规则本身 + 为什么有这条规则的历史 → CLAUDE.md 放规则,Memory 放 why
1. 记忆膨胀:把 A 层当万用抽屉
Section titled “1. 记忆膨胀:把 A 层当万用抽屉”最危险的趋势:每次学到新东西就往 A 层加。A 层始终加载,文件越多,每个会话的上下文就越多。如果 A 层从 13 个膨胀到 30 个,效果反而不如没有记忆系统——Claude 被大量不相关信息淹没了。
对策:加新记忆时先问自己 “这真的是任何任务都需要知道的吗?”。大多数新知识应该进 B 层或 C 层(按关键词触发)。
2. 忘记 grep 就加新规则
Section titled “2. 忘记 grep 就加新规则”不加 grep 就直接加新规则,等于在索引卡片柜里塞了一张可能跟已有卡片矛盾的卡片。几个月后 Claude 读到两条互相冲突的规则,它会遵循哪条?你不知道。
对策:把 “新事实出现时,先 grep 三个索引” 变成肌肉记忆。或者让 Claude 帮你做(在 CLAUDE.md 里写这条规则,Claude 自己就会执行)。
3. 只写不更新
Section titled “3. 只写不更新”记忆文件的创建只是一个开始。规则会过时、会需要补充例外、会因为技术栈变化而失效。如果永远只加新文件不回头更新旧文件,记忆系统会变成垃圾场。
信号:当你看到一条记忆规则想说 “但是现在不一定了吧?”,那就是该更新它的时候了。
4. 把 CLAUDE.md 和 Memory 混用
Section titled “4. 把 CLAUDE.md 和 Memory 混用”CLAUDE.md 里塞长篇解释(Why + 场景 + 例子),或者 Memory 里只写一句不写 why。前者浪费每次会话的 token,后者让 Memory 变成没有上下文的死规则。
对策:用上面的决策框架做判断。不确定的时候,默认放 Memory(信息更完整),CLAUDE.md 只放最简指令。
Checkpoint 练习
Section titled “Checkpoint 练习”当你读完这一章,试着做这个练习:
回想今天学到的一个教训。创建一个记忆文件,包含:
- 规则(一句话,Claude 应该遵守什么)
- Why(这条规则是怎么产生的——具体的对话场景、你踩了什么坑)
originSessionId(当前会话的 ID)- 判断它属于哪一层(A 层始终适用?B 层关键词触发?C 层项目专属?)
做完后,把文件注册到对应的 MEMORY.md 索引中。
- 继续 工作流编排思路 —— 理解了记忆系统后,看看怎么把它和其他工具串成完整工作流
- 回顾 CLAUDE.md 与记忆系统 —— 重新读一遍,现在你应该能理解 CLAUDE.md 和 Memory 的分工了
- 转到 Claude Code 上下文窗口管理 —— token 预算怎么分配,记忆占了多少
- 回 学习方法论