【笔记】Claude Code MEMORY 的索引与检索机制
Claude Code 的 auto memory 不是一份不断增长、每次完整塞进提示词的聊天摘要。它更像一个项目级的小型知识库:MEMORY.md 负责导航,topic files 保存正文,运行时按索引或相关性把材料带回上下文。
本文的公开行为依据 Claude Code 官方文档;自动提取、相关性预取、team memory 和 KAIROS 来自 2026-08-01 本地 harness 源码,其中多项受 feature flag 控制,不应视为所有发行版都启用的稳定能力。
1. 中心模型:索引、内容、召回、写入
flowchart LR
C[当前对话] --> W{值得长期记住?}
W -->|是| T[写入 topic file]
T --> I[更新 MEMORY.md 索引]
I --> S[新会话加载索引]
S --> Q[用户任务提供检索线索]
Q --> R[读取相关 topic file]
R --> V[验证是否仍然有效]
V --> C
四个角色不能混淆:
MEMORY.md是入口和索引;- topic file 是具体记忆内容;
- 召回机制决定本轮读哪些内容;
- 写入机制决定什么值得跨会话保存。
这个设计解决的是“上下文有限,但未来任务不可预测”的矛盾:入口必须短,正文可以分散,细节按需加载。
2. Auto memory 与 CLAUDE.md 不是同一层
2.1 CLAUDE.md 保存显式指令
项目中的 CLAUDE.md 通常随代码库维护,适合保存团队都应遵守的开发命令、结构说明和行为约束。CLAUDE.local.md 则适合个人且不提交的项目指令。
它们的共同点是:由人明确维护,内容本身就是希望 Claude 执行的上下文。
2.2 Auto memory 保存跨对话认知
auto memory 默认位于:
1
2
3
4
5
~/.claude/projects/<project-key>/memory/
├── MEMORY.md
├── user.md
├── feedback.md
└── project-context.md
它适合保存当前代码和 Git 历史无法直接推出、但未来协作仍有价值的信息,例如用户偏好、非显然的项目动机和外部系统入口。
2.3 两层会重叠,但不应重复
一条稳定的团队规则如果已经写进 CLAUDE.md,就不应继续作为 auto memory 重复维护。当前 harness 内置 /remember Skill,正是用来检查 auto memory 是否应晋升到 CLAUDE.md、留在私有层、更新或删除。
判断标准不是“哪一层更高级”,而是所有权:
- 仓库事实和团队规则由项目文档负责;
- 针对用户和长期协作的补充认知由 auto memory 负责;
- 短期任务状态留在当前会话或任务系统,不进入长期记忆。
3. 存储目录如何确定
3.1 默认按规范化仓库根隔离
当前源码优先寻找 canonical Git root,再生成项目键。这使同一仓库的多个 worktree 默认共享一套 auto memory,而不是每个 worktree 各建一份。
这符合语义:worktree 共享仓库历史,绝大多数长期项目认知也应共享。但若记忆记录的是某个 worktree 的临时现场,它本来就不适合进入 auto memory。
3.2 可以配置自定义目录
官方支持:
1
2
3
{
"autoMemoryDirectory": "~/my-memory-dir"
}
当前实现只接受绝对路径或安全的 ~/ 路径,并拒绝根目录、UNC、空字节等危险目标。更重要的是,源码刻意不从仓库内可提交的 project settings 接受这个目录覆盖,避免恶意仓库把自动写权限引向敏感目录。
3.3 Auto memory 默认启用,但有多层关闭条件
公开配置可按项目关闭:
1
2
3
{
"autoMemoryEnabled": false
}
当前实现还会在 --bare、显式禁用环境变量,以及缺少持久存储的特定 remote 场景关闭 auto memory。关闭不是只停止读取,也会阻止后台提取、整理和相关能力继续写入。
4. 为什么 MEMORY.md 只能做索引
4.1 启动上下文必须有硬上限
官方文档规定,启动时最多加载 MEMORY.md 的前 200 行或 25KB,超出部分不会进入上下文。YAML Front Matter 与 HTML 注释会在加载前剥离。
因此把长篇正文直接写进 MEMORY.md 会产生三个问题:
- 每次会话都支付无关 token;
- 后面的索引项可能被截断,变得不可发现;
- 更新不同主题时容易制造冲突和重复。
4.2 Topic file 承担正文
典型索引项应当很短:
1
- [测试偏好](feedback-testing.md) — 何时要求真实数据库而不是 mock
索引只提供“这里有什么”和“什么时候可能有用”。完整原因、适用边界和更新时间放在 topic file 中。
4.3 索引与正文是两步提交
写入新记忆时,需要同时满足:
- topic file 已创建或更新;
MEMORY.md有一条能帮助未来召回的指针。
只写正文没有入口,未来难以发现;只写索引没有正文,则变成空泛标签。
5. 什么值得保存
5.1 当前分类体系
当前 harness 将 auto memory 分成四类:
| 类型 | 保存内容 | 典型用途 |
|---|---|---|
user | 用户角色、目标、知识背景和偏好 | 调整解释和协作方式 |
feedback | 用户对工作方法的纠正或确认 | 避免重复犯错,延续有效判断 |
project | 代码之外的动机、责任人、期限和进行中决策 | 理解需求背后的约束 |
reference | 外部系统中权威信息的位置 | 知道去哪里获取最新事实 |
分类不是为了给文件贴标签,而是强迫写入者回答:未来在什么场景下,这条信息会改变行动?
5.2 不保存可现场推导的内容
当前提示明确排除:
- 代码结构、文件路径和实现模式;
- Git 历史和最近提交;
- 已经写在 CLAUDE.md 的内容;
- 调试步骤和修复配方;
- 当前任务的临时进度。
这些信息有更权威的事实源。复制到 memory 会迅速过时,还会让模型误把旧快照当成当前状态。
5.3 保存“为什么”和“何时使用”
高质量记忆不只记录结论,还要包含:
- 为什么这条信息重要;
- 哪类请求应触发它;
- 什么时候需要重新验证;
- 新事实出现后应更新还是删除。
没有触发条件的记忆很难召回,没有原因的规则则容易被机械套用。
6. 读取路径一:启动时加载索引
6.1 入口作为 memory file 加载
auto memory 启用且文件存在时,当前 getMemoryFiles 链路会把 MEMORY.md 标记为 AutoMem,与 global、project、local 等 CLAUDE.md 层共同组织进系统上下文。
运行时会明确标注它是“跨对话持久化的用户 auto-memory”,避免把它误认成仓库内项目指令。
6.2 启动加载不是全文召回
默认公开模型里,启动时加载的是受截断限制的 MEMORY.md,不是 memory 目录所有 topic files。topic file 仍需在任务相关时读取。
所以索引描述必须能够帮助模型判断“当前问题是否值得打开这个文件”,而不是只写一个模糊标题。
6.3 实验性相关性检索可能替代索引注入
当前 harness 还有 feature-gated 路径:开启相关性检索后,不再把 AutoMem/TeamMem 索引直接注入系统提示词,而是在每轮根据真实用户输入异步检索 topic files,并以 attachment 形式注入最多若干相关结果。
这条路径表明架构可以从“模型读索引后主动找文件”演进为“运行时先召回候选”。但它受内部 flag 控制,不能覆盖官方文档描述的默认行为。
7. 读取路径二:按任务召回 topic files
7.1 用户输入提供检索线索
相关性预取会跳过元消息,从最后一条真实用户输入提取线索。单个词通常不足以检索,过短输入会被跳过。
若用户显式 @ 提到某个有独立 memory 的 Agent,检索范围切到该 Agent 的目录;否则搜索当前项目 auto memory。
7.2 召回结果有去重与总量限制
当前实现会排除本轮已经读过、过去 attachment 已经注入的文件,并限制候选数与会话累计字节。单个文件也受行数和字节截断,截断时附带完整路径供模型继续读取。
这些限制说明 memory recall 是上下文预算分配,不是数据库查询结果越多越好。
7.3 预取不能阻塞主任务
相关性检索以异步 prefetch 启动。收集点只消费已经就绪的结果,未完成则跳过并在后续迭代重试,避免记忆搜索给每轮增加固定延迟。
因此“某条记忆存在”不等于“本轮一定召回”。关键规则仍不应只依赖自动相关性检索,稳定项目约束应该写入 CLAUDE.md。
8. 召回后必须验证漂移
Memory 表示“保存时认为成立的认知”,不是当前事实的权威副本。
若记忆提到具体文件、函数、flag 或运行状态,应在给出可行动建议前检查:
1
2
3
4
文件路径 → 检查是否存在
函数或 flag → 在当前源码 grep
近期仓库状态 → 读取代码或 git log
外部系统状态 → 查询当前权威来源
发生冲突时,应相信当前观测,并更新或删除过时记忆。把“记忆说 X 存在”直接写成“X 当前存在”,正是 memory 系统最危险的失败模式。
9. 写入路径一:主 Agent 直接保存
系统提示会告诉主 Agent 何时可以读写 memory。用户明确要求记住或忘记时,主 Agent可以在当前回合直接更新 topic file 和索引。
当前文件权限系统对受控 auto-memory 目录有专门识别,但这不表示任意路径都可静默写入。自定义目录来源、路径规范化和运行模式仍参与权限判断。
主 Agent 直接写入后,后台提取器会检测本段消息已有 memory write,并跳过同一范围,避免两个写入者重复保存。
10. 写入路径二:后台提取 Agent 兜底
10.1 它不是无条件运行
后台 extractMemories 同时受 auto memory 开关、feature gate、交互/远端模式和节流条件影响。因此不能把它描述成“每轮必然启动”。
10.2 它只看新消息窗口
提取器记录上次处理位置,只分析最近新增的模型可见消息。成功后才推进 cursor;失败则保留位置,留待下次重新考虑。
10.3 它是权限受限的 fork
后台 Agent 继承当前对话前缀,但工具集合被限制为:
- 读取、搜索和列举文件;
- 只读 Shell;
- 仅在 memory 目录内 Edit/Write;
- 不允许 MCP、再派生 Agent 或写能力 Shell。
它还有很小的 turn budget,目标是“批量读候选 → 批量更新”,不是重新调查和验证当前代码。
这意味着后台提取适合整理对话中已经明确出现的事实,不适合独立证明某个技术判断。
11. 助理模式与普通 auto memory 的区别
当前 KAIROS 助理模式采用另一种写入节奏:日常工作先追加到按日期组织的日志:
1
memory/logs/YYYY/MM/YYYY-MM-DD.md
再由独立的 dream/consolidation 流程把日志蒸馏成 topic files 和 MEMORY.md。这更适合持续运行的助理,因为实时维护索引容易产生高频冲突。
它仍复用 auto memory 目录,但“每日追加日志”是特定 feature 下的策略,不是普通 Claude Code 会话的通用 MEMORY.md 写入规则。
12. Team memory 与 Agent memory 是扩展层
12.1 Team memory
feature 开启后,团队目录可以拥有独立 MEMORY.md 和 topic files,并同步到组织范围。写入时需要在 private 与 team scope 之间选择,用户个人信息和敏感数据不应进入共享层。
12.2 Agent memory
自定义 Agent 可以声明自己的 memory scope。召回时按 Agent 隔离目录,避免一个专用 Agent 的经验无差别污染所有对话。
两者说明 memory 的真正抽象不是固定路径,而是“有明确所有者和召回边界的持久上下文”。
13. 一条记忆的生命周期
stateDiagram-v2
[*] --> Candidate: 对话中出现非显然信息
Candidate --> Rejected: 可由代码/Git推出或过于临时
Candidate --> Topic: 写入或更新 topic file
Topic --> Indexed: 更新 MEMORY.md 指针
Indexed --> Recalled: 新任务命中索引或相关性搜索
Recalled --> Verified: 对照当前事实核验
Verified --> Applied: 仍然有效
Verified --> Updated: 部分过时
Verified --> Deleted: 已失效或重复
Updated --> Indexed
Memory 的维护不是只增不减。保存、召回、验证、纠正和删除共同构成完整生命周期。
14. 复习索引
MEMORY.md是短索引,topic files 才是记忆正文;- CLAUDE.md 保存显式项目指令,auto memory 保存代码外的跨会话认知;
- 默认启动只加载受限索引,细节按需读;当前源码另有 feature-gated 相关性预取;
- 写入可以由主 Agent 直接完成,也可以由受限后台提取 Agent 兜底;
- 可从代码、Git 或权威系统重新取得的信息,不应复制成长期记忆;
- 召回只提供历史上下文,行动前仍需验证当前事实;
- KAIROS、team memory 和 Agent memory 是建立在同一抽象上的特殊作用域和写入策略。
15. 核验入口
- Claude Code 官方 Memory 文档:auto memory 的目录、开关和 200 行/25KB 限制;
src/memdir/paths.ts:启用条件、路径解析和 worktree 共享;src/memdir/memoryTypes.ts:四类记忆、排除项和召回后验证原则;src/utils/claudemd.ts:MEMORY.md 加载、截断与注入;src/utils/attachments.ts:feature-gated 相关性预取和 topic file attachment;src/services/extractMemories/:后台提取 Agent 的 cursor、权限和写入规则;src/services/autoDream/:助理模式日志蒸馏。