主题
深度解析 Claude Code 的 Memory 策略与演进路径
本文从上下文工程(Context Engineering)视角,系统拆解 Anthropic Claude Code 的 Memory 体系,并以"问题—方案—取舍—遗留"四要素叙事,回顾它从单文件 prompt 注入演进到分层 + 按需加载 + 压缩续接的完整路径。文中凡涉及未公开实现细节,均以
[推测]/[未公开]显式标注。
1. 概览:什么是 Claude Code 的 Memory
一句话定义
Claude Code 的 Memory,是一套以用户可读 Markdown 文件为载体、按"作用域 + 触发时机"分层注入到模型上下文窗口的持久化指令与事实集合——它既不是模型权重的一部分,也不是临时对话历史,而是介于两者之间的"工程化长期上下文层"。
与相关概念的边界
| 概念 | 是否持久化 | 是否进入每轮 prompt | 主要载体 | 与 Memory 的关系 |
|---|---|---|---|---|
| Context Window | 否 | 是 | 模型一次推理的 token 缓冲 | Memory 是其中"被显式预算的一段" |
| Session State | 部分(会话内) | 是 | 对话历史、TodoWrite、临时变量 | Memory 是 Session State 的"跨会话超集" |
| RAG | 否(按 query 检索) | 否(按需召回) | 向量库、外部检索器 | Memory 是"无需检索、默认在场"的高优先级前置上下文 |
| Persistent Memory(如 ChatGPT Memory) | 是 | 是 | 平台后端结构化存储 | Claude Code 走"文件 + Git 友好"路线,而非"黑盒后端" |
一句话区别:RAG 是"被检索的知识",Session State 是"当前对话的记忆",Memory 是"始终在场的契约"。
架构总览(Mermaid)
核心设计哲学可以一句话概括:"持久化的一切都落到文件、运行时的一切都按预算拼装、不确定的一切都隔离到子上下文"。
2. 当前 Memory 体系的完整拆解
下面按"作用 / 存储位置 / 生命周期 / 加载时机 / 写入方式 / 典型示例"六维度展开。
2.1 项目级记忆:CLAUDE.md / AGENTS.md
| 维度 | 描述 |
|---|---|
| 作用 | 承载项目特定的"协作契约":技术栈、目录约定、跑测试的命令、禁止事项、领域术语 |
| 存储位置 | 项目根目录 ./CLAUDE.md;新约定下也读 ./AGENTS.md(与 Cursor、Codex CLI 共享) |
| 生命周期 | 与代码仓库同寿,随 Git 版本化 |
| 加载时机 | CLI 启动时读入;/memory 编辑后会重新加载 [推测] |
| 写入方式 | 直接编辑文件;# 开头的 prompt 自动追加;/memory 命令打开编辑器 |
| 典型示例 | "本项目用 pnpm 而非 npm"、"提交前必须跑 make lint"、"不要修改 generated/ 目录" |
Why(为什么是 Markdown 文件而不是 JSON / YAML):Markdown 既被人读、又被模型读,且天然支持代码块、列表、链接,避免了"配置即代码即文档"三态分裂。Git diff 友好是关键的工程权衡。
Trade-off:纯文本无 schema → 容易写得啰嗦;不同团队的写法风格差异极大;模型对长 CLAUDE.md 有"前置预算挤占后续推理"的代价。
2.2 用户级记忆:~/.claude/CLAUDE.md
| 维度 | 描述 |
|---|---|
| 作用 | 跨项目的个人偏好:语言("始终用中文回答")、口吻、提交规范、常用工具偏好 |
| 存储位置 | ~/.claude/ 用户目录下的全局 Memory 文件 |
| 生命周期 | 与用户账户同寿 |
| 加载时机 | 任何项目启动 Claude Code 时都会加载,优先级低于项目级 [推测:当冲突时项目级覆盖] |
| 写入方式 | 手动编辑;# 写入时会被 Claude 询问"写到项目级还是用户级" |
| 典型示例 | "回答用中文"、"不要使用 emoji"、"喜欢函数式风格" |
Why(为什么要分用户级 / 项目级):避免把"我的口味"污染到团队仓库;同时把"团队规范"和"个人偏好"做出明确的归属边界。
2.3 子目录 / 模块级 Memory(嵌套合并)
| 维度 | 描述 |
|---|---|
| 作用 | 大型 monorepo 中,让"前端 / 后端 / infra"各自维护局部规范 |
| 存储位置 | 任意子目录下的 CLAUDE.md |
| 加载时机 | 当 Claude Code 在该子目录进行操作(读 / 写文件)时,按"由根向下"的顺序合并 [推测:实际可能是基于当前 cwd 或被操作文件路径触发的"按需上探 + 按需下探"] |
| 合并规则 | 后加载(更深层)的 Memory 追加到上层之后,遇到冲突时由模型自行根据"局部优先"语义裁决 [推测] |
| 典型示例 | frontend/CLAUDE.md:用 React + TypeScript;backend/CLAUDE.md:用 Go,禁止引入 ORM |
Trade-off:嵌套带来"加载顺序"和"覆盖语义"的复杂度。Anthropic 选择不引入显式 override 关键字,而是让模型自然处理冲突——这是典型的"用模型能力换工程复杂度"的取舍。
2.4 会话级记忆:对话历史、TodoWrite、临时上下文
| 维度 | 描述 |
|---|---|
| 作用 | 保留当前会话上下文:用户消息、模型回复、工具调用结果、TodoWrite 列表 |
| 存储位置 | 进程内(CLI)或服务端会话存储(Cloud Agent) |
| 生命周期 | 单次会话;CLI 退出即销毁(除非通过 --resume/会话恢复机制 [推测有此能力] 重连) |
| 加载时机 | 每轮推理整体前置 |
| 写入方式 | 对话过程自动累加;TodoWrite 工具显式管理任务列表 |
| 典型示例 | 用户上一条说"先重构再加测试",模型记住后续 5 轮内自动遵守 |
TodoWrite 的特殊地位:它是 Anthropic 把"任务规划"从"对话散文"中提取出来的结构化层,效果类似于"模型自己给自己写的、不会被压缩掉的便签"。在长任务中显著缓解了"模型走着走着忘了原始目标"的问题。
2.5 工具级 Memory:MCP / Skills / Hooks 协同
这一层是 Claude Code 近年最大的演进,把"记忆"从"被动文档"升级为"可执行能力 + 触发式上下文"。
Skills(SKILL.md)
- 本质:磁盘上的
SKILL.md文件,包含"何时使用 + 详细操作指南"两段。 - 加载策略:默认只把所有 Skill 的"何时使用"摘要注入 prompt,模型判断需要时再用 Read 工具读取完整 SKILL.md。这是典型的两阶段加载。
- Why:避免上百个 SKILL 全文塞进 context 浪费 token;同时保留"模型自主决策"的弹性。
- Trade-off:模型必须能正确识别触发条件——这对 SKILL 的 description 写作质量提出了很高要求。
MCP(Model Context Protocol)
- 本质:标准化的"外部工具/资源"对接协议。Memory 维度上,MCP 服务器可以暴露
resources,被模型按 URI 拉取。 - 与 Memory 的关系:MCP 资源是**"按需的、外部托管的 Memory"**,与 CLAUDE.md 的"始终在场的本地 Memory"形成互补。
Hooks
- 本质:事件驱动脚本(如
PreToolUse、PostToolUse、UserPromptSubmit),可往上下文里注入文本或阻断操作。 - 与 Memory 的关系:Hooks 提供"动态、上下文敏感"的记忆——例如
UserPromptSubmit时自动注入当前 git 分支和 PR 状态。它是**"运行时计算出来的 Memory"**,弥补了静态文件的不足。
2.6 长期记忆与外部知识:/memory 与 # 快捷写入
| 入口 | 行为 | 设计意图 |
|---|---|---|
/memory | 打开 $EDITOR,让用户直接修改 CLAUDE.md(询问层级) | 高频维护时的低摩擦入口 |
# 前缀 | 用户输入 # 以后所有 SQL 都用 snake_case,Claude 询问写入哪个 Memory,确认后追加 | "对话即配置",把零散偏好沉淀到文件 |
Why(为什么要有两种入口):/memory 适合"系统化整理",# 适合"边聊边沉淀"。两者覆盖了不同的心流场景——这是从纯 IDE 配置工具向"会话式 IDE"演进的关键产品决策。
未在 Memory 内但相关:Claude Code 不内置向量化的长期记忆 [截至公开信息],跨会话事实主要靠 Markdown 文件 + Git;如果需要"语义化召回",要走 MCP 接外部向量库。
3. 演进时间线(核心章节)
下面以"问题—方案—取舍—遗留"四要素叙事,复盘 Claude Code Memory 体系的迭代路径。部分阶段的时间顺序是基于公开信息的逻辑重建,并非严格的版本号时间线 [推测]。
【阶段 1】纯 Prompt 注入:无持久化记忆
- 痛点:早期 Claude API 用法只能在每次请求里手写 system prompt;用户每开一个新会话都要"重新教 Claude"项目背景,认知负担大、复用差。
- 方案:CLI 提供命令行参数 / 环境变量,把若干"通用指令"塞到 system prompt。本质是**"无 Memory"**——一切都依赖会话内对话或调用方手写。
- 取舍:实现极简、可控性最强;但完全没有跨会话传承,团队协作时每个人都要"私藏一份 prompt"。
- 遗留问题:用户开始把 prompt 存为文件、互相复制;事实上的"野生 CLAUDE.md"在社区里出现,倒逼官方收口。
【阶段 2】单文件 CLAUDE.md:项目记忆诞生
- 痛点:野生 prompt 文件命名混乱、加载方式各异、无法被官方 CLI 自动识别。
- 方案:约定俗成
CLAUDE.md作为项目根的官方 Memory 文件,CLI 启动时自动加载到 system prompt 之后。用文件名约定代替配置项——零配置、Git 友好、对人和模型双重可读。- 取舍:优雅但作用域只有一层——大型 monorepo 中根目录的 CLAUDE.md 会变成"什么都往里塞"的垃圾桶;不同模块的规范打架。
- 遗留问题:需要分层;同时"是否应该把个人偏好也写进项目 CLAUDE.md"成为新的争议。
【阶段 3】分层记忆:用户级 + 项目级 + 子目录级
- 痛点:阶段 2 的单层文件无法区分"团队约定"和"个人口味";monorepo 子模块差异无处安放。
- 方案:引入三层 Memory:
~/.claude/CLAUDE.md(用户级,跨项目)./CLAUDE.md(项目级,进入仓库)- 子目录
CLAUDE.md(模块级,按 cwd / 操作路径动态加载)- 关键设计决策:不引入显式优先级关键字,让"路径越深 = 越具体 = 隐式优先"作为约定,把冲突解决交给模型。
- 取舍:心智模型清晰、扩展性强;代价是调试困难——当出现"模型为什么不按我说的做"时,用户可能要排查多层文件;同时Token 占用变大,长 monorepo 下三层叠加可能吃掉数千 token。
- 遗留问题:用户编辑 Memory 的摩擦依然高(要主动
vim),且没有"边对话边沉淀"的入口。
【阶段 4】快捷写入与 /memory 命令:把"沉淀"变成对话动作
- 痛点:阶段 3 的 Memory 文件需要用户主动跳出对话去维护,违反心流。许多临时偏好("以后用 pytest 而不是 unittest")说完即忘。
- 方案:
#前缀:用户在对话中以# ...开头输入,Claude 识别为"沉淀指令",追问"写到项目级还是用户级",确认后追加。/memory:斜杠命令直接打开编辑器,结构化整理。- 关键设计决策:写入需要二次确认——避免模型误把普通对话当成 Memory 写入,保证"用户始终是 Memory 的最终所有人"。
- 取舍:交互摩擦显著降低;但
#触发依赖用户记住语法,新用户发现成本高;且模型解读"是否该追问"本身有错误率。- 遗留问题:Memory 越积越多 → 上下文预算紧张;且不同用户的 Memory 写作质量参差,模型表现不稳定。
【阶段 5】Skills / Subagents / Hooks 协同:从"被动文档"到"按需能力"
- 痛点:阶段 4 的 Memory 都是"全量前置注入"——一段写给"做 React 时怎么办"的指令,在"写 SQL"时也白白占用 token;同时复杂任务(如 PR 审查)希望走"独立子流程",不污染主上下文。
- 方案:
- Skills:
SKILL.md文件 + 两阶段加载:默认只注入 description,模型自主决定是否 Read 完整内容。把 Memory 从"始终在场"升级为"按需召回"。- Subagents:派生独立子上下文执行子任务,结果以摘要形式回传父上下文。子上下文不继承父级的对话历史——这是用"上下文隔离"换取"长任务下的认知聚焦"。
- Hooks:事件驱动注入(如
UserPromptSubmit钩子可以注入当前 git 状态、CI 失败信息)——这是**"运行时计算的 Memory"**。- 关键设计决策:Memory 的语义从"文档"扩展到"可执行 + 可触发"。CLAUDE.md 仍然存在,但只承担"高频、跨任务、无法计算"的契约层,其余下放给 Skills/Hooks。
- 取舍:架构复杂度陡增(用户要理解四种机制:CLAUDE.md / Skill / Subagent / Hook 各自的边界);description 写作质量直接决定 Skill 是否被正确触发。
- 遗留问题:长会话下,即便每段 Memory 都很精简,对话历史本身也会增长到接近上下文上限,必须解决"会话续接"问题。
【阶段 6】上下文压缩(Auto-Compact)与会话续接
- 痛点:长任务(数小时连续对话、数十次工具调用)下,对话历史本身变成最大的 token 消耗者;接近上下文上限时模型会"忘头"。
- 方案:Auto-Compact——当 token 预算接近阈值时,CLI 自动用模型对早期历史做摘要,把摘要替换原文。Memory(CLAUDE.md 等持久层)不参与压缩,始终原样保留——这是关键的优先级设计。
- 关键设计决策:
- 持久化 Memory 优先级最高:宁可压缩对话,也不动 CLAUDE.md。
- TodoWrite 内容受保护 [推测]:任务规划结构化数据要避免被摘要稀释。
- 压缩对用户可见:UI 提示"已压缩",避免模型行为变化让用户困惑。
- 取舍:会话寿命大幅延长;但摘要必然丢失细节,**长会话末期模型对早期细节的"模糊化"**是无法消除的副作用。
- 遗留问题:单机会话仍然受"进程生命周期"限制;CI / 远程协作场景需要会话能跨设备续接。
【阶段 7】跨会话 / 跨设备:Cloud Agent 与会话恢复
- 痛点:CLI 退出 = 会话消失;想从笔记本切换到云端继续任务很难。
- 方案:Anthropic 推出 Cloud Agent / 会话恢复能力 [部分公开],把会话 State 持久化到服务端,可以跨设备恢复。
- 与本地 Memory 的关系:Cloud Agent 启动时仍然读取项目仓库内的 CLAUDE.md / AGENTS.md,Memory 文件依然是真理之源——云端只补齐"会话历史 + TodoWrite + 工具调用结果"。
- 取舍:协作 / 移动场景大幅改善;带来隐私和数据所有权的新问题(哪些上下文被持久化到云端?)。
- 遗留问题:Memory 仍然是"文本 + 文件",缺乏语义化召回和结构化关系,对超大型仓库(百万行代码)的"长期事实积累"还是手工活。
【阶段 8 · 推测】未来方向:向量化 / 结构化记忆图谱 / 多 Agent 共享
- 可能演进路径:
- 本地向量化 Memory:把历史会话、提交记录索引化,按 query 动态召回相关片段,缓解"CLAUDE.md 越写越长"的问题。
- 结构化记忆图谱:把"约定 / 决策 / 实体"抽成节点—关系(类似 ADR + 知识图谱),让模型不仅"读到",还能"推理"。
- 多 Agent 共享 Memory:当 CLAUDE.md 被多个 Agent(Claude Code / Cursor / Codex)共同读取(即
AGENTS.md趋势),是否会出现"agent-neutral memory schema"标准。- Memory 可观测性:让用户能看到"模型这一轮用了哪些 Memory 段、在做决策时引用了哪条规则",把"黑盒上下文"变成"白盒审计"。
- 上述均为 [推测],作为产品和研究的开放方向。
4. 关键设计原则提炼
从七个阶段的演进中,我归纳出五条可复用的设计原则:
"持久化的一切都落到文件,运行时的一切都按预算拼装"
- Memory 不走云端黑盒,走 Markdown + Git;这保证了可审计、可版本化、可团队协作。
- 运行时再按"作用域 + 触发条件"动态拼装,避免一次性塞爆 context。
"显式优于隐式,但默认要够智能"
#前缀写入要追问"哪一层",强制用户做出归属选择 → 显式。- 但子目录 Memory 的合并不需要写
extends:、override:→ 隐式约定,靠路径深度作为优先级 → 默认够用。 - 反例(错误的设计):要求用户写 YAML 配置 + 优先级数字。
"Memory 优先级永远高于对话历史"
- Auto-Compact 砍对话不砍 CLAUDE.md。
- 这是一种**"契约 > 临时叙述"**的价值排序,避免长会话漂移。
"用上下文隔离换长任务的认知聚焦"
- Subagent / Skill 两阶段加载 / Hooks 都是同一思想:不要让 Agent 一次性记住所有事情。
- 这与人类认知一致:复杂任务要分模块、分会话、分笔记。
"Memory 的载体必须人和模型双重可读"
- Markdown 既是配置又是文档;写 Memory = 写团队规范 = 提交可 review。
- 反例:JSON / 二进制格式 / 平台后端的"用户记忆"——人无法 review,模型也无法直接编辑。
5. 与同类产品的横向对比
| 维度 | Claude Code | Cursor | Codex CLI | Cline |
|---|---|---|---|---|
| 项目记忆载体 | CLAUDE.md(也读 AGENTS.md) | .cursor/rules/*.mdc + AGENTS.md(多文件 + frontmatter 控制 globs/alwaysApply) | AGENTS.md(与 Claude / Cursor 共享约定) | .clinerules/(多文件,类似 Cursor) |
| 全局记忆 | ~/.claude/CLAUDE.md | 用户级 Rules(IDE 设置) | ~/.codex/AGENTS.md 等 [推测路径,以官方为准] | 用户级 rules 目录 |
| 写入触发方式 | # 前缀 + /memory 命令 | 手动编辑 .mdc,或在对话中让 Cursor 帮忙生成 rule | 手动编辑 AGENTS.md | 手动编辑 .clinerules |
| 作用域控制 | 文件路径深度(隐式) | frontmatter 显式 globs / alwaysApply / agentRequested | 路径约定 [推测] | frontmatter / 路径约定 |
| 上下文压缩 | Auto-Compact(自动摘要早期历史) | 自动摘要 + 用户可见的 Pin/Unpin(细节因版本而异) | 类似自动压缩(细节 [未公开]) | 自动摘要 |
| 跨会话续接 | CLI 会话恢复 + Cloud Agent | IDE 会话内置(IDE 进程内) | CLI session [推测有] | IDE 会话 |
| 按需能力机制 | Skills(SKILL.md,两阶段加载) | Custom Modes / @-mentions / Rules 的 description 字段 | [未公开等价物] | Custom Instructions / MCP |
| 多 Agent 协作 | Subagents(独立 context) | Background Agents、Bugbot | [未公开] | 单 Agent 为主 |
核心差异点解读:
- Cursor 走的是"显式 schema 化 rule"路线(frontmatter + 多文件),适合工程化深度配置;
- Claude Code 走的是"约定 + 文件名 + 模型自主裁决"路线,更轻量、更容易上手;
- 三家都在收敛到
AGENTS.md的事实标准,意味着未来 Memory 文件可能跨 Agent 复用。
6. 落地启示:从 Claude Code 中可借鉴的 5 条工程实践
如果你要为自己的 Coding Agent 设计 Memory 系统,下面是可以直接抄作业的 5 条:
启示 1:用文件名约定 + Markdown 作为 Memory 载体
- 推荐文件名:直接复用
AGENTS.md这一新兴标准(Claude / Cursor / Codex 都识别),同时兼容自己专属的<YOURAGENT>.md。 - 加载顺序(强烈建议):
~/.<youragent>/AGENTS.md(用户级,先加载,优先级最低)- 项目根
./AGENTS.md(覆盖用户级冲突项) - 当前操作路径上溯到根的所有
AGENTS.md,由浅到深依次追加(深的在后,模型天然倾向于"最近上下文")
- 冲突解决:不引入 override 关键字,让模型按"路径越深越具体"的常识裁决。
启示 2:把 Memory 写入做成"对话动作",但需要二次确认
- 复刻
#前缀语义:用户说# 以后用 ruff 而不是 flake8,Agent 识别后追问"写入用户级还是项目级 Memory?",确认后追加到对应文件。 - 关键约束:永不未经用户确认就修改 Memory 文件——Memory 必须是"用户授权"的契约,不是模型偷偷记下的事实。
启示 3:Memory 在压缩时享有最高优先级
- 实现 Auto-Compact 时,按以下优先级排队:
System Prompt > 持久化 Memory > 当前 TodoWrite > 最近 N 轮对话 > 早期对话(可摘要) - 当 token 接近上限时,只摘要最早期的对话,永远保持 Memory 段原样。
启示 4:把"按需能力"和"前置 Memory"分开存放
- 借鉴 Skills 的两阶段加载:
AGENTS.md只放"始终在场的契约"(短、稳定、跨任务)。- 任务相关的详细 SOP 放在
skills/<name>/SKILL.md,默认只注入 description,模型按需 Read。
- 这能把 Memory 段控制在 1-2K token 内,避免"上下文越用越胖"。
启示 5:复杂任务派生 Subagent,结果以摘要回传
- 长任务(如代码审查、批量重构)派生独立子上下文,只把任务描述 + 必要文件路径传入,不继承父级对话历史。
- 子任务完成后,强制要求"输出一段结构化摘要",由父 Agent 决定是否进一步处理。
- 这是用架构隔离而非"prompt 提醒"来对抗长任务的认知漂移,效果更稳定。
7. 参考资料
注:以下链接为公开信息入口,建议读者按当前版本以官方文档为准;社区文章用于补充推测性内容,标注 [社区]。
- Anthropic 官方文档:Claude Code 主页与 Memory / Settings 章节(
docs.anthropic.com下 Claude Code 部分) - Anthropic 官方博客:关于 Skills、Subagents、Cloud Agents 的发布说明
- Claude Code CHANGELOG(GitHub
anthropics/claude-code仓库的 releases / CHANGELOG) AGENTS.md公开提案(agents.md 站点 / 各大 Agent 厂商的兼容声明)- Model Context Protocol 官方规范(
modelcontextprotocol.io) - [社区] 各类对 Claude Code 的逆向分析与实战总结(GitHub awesome-claude-code 类整理、个人博客)
- 横向对比:Cursor 文档(Rules、Custom Modes、AGENTS.md 兼容说明)、Codex CLI README、Cline 文档
总结一句话:Claude Code 的 Memory 不是单一机制,而是**"持久层(文件) + 运行层(按需拼装) + 隔离层(Subagent)"三层结构逐步演进的结果。它的核心创新不在于发明了某个新概念,而在于坚持用最简单的工程原语(Markdown 文件、路径约定、二次确认)解决最复杂的上下文管理问题**,并把决策权稳稳地留在用户手中。这一思路,比任何具体的 API 都更值得借鉴。