Skip to content

Claude Code 的 CLAUDE.md 遵循两种不同的加载机制:从当前目录向上找到的所有祖先 CLAUDE.md 在启动时立即加载;子目录的 CLAUDE.md 则只在 Claude 操作该目录的文件时才懒加载。正确理解这两种机制是组织 monorepo 项目指令的基础。

Claude Code Memory 深度解析:CLAUDE.md 在单体仓库中的加载机制

什么是 CLAUDE.md

CLAUDE.md 是 Claude Code 的持久上下文文件,用来告诉 Claude 项目规范、代码风格、测试命令、常见陷阱等。它是对 Claude 输出质量影响最大的单一配置文件,相当于每次对话开始前 Claude 必读的"工作手册"。

CLAUDE.md 可以放在多个位置,每个位置有不同的作用范围:

  • ~/.claude/CLAUDE.md:全局个人配置,适用于所有项目
  • <项目根目录>/CLAUDE.md:项目级共享配置,提交到 git 供团队使用
  • <项目根目录>/CLAUDE.local.md:项目级个人配置,加入 .gitignore
  • <子目录>/CLAUDE.md:模块级配置,仅在操作该模块文件时加载

两种加载机制

理解这两种机制是 monorepo 中合理组织 CLAUDE.md 的关键。

向上加载(Ancestor Loading)——启动时立即加载

Claude Code 启动时,从当前工作目录向上遍历整个目录树直到根目录,加载沿途找到的所有 CLAUDE.md 文件。这些文件立即注入上下文,无需等待任何操作。

/mymonorepo/          ← CLAUDE.md 启动时加载 ✓
├── CLAUDE.md
└── frontend/         ← 从这里启动 claude
    └── CLAUDE.md     ← CLAUDE.md 启动时加载 ✓

/mymonorepo/frontend/ 启动时,frontend/CLAUDE.md/mymonorepo/CLAUDE.md 都会立即加载。

向下懒加载(Descendant Loading)——操作时按需加载

子目录的 CLAUDE.md 不会在启动时加载,只有当 Claude 读取或编辑该子目录内的文件时才会触发加载。

/mymonorepo/          ← 从这里启动 claude
├── CLAUDE.md         ← 启动时加载 ✓
├── frontend/
│   └── CLAUDE.md     ← 操作 frontend/ 文件时加载
├── backend/
│   └── CLAUDE.md     ← 操作 backend/ 文件时加载
└── api/
    └── CLAUDE.md     ← 操作 api/ 文件时加载

兄弟目录互不影响:在 frontend/ 工作时,永远不会自动加载 backend/CLAUDE.mdapi/CLAUDE.md

完整的加载场景示例

场景 1:从根目录启动

bash
cd /mymonorepo
claude
文件是否加载原因
/mymonorepo/CLAUDE.md✅ 启动时当前目录
frontend/CLAUDE.md延迟等到操作 frontend/ 文件
backend/CLAUDE.md延迟等到操作 backend/ 文件

场景 2:从子目录启动

bash
cd /mymonorepo/frontend
claude
文件是否加载原因
/mymonorepo/CLAUDE.md✅ 启动时祖先目录
frontend/CLAUDE.md✅ 启动时当前目录
backend/CLAUDE.md❌ 不加载兄弟目录,永不加载
api/CLAUDE.md❌ 不加载兄弟目录,永不加载

为什么这个设计合理

  • 祖先向下传递:根目录的规范会被所有子项目自动继承,无需重复
  • 子目录按需加载:不操作某个模块就不加载它的规则,避免无关上下文污染
  • 兄弟隔离:前端开发者不会被后端规范干扰

如何组织 Monorepo 的 CLAUDE.md

根目录 CLAUDE.md——放全局规范

markdown
# mymonorepo

## 技术栈
- 包管理:pnpm workspaces
- 测试:vitest
- 提交格式:Conventional Commits

## 常用命令
- `pnpm test`:运行全量测试
- `pnpm build`:构建所有包

## 注意事项
- 不要直接修改 dist/ 目录
- PR 必须通过 CI 才能合并

子目录 CLAUDE.md——放模块专属规范

markdown
# frontend 模块

## 框架规范
- 使用 React 18 + TypeScript
- 状态管理:Zustand(不用 Redux)
- 组件文件:每个组件一个目录,含 index.tsx + tests/

## 禁止事项
- 不直接调用后端 API,通过 api/ 包的封装

个人配置 CLAUDE.local.md

添加到 .gitignore,用于个人偏好:

markdown
# 我的偏好
- 代码注释用英文
- 变量命名偏好 camelCase
- 我在用 M4 MacBook,可以并行运行构建任务

.claude/rules/ 的按路径激活

除了 CLAUDE.md,还可以在 .claude/rules/ 目录放置规则文件,通过 paths frontmatter 实现只在操作特定文件时激活:

markdown
---
# .claude/rules/typescript-rules.md
paths: "**/*.ts,**/*.tsx"
---

# TypeScript 规则

- 始终定义函数的返回类型
- 避免使用 any,优先用 unknown

只有当 Claude 操作 .ts.tsx 文件时,这条规则才会加入上下文。这是更精细的懒加载控制。

写好 CLAUDE.md 的核心原则

根据 Boris Cherny 和 Humanlayer 的经验:

  1. 控制在 200 行以内:太长会稀释重要规则的权重,Claude 可能忽略后面的内容
  2. 关注"不显而易见"的规则:Claude 本身已经懂编程规范,只写项目特有的约束和陷阱
  3. 让团队共同维护:每次 Claude 做错的事,立即加入 CLAUDE.md,下次就会记住
  4. <important> 标签标记关键规则:对于"绝对不能违反"的规则,用标签包裹以提高权重
markdown
<important if="modifying-auth">
修改认证相关代码时,必须同时更新 auth-tests/ 目录下的集成测试。
</important>
  1. 任何开发者运行 claude 说"运行测试"都应该成功:如果不行,说明 CLAUDE.md 缺少了构建/测试命令

FAQ

Q: CLAUDE.md 和 .claude/rules/ 有什么区别? A: 功能相同,但 .claude/rules/ 更适合大型项目:支持多文件拆分,支持 paths 字段按文件路径懒加载,便于团队分工维护不同模块的规则。CLAUDE.md 更简单,适合小型项目。

Q: 为什么子目录的 CLAUDE.md 没有在启动时加载? A: 设计上的选择:如果所有 CLAUDE.md 都在启动时加载,大型 monorepo(可能有几十个子模块)会在启动时就把大量无关上下文注入,不仅浪费 tokens,还会干扰 Claude 的判断。懒加载确保只有你真正在操作的模块规则才会进入上下文。

Q: Claude 真的会忽略 CLAUDE.md 里的规则吗? A: 会,概率在 20% 左右(来自社区数据)。缓解方法:把最重要的规则放在文件开头,使用 <important> 标签,保持文件简洁(< 200 行),以及在规则里解释为什么(有原因的规则更不容易被忽略)。