Memory Management
How to write into Claude Code's auto-memory and CLAUDE.md so the library stays searchable as the project grows.
Quick Reference
| User says... | Do this |
|---|---|
| "记一下"(模糊,多条候选)/"复盘"/"开发完了看有什么值得记的" | → Mode 1:候选评估(多候选筛选) |
| "记一下今天那个 X 坑"(具体单条)/ 重大 bug 修完后 / 安全事件处置完 / 单次决策有非显然结论 | → Mode 2:新建 memory(直接走) |
| "更新这个 memory / 修正 X 的结论" | → Mode 3:update 已有 memory(优先于新建) |
| 待加段超过 100 行或文件已 > 4 个 H2 主题 | → Rule 6:拆分而非 update |
| "改 schema / 加新 type / 改记忆结构" | → Mode 4:结构性变更(必读已踩坑清单) |
| "新项目零记忆起步" / "怎么开始" | → Mode 5:零记忆 bootstrap |
| "记忆系统看起来乱了 / audit" | → 项目根有 scripts/audit-memory.sh 则跑;无则参考 templates/audit-memory.template.sh 自建 |
Important Rules
Rule 1:事实进 memory,方法进 skill
memory file 装"踩过 X 坑"、"业界 Y 数据"、"项目 Z 状态";本 skill 装"如何决定记什么 / 怎么写 / 怎么组织"。不要把 schema 规范写到 memory 里(类别错误)。
Rule 2:先判断"是否值得记",再判断"记到哪"
不是每个发现都该记。决策树:
| 信号 | 该记吗 |
|---|---|
| 同样的坑踩了第 2 次 | ✅ 必记 |
| 对抗审查发现非显然的判断 | ✅ 记决策的"Why" |
| 业界对照 / 实测数字(可复用基线) | ✅ 记 |
| 一次性 debug 已修完无沉淀价值 | ❌ 不记(commit message 就够) |
| 临时状态会变化 | ⚠️ 看持续性,长期才记 |
| 低频但致命(半年没读但仍是唯一真相) | ✅ 留 —— 30 天未触 ≠ 过时;删的依据是「主题已消失/被取代」,不是「多久没读」 |
判断"记到哪" —— 触发就近性(locality)四级路由:
先问一个正交问题:「未来需要这条事实时,是正盯着某个具体代码位置,还是在做跨文件决策 / 排查某类报错?」
| 触发条件 | 去处 | 机制 |
|---|---|---|
| 盯某一行/块,WHY 一句话讲得清 | 行内代码注释(就在那行上方) | 改文件时 100% 撞见,0 索引成本 |
| 锁定一组具体文件的多点契约 / 检查清单 | .claude/rules/<x>.md + paths: frontmatter | 碰匹配路径自动注入 context |
| 触发是场景/报错/某类问题,或跨多文件,或不属于单个仓库文件(平台/SDK 坑) | memory(本系统) | description 命中 |
| 每个 session 都要守的规则(命令、技术栈、协作偏好) | CLAUDE.md | 常驻 |
绑某文件的 feedback 默认 SPLIT:文件局部内核 → 行内注释(写前先 grep 那段代码,往往已有等价注释);memory 只留「跨文件可复用的原则 + 指向该文件的指针」。
三条防过度迁移护栏(默认 memory,宁可少迁):
- 抽掉具体文件仍剩通用教训 → 留 memory(如「别拿 optional 字段做关键路径决策」,具体文件只是例子,原则可迁)
- 平台/SDK 行为跨多文件复现 → 留 memory,哪怕有代码含义
- 墓碑(X 已退役→看 Y)/ 调查 SOP / 业务经济推理 → 留 memory(触发在架构/场景层)
实证(一个 175 文件生产库的全量审计):仅 ~15% 条目绑单一文件,且其中多数文件内核早已在代码注释里 —— 「迁移」多半是删 memory 冗余副本,不是真搬运。
.claude/rules/*.md 写法(放项目 .claude/rules/,进 git → 跨机器/worktree 共享):
---
description: 一句话这条规则管什么
paths:
- src/components/SomeDialog.tsx
- src/lib/providers/*.ts # 支持 glob
---
碰到上面路径时自动注入的契约 / 检查清单正文(多点 gotcha)。
⚠️ 原生 rules 注入的已知边界(2026-07 核实,anthropics/claude-code issues):paths: 规则只在 Read 匹配文件时注入,Write/新建文件时不注入(#23478);用户级 ~/.claude/rules/ 的 paths: 被忽略,只有项目级生效(#21858)。「创建新文件时也必须生效」的契约要留在 CLAUDE.md,别只放 rules。
Rule 3:优先 update 已有,不新建
主题相关已有 file → update 该 file(加段或加 changelog 段)。主题完全正交才新建。新建会导致主题碎片化 → 找东西难 → 失忆。
Rule 4:memory 不自动加载,description 决定命中
topic file(memory/*.md)session 启动不加载,Claude 凭 MEMORY.md 索引里的 description 判断是否读。description 必须场景关键词 + 核心结论混合,否则 Claude 会凭印象决定读哪个。
原生机制核实(2026-07,官方 docs/en/memory):没有向量/语义自动召回 —— 发现全靠「MEMORY.md 索引行 + 文件名」,Claude 用 Read 按需读取;读取时 harness 会注入 "This memory is N days old" 时效提示。索引行 hook 的质量 = 命中率的全部,这是原生行为,不是本 skill 的约定。
Rule 5:skill 自身要符合 skill 教的规范
如果本 skill 让用户写 ## Why 段,本 skill 也应该解释自己每条规则的 Why(它们都在本文件 inline)。
Scope 注意:Rule 5 适用范围是"方法/写法/Quick Reference 形式等",不递归适用 schema 规则。Schema(命名/frontmatter/Why 段)是给 memory 文件的,不适用 skill 自身。Skill 不是 memory file。
Rule 6:何时拆分而非 update(防止单文件 / 单组超载)
Rule 3 优先 update,但有阈值。触发拆分的信号(单文件层):
| 信号 | 行动 |
|---|---|
| 已有 file > 100 行,且要加的新内容跟原主题正交 | 拆出新 file,不要塞 |
| 已有 file 已 ≥ 4 个 H2 顶层段,且新内容属于第 5 个独立主题 | 拆出新 file |
| 加段后总长度跨过 150 行 | 评估是否拆(看主题独立性) |
| 加的内容跟原 file 标题/description 不匹配 | 拆出新 file(原 file 应该专注其声明的主题) |
单组超载(索引层):
| 信号 | 行动 |
|---|---|
| MEMORY.md 某大组 entry 数 ≥ 15 | 考虑建 hub memory(段索引)替代扁平索引,新 entry 挂 hub |
| 一个组的 description 加起来扫一遍 > 25 行 | 同上 |
MEMORY.md > 23,000 字符(wc -m)或 > 190 行 | 🔴 原生硬限制 = 前 200 行 或 25K 字符,先到为准(官方 docs 措辞 "25KB",实测按 string length=字符执行:一份 27,972 字符/37.9KB 的索引恰在第 25,000 字符处截断,按字节应提前 ~35%)。超出部分静默不加载。⚠️ 别用 wc -c(字节)估算:中文 UTF-8 每字 3 字节,会高估 ~35% 余量。接近上限时 harness 会注入警告,见到 Only part of it was loaded = 已经在丢索引 |
| 单条索引行 > ~160 字符 | description 堆太多细节 → 移进 topic file 或下沉到代码注释,索引只留"场景词+核心结论" |
为什么单组超载也要管:Claude 凭 MEMORY.md 索引扫 description 命中,组内 20+ 条 description 凭一次扫描有遗漏率。建 hub 后,组索引只一行指向 hub,hub 内做主题地图。
为什么索引层整体最危险:单文件/单组超载只是"命中力下降";但索引整体被截断 = 末尾整条不加载 = 命中力归零,且静默无报错。所以 ⭐⭐⭐ 皇冠条目应放 MEMORY.md 靠顶部(抗截断保险)。
超限 / 过大时的瘦身优先级(压缩 description 是最差的第一招,自伤命中力):
- 先迁:文件局部条目 → 行内注释 /
.claude/rules(索引变小且命中率变高,见 Rule 2 四级路由) - 再删:真墓碑(主题已消失/被取代且无防复活价值的)
- 再排:把 ⭐⭐⭐ 挪到 MEMORY.md 靠顶部
- 再分级:索引行按重要性分预算 — 皇冠条目 ≤160 字符,普通条目 ≤110,长尾低频条目聚合成一行多链(
子主题 → [a](f1.md) · [b](f2.md),一行装 5-10 个文件)。另:链接 label 用去 type 前缀的短名([foo-bar](feedback_foo_bar.md)),别重复完整文件名,每行省 12-45 字符 - 最后才压缩单条 description 的信息量
历史踩坑案例(reference,非规则的一部分)
- 单文件超载:一个 reference 文件长到 130+ 行,塞了 7-8 个独立子主题(基础设施、cron 列表、故障手册等),MEMORY.md 索引描述概括不全,Claude 命中不了具体子主题。拆成 5 个独立 memory 后每个主题精准命中。
- 单组超载:某分组累积 20+ 条 entry,新 session Claude 扫索引时有遗漏,处理任务时重复造轮子。建一个 hub memory 聚合相关入口 → 解决。
- 索引层整体超载:MEMORY.md 涨到 43KB 字节(≈31K 字符,超 25K 字符上限),93 条 description 各 400-900 字符,启动时被静默截断,末尾 ⭐⭐⭐ 条目漏读 → 一次调查里把按设计运行的机制误判成漏洞。教训:description 不是越详细越好,过详细会撑爆索引反而害了命中。
- 字节/字符混淆的误校准:治理超载时把警告线按字节(
wc -c)设成 32KB,而 harness 按字符执行(中文每字 3 字节)→ 字节线让人以为还有余量,索引再次被截。教训:跟 harness 对表必须用同一单位,监控用wc -m。
Workflow Modes
Mode 1:候选评估(多候选,需要筛选)
触发场景(多条候选 → 需要 Mode 1 筛选):
- 功能开发完 / 长 debug 完 / 对抗审查完
- 反滥用处置完(可能多个判断点 + 教训)
- 安全事件处置完 / 故障定位完
- 用户说 "记一下"(模糊,未指明具体哪个坑)
单条具体内容直接走 Mode 2:用户说 "记一下今天那个 wildcard bug" / "记一下连接泄漏的故障手册" → 已经明确单条 → Mode 2 不要 Mode 1。
步骤:
- 回顾本次会话关键节点(用户校正、对抗审查发现、未预期 bug、业界对照查询、单次决策的非显然结论)
- 逐个套 Rule 2 决策树,筛出值得记的
- 对每个候选,判断:
- 是否已有 memory 文件覆盖?(grep MEMORY.md 索引)→ 有则走 Mode 3 update,无则走 Mode 2 新建
- 待加的内容是否超 Rule 6 拆分触发线?→ 拆出新 file
- 是否应该进 CLAUDE.md 而非 memory?(见下方表格)
- 跟用户确认清单:列出"建议新增 / 建议 update / 建议拆分"候选,等用户确认再写
memory vs CLAUDE.md 边界:
| 内容性质 | 放哪 |
|---|---|
| 学到的具体踩坑(SDK bug、平台限制、业界数据) | memory feedback_* |
| 主题深度参考 / 标准方法 / 流程文档 | memory reference_* |
| 状态性事实(进行中工作、临时配置、当前架构快照) | memory project_* |
| 每次 session 都要遵守的规则(命令、技术栈、协作偏好) | CLAUDE.md |
| 特定文件操作时才需要的规则 | .claude/rules/*.md 加 paths frontmatter |
Mode 2:新建 memory(标准流程)
步骤 0:先过触发就近性(Rule 2 四级路由)
写之前先确认它真该进 memory:盯单一文件 → 行内注释;一组文件的契约 → .claude/rules+paths;场景/跨文件/平台坑 → 才进 memory。绑文件的 feedback 默认 SPLIT(内核进注释,memory 只留跨切原则 + 指针)。详见 Rule 2。
步骤 1:确定 type
| Type | 何时用 | 必含信息 |
|---|---|---|
| feedback | 学到的踩坑(SDK bug / 平台限制 / 用户偏好) | 原因(为什么这个结论)+ 何时复用(触发场景) |
| reference | 主题深度参考 / 标准方法 / 业界对照 / 复用 pipeline | 不强制原因段(描述性) |
| project | 状态性事实(架构快照、进行中工作、经济学分析) | 不强制原因段(状态性) |
feedback 必含信息的呈现形式(任一即可):
- 单独段:
## Why或同义中文## 根因/## 原因/## 教训/## 为什么(audit 都接受) - 加粗行内:
**Why**:/**根因**:(短结论也可) - inline 在 description 或 ## 标题里(如果结论本身已经隐含原因 + 何时复用,如对比 ❌/✅ 表格)
何时复用信息:可以是单独 ## How to apply 段,也可以是 description 含场景关键词(如 tab 切换 / mutation 已经暗示触发场景)。
步骤 2:文件命名
<type>_<topic>[_<modifier>].md 全小写下划线:
- ✅
feedback_supabase_from_deadlock.md - ✅
reference_supabase_egress_favorites_refactor.md - ❌
feedback-supabase-deadlock.md(用了连字符) - ❌
FeedbackSupabaseDeadlock.md(驼峰) - ❌
_schema.md(下划线开头会被当隐藏文件,且 Claude 不会主动读)
步骤 3:写 frontmatter
---
name: kebab-case-slug
description: 场景关键词 + 核心结论
type: feedback | reference | project # 平铺(推荐)
# 或:
# metadata:
# type: feedback | reference | project # 嵌套(兼容写法)
---
type 字段位置:type: 平铺(推荐)或 metadata.type: 嵌套都接受。audit 脚本两种都识别。新建文件优先用平铺,跟现有多数对齐。
description 风格判定:
| ✅ 好 description | ❌ 坏 description |
|---|---|
浏览器端 supabase.from() mutation 在 tab 切换后死锁,必须用 fetch() 调 REST API | Supabase 相关问题 |
CF Image Transformations 失败 7 天缓存 / cf-resized err= / FavoriteCard retry pattern | 图片有时显示不出来 |
RLS 策略必须用 (SELECT auth.uid()) 包装,否则每行重复求值 | RLS 性能优化 |
判定标准:Claude 读 description 时能不能立刻知道"这是 X 场景下要查的 Y 结论"。
步骤 4:写正文
feedback 类(必含原因 + 何时复用):
# 标题(What — 一句话)
[核心结论 + 1-2 段背景]
## Why(或同义:## 根因 / ## 原因 / ## 教训 / ## 为什么)
[为什么是这个结论 — 踩过的具体坑、对抗审查发现、用户偏好]
**为什么必填**:没有原因段,下次重新讨论同一决策时往往会得出同一个错误结论。
## How to apply(可省略,如 description 已含场景关键词)
[何时复用这条 — 触发场景、检查清单、避坑步骤]
reference / project 类:不强制段结构,按主题自然组织即可。
步骤 5:加到 MEMORY.md 索引
- 选已有大组,不新建分组
- description 加到组内对应位置(高重要性用 ⭐⭐ / ⭐⭐⭐ 加粗)
- 跨主题:description 末尾加
(亦见 [[other-file]])
Mode 3:Update 已有 memory(优先于新建)
步骤 1:用 grep 确认现有主题归属
grep -l "<关键词>" memory/*.md
步骤 2:决定 update 方式
| 情况 | 怎么 update |
|---|---|
| 新数据 / 新案例补充已有结论 | 在正文加段或 changelog 段 |
| 已有结论被推翻 | 旧文件顶部加 ⚠️ Superseded by [[new-file-slug]],新文件正文写"取代 [[old]] 的什么部分" |
| 只是 description 描述不够清楚 | 改 MEMORY.md 索引,不改 file 本身(除非也加内容) |
步骤 3:同步 MEMORY.md
如果改了 description,MEMORY.md 对应行也要改。
Mode 4:结构性变更(改 schema / 加新 type / 改分组)
必读已踩过的坑清单:
- 不要尝试 hook
if: "Write(memory/*.md)"glob 语法 —if:是 permission rule 不是 file glob,已验证无效 - 不要用 exit 2 阻塞 hook — 已验证破坏 pre-deploy batch 流(Claude 没有自动重试机制)
- 不要把 schema 权威源放
_schema.md类下划线开头文件 — Claude 不主动读 topic file - 不要在项目
.claude/settings.json配 hook — 该目录通常在.gitignore里,不进 git 不跨 worktree - 加新必填字段时同步 3 处:(a) 本 skill 段 "Mode 2 → 步骤 3" (b) MEMORY.md 顶部速查精华段 (c) audit-memory.sh 脚本字段列表
- 修 hook / 加约束前先
bash scripts/audit-memory.sh看当前合规率 — <95% 才需要硬措施,≥95% 维持 soft warning - MEMORY.md 大小监控必须按字符(
wc -m)不是字节(wc -c) — 原生上限 200 行/25K 字符按字符计;中文每字 3 字节,按字节校准会导致静默截断(见 Rule 6 历史案例)
改 schema 流程:
- 跑 audit 拿当前基线
- 设计变更(改本 skill + 项目 hub)
- 验证现有 memory 是否大批违反新规(>10% → 暂缓,先按新规迁移)
- 更新 MEMORY.md 精华段同步
- 改 audit 脚本字段列表
- 复跑 audit 看新合规率
Mode 5:零记忆 bootstrap(新项目)
当用户在一个没有 memory 系统的项目说"开始建记忆":
步骤 1:确认 auto memory 目录路径
Claude Code 自动建 ~/.claude/projects/<project-slug>/memory/,其中 <project-slug> = 项目绝对路径将 / 替换为 -。例:
- 项目
/Users/alice/Project/myapp→ slug-Users-alice-Project-myapp
如果 Claude Code 已经为该项目自动创建过 auto memory,目录会存在。验证:ls ~/.claude/projects/ | grep <项目名>。
步骤 2:建 MEMORY.md 索引
顶部模板(可压缩到 ~25 行):
# <项目名> 项目记忆
## ⭐⭐⭐ 写 memory 速查(硬规则)
- 文件名:`<type>_<topic>.md` 全小写下划线;type ∈ {feedback, reference, project}
- 必填 frontmatter:name / description / type
- feedback 必须含 ## Why 段(或同义中文 ## 根因 / ## 教训 / ## 原因)
- description 风格:场景关键词 + 核心结论(单行 ≤160 字符)
- 同主题已有文件 → update,不新建(超 Rule 6 阈值则拆)
- 本索引硬上限:前 200 行 或 25K 字符(先到为准),超出静默不加载
- 详细方法:memory-management skill
## ⭐ 项目主题列表
(暂无 — 后续按主题增加分组)
步骤 3:分组演进阈值(按文件数决定结构)
| memory 文件数 | 推荐结构 |
|---|---|
| < 15 条 | flat list,无分组(单一列表足够,分组反而碎片化) |
| 15-25 条 | 引入 3-5 个大组(按主题聚合) |
| > 25 条 | 分组成熟,冻结分组禁止新建,新条目挂已有组(跨主题用 (亦见 X)) |
步骤 4:CLAUDE.md 顶部加 Memory 协议(3-5 行)
## Memory 管理
涉及 memory 写入 / 更新 / schema 调整时 → 使用 `memory-management` skill。
- 速查规则:MEMORY.md 顶部 ⭐⭐⭐ 段
- 体检合规率:`bash scripts/audit-memory.sh`(可选,见 skill templates/)
步骤 5:复用本 skill 通用方法
不要把 skill 内容复制到项目。skill 在用户级,所有项目共用一份方法。项目里只放项目特定状态(分组列表 / 待办 / 项目特有踩坑)。
Schema 规范(权威源)
文件命名
<type>_<topic>[_<modifier>].md 全小写下划线,type ∈ {feedback, reference, project}
必填 frontmatter
---
name: kebab-case-slug
description: 场景关键词 + 核心结论
type: feedback | reference | project # 平铺(推荐)
# 或:
# metadata:
# type: feedback | reference | project # 嵌套(兼容)
---
audit 脚本两种都识别。新建文件优先平铺。
feedback 必含信息
原因段(任一):
## Why或同义中文标题## 根因/## 教训/## 原因/## 为什么/## Root cause(可带英文:或中文:)- 加粗行内
**Why**:/**Why**:/**根因**:等
何时复用(任一):
- 单独
## How to apply段 - description 含场景关键词(隐含触发场景即可)
description 风格
混合(场景关键词 + 核心结论),让 Claude 凭 description 命中"X 场景查 Y 结论"。单行 ≤ ~160 字符 —— 细节进 topic file 或代码注释(索引硬上限 = 200 行/25,000 字符先到为准,超出静默不加载)
索引行格式
- [短标签](完整文件名.md) — hook。短标签 = 去 type 前缀的连字符名(如 [supabase-from-deadlock](feedback_supabase_from_deadlock.md));长尾低频条目用聚合行(子主题 → [a](f1.md) · [b](f2.md))
分组冻结
从已有大组选,禁止新建分组。归属模糊用 (亦见 hub-X) 跨引用。
Common Mistakes
| 错 | 对 |
|---|---|
| 凭印象写 description "Supabase 问题" | 写场景关键词 + 结论 "supabase.from() tab 切换死锁,用 fetch" |
| feedback 只写"是什么" | feedback 必带 ## Why,保护未来不重新质疑 |
| 同主题新建第二个文件 | 优先 update 已有,新建会碎片化 |
| 新建"网络问题"分组放 1 条 entry | 用已有分组,跨主题用 (亦见 X) |
| 把 schema 规范写到 memory file | schema 在本 skill,memory 装事实 |
| 用 hook exit 2 强制阻塞 | 用 soft warning(stderr + exit 0)或 audit 事后体检 |
Self-Check(写完后)
- 类型对吗(feedback/reference/project)?
- 文件名符合
<type>_<topic>.md全小写下划线? - frontmatter 3 字段齐(name / description / type)?
- feedback 类有原因段(
## Why或同义中文 / 加粗行内)? - description 含场景关键词 + 核心结论?
- 已加到 MEMORY.md 索引正确大组下?
- 没新建分组?(如果新建了,撤回放已有组)
- 跨主题加了
(亦见 X)提示? - Rule 6 检查:新 file < 100 行 + < 5 个 H2 段?(如果 update 已有 file 让它超阈值,改成拆出新 file)
- 触发就近性检查(Rule 2):这条绑某个具体文件吗?若是,文件局部 WHY 是否已/应在代码注释里、memory 只留跨切原则?
- 索引层检查:新增/改 description 后 MEMORY.md 仍 < 23,000 字符(
wc -m,不是字节!)且 < 190 行 + 单行 ≤ ~160 字符? - 触发力体检:列 3 个未来可能问到的场景关键词,模拟问"Claude 凭 description 会读这个 memory 吗?"(如果想象不出场景,description 不合格)
Tool Integration
audit 脚本是可选项目工具。
项目根有 scripts/audit-memory.sh → 跑:
bash scripts/audit-memory.sh # 看合规率 / 列违规 / 列 30 天未触
输出:总文件数 / 缺 frontmatter / 缺 Why / MEMORY.md 断链 / 30 天未触 / MEMORY.md 大小(字符+行,对照原生 200 行/25K 字符上限) / 合规率%。 目标合规率 ≥ 95%。
没有 audit 脚本 → 从模板自建:
# 用户级 skill 自带通用模板
cp ~/.claude/skills/memory-management/templates/audit-memory.template.sh \
<你的项目>/scripts/audit-memory.sh
# 修改 MEMORY_DIR 指向你项目的 auto memory 目录
chmod +x <你的项目>/scripts/audit-memory.sh
bash <你的项目>/scripts/audit-memory.sh
参考默认 auto memory 路径:~/.claude/projects/<project-slug>/memory/,见 Mode 5 步骤 1。