Claude Code 的持久化记忆系统基于项目中的 CLAUDE.md 文件,其核心在于两种加载规则:启动时自动向上(Ancestor Loading)遍历并加载所有祖先目录的 CLAUDE.md;对于子目录(Descendant Loading)的 CLAUDE.md,则采用惰性加载策略,仅在访问相关文件时才注入上下文。理解此机制是管理大型单体仓库(Monorepo)中 Claude Code 行为的关键。
Claude Code Memory 机制详解:CLAUDE.md 加载规则与单体仓库最佳实践
Claude Code 的 Memory 机制允许开发者通过 CLAUDE.md 文件为项目提供持久化的上下文和指令。在单体仓库等复杂项目结构中,理解这些文件如何被加载到会话中,对于精确控制 Claude 的行为至关重要。
1. CLAUDE.md 的作用与核心加载机制
CLAUDE.md 文件是 Claude Code 会话的“记忆”,存放项目规范、编码标准、工作流说明等。Claude Code 通过两种机制加载这些文件。
1.1 向上加载 (Ancestor Loading)
当你在某个目录启动 Claude Code 时,它会从当前工作目录开始,向上遍历整个目录树,直至文件系统根目录。沿途遇到的每一个 CLAUDE.md 文件都会被立即加载到会话上下文中。这确保了仓库根目录等高层级的通用规范始终可用。
1.2 惰性加载 (Descendant Loading)
对于位于当前工作目录下方子目录中的 CLAUDE.md 文件,它们不会在启动时加载。这些文件只有在会话期间,当 Claude 实际读取或编辑该子目录下的文件时,才会被按需加载。这种设计避免了会话启动时加载大量可能不相关的上下文,优化了内存使用。
2. 单体仓库中的加载行为详解
假设我们有一个如下的单体仓库结构:
/mymonorepo/
├── CLAUDE.md
├── frontend/
│ └── CLAUDE.md
├── backend/
│ └── CLAUDE.md
└── api/
└── CLAUDE.md
下表详细说明了在不同目录启动 Claude Code 时,各个 CLAUDE.md 文件的加载时机与原因:
| 文件路径 | 从 /mymonorepo 启动 |
从 /mymonorepo/frontend 启动 |
|---|---|---|
/mymonorepo/CLAUDE.md |
是 (启动时) | 是 (启动时,作为祖先目录) |
/mymonorepo/frontend/CLAUDE.md |
否 (惰性加载) | 是 (启动时,作为当前目录) |
/mymonorepo/backend/CLAUDE.md |
否 (惰性加载) | 否 (不同分支,永不自动加载) |
/mymonorepo/api/CLAUDE.md |
否 (惰性加载) | 否 (不同分支,永不自动加载) |
关键结论:
- 祖先始终加载:保证仓库级共享规范无条件生效。
- 后代惰性加载:实现组件级指令的上下文隔离。
- 兄弟永不加载:在
frontend/工作时,不会意外引入backend/的特定指令。
3. Claude Code 三层 Memory 系统对比
除了项目级的 CLAUDE.md,Claude Code 还有其它记忆机制,它们共同构成一个分层系统:
| 特性 | CLAUDE.md (项目记忆) | Auto-memory (用户记忆) | Agent/Subagent Memory (代理记忆) |
|---|---|---|---|
| 存储位置 | 项目目录中的文件 | ~/.claude/CLAUDE.md (全局) |
子代理定义中的 memory 字段指定范围 |
| 作用域 | 仅当前项目及子项目 | 所有项目的任何会话 | 特定子代理及其派生的会话 |
| 用途 | 项目规范、编码标准、工作流 | 个人跨项目的偏好、习惯 | 记录特定任务代理的进度、决策、中间状态 |
| 示例 | 见下文的实际 CLAUDE.md 节选 |
用户偏好的代码风格、提交信息格式 | 一个长期运行的“代码审查”代理对审查历史的记录 |
根据仓库中子代理的定义,memory 字段(user, project, local)控制了这种持久化记忆的范围。
4. 编写有效 CLAUDE.md 的最佳实践
基于仓库中的实践经验,组织 CLAUDE.md 文件应遵循以下原则:
4.1 文件组织与大小
- 保持简洁:单个
CLAUDE.md文件最好控制在 200 行以内,以确保 Claude 能可靠地遵循其中的指令。 - 根目录放通用规范:将编码标准、Git 提交规则(如本项目要求的每个文件单独提交)、PR 模板等仓库全局规范放在根目录的
CLAUDE.md中。 - 子目录放组件规范:在
frontend/CLAUDE.md、backend/CLAUDE.md中放置框架特定的模式、组件架构和测试约定。
4.2 使用 CLAUDE.local.md 与 Rules
- 个人偏好隔离:创建
CLAUDE.local.md并将其加入.gitignore,用于存放不应与团队共享的个人指令或临时调试配置。 - Rules 的惰性加载:在
.claude/rules/*.md中通过 YAML frontmatter 的paths:字段定义规则,可以实现更精细的惰性加载,仅当文件匹配时才注入上下文。
4.3 引用实际配置示例
一个优秀的 CLAUDE.md 应清晰地描述项目架构和关键模式。例如,本项目的根 CLAUDE.md 就详细说明了:
- 工作流架构:如 Weather System 展示的
Command → Agent → Skill模式。 - 定义结构:如 Skills 和 Subagents 的 YAML frontmatter 字段说明。
- 系统集成:如 Hooks System 的跨平台声音通知实现。
5. 验证与调试 Memory 加载
如果怀疑 CLAUDE.md 没有被正确加载:
- 使用
/doctor命令进行基础诊断。 - 检查你的当前工作目录。向上加载机制从该目录开始。
- 确保文件名是准确的
CLAUDE.md(全大写,无扩展名错误)。 - 对于全局记忆,检查
~/.claude/CLAUDE.md是否存在。
FAQ
Q: 子目录的 CLAUDE.md 什么时候会被加载?
A: 仅当 Claude Code 在会话中实际读取或编辑该子目录下的文件时,才会惰性加载对应的 CLAUDE.md。启动时或访问其他不相关的目录时不会加载。
Q: 如何设置对所有项目都生效的个人偏好?
A: 在你的用户主目录下创建全局文件 ~/.claude/CLAUDE.md。其中的指令会应用于所有 Claude Code 会话,无论项目是什么。
Q: CLAUDE.local.md 和 CLAUDE.md 有什么区别?
A: CLAUDE.md 通常提交到版本库,用于团队共享的规范。CLAUDE.local.md 应被 .gitignore 忽略,用于存放个人配置、临时实验或敏感信息,不会影响其他协作者。
Q: 为什么说“兄弟目录的 CLAUDE.md 永不加载”?
A: 因为向上加载只沿当前目录到根目录的单一路径进行。如果你在 frontend/ 目录,Claude 只会向上查找 frontend/ -> /mymonorepo/ -> / 路径上的文件,不会横向去扫描 backend/ 或 api/ 目录。惰性加载也仅作用于后代(子目录),不包含兄弟目录。