Claude Code SDK #17:Memory 与 CLAUDE.md 全解——两套机制 × 四层作用域 × 路径级按需加载,让 Claude 跨 session 记住一切

Claude Code SDK #17:Memory 与 CLAUDE.md 全解——两套机制 × 四层作用域 × 路径级按需加载,让 Claude 跨 session 记住一切

每次新 session Claude 都从零记忆出发,CLAUDE.md 和 Auto Memory 是解决这个问题的两套互补机制。本篇完整拆解四层作用域(Managed/User/Project/Local)与加载顺序、`.claude/rules/` 的路径级按需加载如何省 token、Auto Memory 的存储结构与懒加载设计、企业 Managed 层部署与 claudeMdExcludes 策略,以及「/compact 后规则消失」等三个高频调试坑,附五条可落地的实践建议。

Claude Code SDK 每日技术拆解
2026/6/10 · 9:11
3 订阅 · 51 内容
每次启动新 session,Claude 的上下文都从零开始。你可能已经无数次打出同样的话:「用 2-space 缩进」「测试命令是 npm run test:unit」「别直接往 main 分支推」。
这不是你的问题,是机制问题——而 Claude Code 提供了专门解决这个问题的两套系统:CLAUDE.md 文件Auto Memory。本篇完整拆解这套记忆体系的加载逻辑、作用域层级、路径级按需规则、企业部署,以及「/compact 后指令消失」等高频调试坑,附五条可落地的实践建议。

两套机制,互补而非替代

理解这套体系的第一步,是搞清楚 CLAUDE.md 和 Auto Memory 是两种不同性质的机制,不要混用1
CLAUDE.mdAuto Memory
由谁写开发者手动写Claude 自动记录
内容类型项目规范、工作流程、架构约定构建命令、调试经验、Claude 观察到的偏好
作用域项目 / 用户 / 组织级单仓库,跨 worktree 共享
加载方式每次 session 全量注入上下文每次 session 加载前 200 行或 25KB
最适合你想主动控制的规则与约定让 Claude 从使用中学习、减少重复纠正
两套机制并行工作,都在每次 session 启动时加载。但有一点要记住:无论哪套机制,内容进入的是上下文窗口,不是强制执行层。想要无条件拦截某个工具调用,应该用 Hooks 的 PreToolUse 而不是在 CLAUDE.md 里写「禁止执行 rm -rf」。
深色终端上的代码,展示 Claude Code 上下文注入后的工作环境
深色终端上的代码,展示 Claude Code 上下文注入后的工作环境

CLAUDE.md 的四层作用域

CLAUDE.md 文件可以放在四个不同位置,每个位置对应不同的作用范围1
层级路径作用范围典型用途
Managed 层macOS: /Library/Application Support/ClaudeCode/CLAUDE.md / Linux: /etc/claude-code/CLAUDE.md机器上所有用户、所有项目公司编码规范、合规要求(IT 通过 MDM/Ansible 分发)
User 层~/.claude/CLAUDE.md当前用户的所有项目个人代码风格偏好、常用工具快捷方式
Project 层./CLAUDE.md./.claude/CLAUDE.md当前项目(通过版本控制与团队共享)项目架构、测试命令、命名约定
Local 层./CLAUDE.local.md(加入 .gitignore仅当前用户、当前项目本地 sandbox URL、个人测试数据
加载顺序:从文件系统根目录向工作目录方向逐层加载,范围越广的文件越先被读入上下文。也就是说,./CLAUDE.md~/.claude/CLAUDE.md 之后进入上下文,项目级指令优先级更高。
如果在 foo/bar/ 目录下启动 Claude,它会加载:foo/CLAUDE.mdfoo/bar/CLAUDE.md → 各层对应的 CLAUDE.local.md,全部拼接进上下文(不是覆盖)。
子目录懒加载:CLAUDE.md 只有在 Claude 实际读取对应子目录中的文件时,才会加载该子目录下的 CLAUDE.md。这是一个重要的 token 节省机制。

.claude/rules/ 做路径级按需加载

当项目变大,把所有规则堆进一个 CLAUDE.md 会遇到两个问题:文件超过 200 行后遵循度下降;大量与当前任务无关的规则占据 token。
.claude/rules/ 目录解决了这个问题:把规则拆成多个 .md 文件,每个文件可以声明只在操作特定路径下的文件时才加载1
your-project/
├── .claude/
│   ├── CLAUDE.md         # 全局主指令
│   └── rules/
│       ├── code-style.md # 始终加载(无 paths 声明)
│       ├── testing.md    # 始终加载
│       └── api-design.md # 只有操作 API 文件时才加载
声明路径绑定只需要在 .md 文件头部加 YAML frontmatter:
---
paths:
  - "src/api/**/*.ts"
  - "src/api/**/*.tsx"
---
# API 开发规范
- 所有 API endpoint 必须包含输入验证
- 使用标准错误响应格式(见 src/lib/errors.ts)
- 必须包含 OpenAPI 注释
当 Claude 读取 src/api/users.ts 时,这份规则才会进入上下文;操作 src/components/Button.tsx 时不会加载。
对于个人偏好,~/.claude/rules/ 下的文件在所有项目中生效——优先级低于项目级 rules,但高于 managed 层之外的全局默认。
带语法高亮的代码文件,演示路径规则如何按文件类型触发加载
带语法高亮的代码文件,演示路径规则如何按文件类型触发加载

Auto Memory:Claude 自己做笔记

Auto Memory 是 Claude Code v2.1.59 引入的机制,默认开启1
每个项目的自动记忆存储在:
~/.claude/projects/<project-hash>/memory/
├── MEMORY.md           # 入口索引(每次 session 加载前 200 行或 25KB)
├── debugging.md        # Claude 整理出的调试经验
├── api-conventions.md  # Claude 观察到的 API 约定
└── ...                 # 其他主题文件(按需创建)
MEMORY.md 是一份索引,记录「去哪里找什么」。细节内容放在主题文件里,不在 session 启动时加载,而是 Claude 认为需要时通过文件工具按需读取。
这套设计背后的逻辑:每次 session 全量注入所有记忆的 token 成本太高;只注入索引,细节懒加载,兼顾了完整性和 token 效率。
同一 git 仓库的所有 worktree 共享一份 Auto Memory(路径由 git repo 根目录计算得出)。跨机器不同步——Auto Memory 是机器本地的。
关闭 Auto Memory:
{
  "autoMemoryEnabled": false
}
或设置环境变量 CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
代码编辑器中的 JavaScript 文件,对应 Auto Memory 存储的技术上下文
代码编辑器中的 JavaScript 文件,对应 Auto Memory 存储的技术上下文

企业部署场景

Managed CLAUDE.md 部署在固定路径(macOS 为 /Library/Application Support/ClaudeCode/CLAUDE.md),由 IT 通过 MDM/Ansible 推送,覆盖该机器上所有用户的 Claude 会话,且无法被 claudeMdExcludes 排除1
还可以直接把 CLAUDE.md 内容内联进 managed-settings.json
{
  "claudeMd": "提交前始终运行 `make lint`。\n禁止直接推送到 main 分支。"
}
Managed 层 vs Settings 层的分工
要控制的事情配置位置
限制特定工具、命令、文件路径managed-settings.jsonpermissions.deny
强制沙箱隔离managed-settings.jsonsandbox.enabled
代码风格、合规提示、行为指令Managed CLAUDE.md
关键区别:settings 里的权限规则是客户端强制执行的;CLAUDE.md 是上下文约束,Claude 会尽力遵循,但不能像 deny 规则一样保证拦截。
大型 Monorepo 中排除其他团队的 CLAUDE.md
{
  "claudeMdExcludes": [
    "**/monorepo/CLAUDE.md",
    "/home/user/monorepo/other-team/.claude/rules/**"
  ]
}
加入 .claude/settings.local.json 使排除只在本机生效。

三个高频调试坑

坑一:Claude 不遵循 CLAUDE.md 里的规则
原因通常是:文件没被加载、规则太模糊、不同文件中存在冲突指令。
先运行 /memory 命令,查看当前 session 实际加载了哪些文件。如果你的 CLAUDE.md 不在列表里,说明路径不对或不在加载层级内。
规则模糊度也很关键:「好好格式化代码」对 Claude 没有足够约束力;「使用 2-space 缩进,函数间留一个空行」才是可操作的指令。
如果规则必须在特定生命周期时间点执行(比如每次提交前运行 linter),应该写成 Hook 而不是 CLAUDE.md 指令。
坑二:/compact 后 Claude 忘记了项目规则
/compact 后,工作目录的 CLAUDE.md 会重新从磁盘读取并注入——这部分不会丢失
但子目录下的 CLAUDE.md 不会自动重新注入,要等 Claude 下次读取对应目录的文件时才重新加载。如果某条重要规则只在对话里给出、没有写进 CLAUDE.md 文件,compact 后它就丢失了。
解决方案:规则写文件,不写对话1
坑三:CLAUDE.md 越写越大,遵循度下降
超过 200 行的单个 CLAUDE.md 文件会消耗大量上下文,且 Claude 对后部分的遵循度明显下降(上下文中越靠后的内容越容易被忽略)。
@path/to/file 语法把内容拆分成多个文件并不能缓解这个问题,因为被 @ 导入的文件仍然在 session 启动时全量注入。真正的解法是用 .claude/rules/paths frontmatter,让规则只在需要时加载。

五条实践建议

1. 用 /init 生成起步文件,再手动精炼 /init 命令让 Claude 自动分析当前代码库,生成包含构建命令、测试方法和项目约定的初始 CLAUDE.md。设置 CLAUDE_CODE_NEW_INIT=1 启用多阶段交互式流程,能进一步定制要生成的 Skills 和 Hooks。初始文件生成后,删掉 Claude 能从代码里自己推断的内容,只保留它靠静态分析无法得知的规则。
2. 「触发第二次犯同样错误时才写进 CLAUDE.md」 第一次纠正可以当作上下文给出;如果同一个错误在下次 session 再次出现,这就是该写进 CLAUDE.md 的信号。这个原则防止 CLAUDE.md 过早膨胀。
3. 按「是否所有上下文下都需要」决定放全局还是 rules/ 「所有 API 文件使用标准错误格式」→ 放进 rules/api-design.mdpaths: ["src/api/**/*.ts"]。「所有文件都用 2-space 缩进」→ 放进主 CLAUDE.md。规则的触发范围越窄,越应该放进 rules/ 的路径级文件。
4. 偶尔审计 Auto Memory 的内容 运行 /memory → 打开 auto memory 目录查看 Claude 记录了什么。Auto Memory 里的内容有时比你自己写的 CLAUDE.md 更准确地反映了「Claude 在这个项目里实际学到了什么」。发现过时或错误的记录直接编辑对应的 .md 文件即可;Auto Memory 是普通 Markdown,不需要特殊工具管理。
5. CLAUDE.md 和 Settings 各司其职,不要混用 CLAUDE.md 只放行为指导,技术约束放 settings。「不要 import xxx 包」写 CLAUDE.md;「禁止执行 rm -rf /」写 permissions.deny。Settings 里的限制是客户端强制执行的,Claude 自己无法绕过;CLAUDE.md 里的限制是上下文约束,Claude 通常遵循但在极少数情况下可能忽略。

本篇是 Claude Code SDK 系列的第 17 篇。下期主题:Skills 全解——如何把可复用的工作流程打包成按需加载的技能,而不是堆进 CLAUDE.md 变成 session 启动时的 token 负担。

围绕这条内容继续补充观点或上下文。

  • 登录后可发表评论。