Claude Code 项目 CLAUDE.md 未加载到上下文 —— 排查与修复

Claude Code 启动后忽略你的项目 CLAUDE.md:规范、命令、说明都没到模型那里。从路径、作用域、合并优先级三方面定位问题。

你为仓库精心写了一份 CLAUDE.md —— 编码规范、测试命令、部署说明,事无巨细。Claude Code 一开新会话立刻违反了一半:用错包管理器、跑错测试命令、改了你明确标注为生成产物的文件。问题不在于 Claude 在”无视”指令,而是这份文件根本没进上下文。项目级 CLAUDE.md 加载失败有几种不太明显的形式:文件名大小写错、文件位于 CLI 当前工作目录无法回溯到的子目录、用户级 CLAUDE.md 把它盖住、或者会话残留旧缓存需要重新加载。

常见原因

按真实场景中出现频率排序。

1. 从错误的工作目录启动

Claude Code 从当前目录向上一级一级找 CLAUDE.md,一直找到家目录。如果你在 ~/projects 而不是 ~/projects/myrepo 里启动,项目级文件根本看不到,只会读到全局那一份。

怎么判断:启动 claudepwd 的结果跟 CLAUDE.md 所在目录对不上;或者你同时开着多个仓库,然后在父目录里跑了 claude

2. 文件名或大小写错误

文件必须恰好叫 CLAUDE.md —— 全大写,扩展名也不能换。Claude.mdclaude.mdCLAUDE.MDCLAUDE.markdown 在区分大小写的文件系统上(Linux、大多数 CI)都会被忽略。macOS 默认 HFS+/APFS 不区分大小写,所以本地能跑,CI 一上就挂。

怎么判断:ls -la CLAUDE.md 没结果,但 ls -la | grep -i claude 显示文件存在,只是大小写不一样。

3. 用户级 CLAUDE.md 把项目级压住

全局 ~/.claude/CLAUDE.md 也会被加载,某些版本中它会跟项目级指令合并,甚至在冲突时把项目级覆盖掉。全局文件里一句”始终使用 yarn”就能压过项目里的”使用 pnpm”。

怎么判断:两个文件都存在,模型行为跟全局文件一致而非项目文件,通常冲突点是包管理器或提交风格。

4. 文件超过容量上限被静默截断

CLAUDE.md 有一个软上限(常见是 10-15k token)。超过这个量,尾部会在注入前被截掉。如果你把关键规则放在底部,它们就直接消失了。

怎么判断:CLAUDE.md 顶部的规则被遵守,底部的规则没被遵守。wc -c CLAUDE.md 超过 40000 字节。

5. @path 引入失败

CLAUDE.md 支持 @./docs/conventions.md 这种引用导入。如果目标文件不存在、被 .gitignore 忽略,或者超出项目根目录,这条引入会静默失败,该块为空。

怎么判断:你的 CLAUDE.md 很短,只有几条 @ 引入;模型只知道 CLAUDE.md 字面内容,完全不知道被引入的文件。

6. 子代理 / Task 工具产生的会话未携带 CLAUDE.md

主代理通过 Task 工具产生子代理时,子代理拿到的是全新上下文。部分配置不会自动把 CLAUDE.md 透传给子代理,因此子代理跑的时候无视项目规则,即便主代理在遵守。

怎么判断:直接给 Claude Code 发的提示遵守 CLAUDE.md;明确派发子代理的提示(“派一个 Task 调研 X”)就不遵守。

开始前

  • 确认你启动 Claude Code 时的 cwd。
  • 记录问题出在主代理、子代理,还是两者都有。
  • 抓一条 CLAUDE.md 里被违反的具体指令 —— 需要一个可复现的测试用例。
  • 检查文件是否纳入版本控制(git ls-files CLAUDE.md)。

需要收集的信息

  • 会话启动时的 pwd
  • ls -la CLAUDE.mdwc -c CLAUDE.md
  • ~/.claude/CLAUDE.md(全局文件)是否存在及其内容。
  • CLAUDE.md 里的 @ 引入及目标文件是否存在。
  • Claude Code 版本(claude --version)。
  • 当前系统:macOS(默认不区分大小写)还是 Linux / CI(区分大小写)。

一步步修复

按”哪个最常是真正的根因”排序。

第 1 步:先确认文件是否被找到

直接问 Claude:

请把你当前加载的项目 CLAUDE.md 前 200 个字符原样输出,不要改写。

如果输出跟你的文件对不上,或者它说”没有看到项目 CLAUDE.md”,问题就在加载,不在规则。

第 2 步:修正 cwd 后重启

退出,cd 到仓库根目录,再启动:

cd ~/projects/myrepo
ls CLAUDE.md   # 必须存在于此
claude

如果是通过外壳包装器启动(tmux、VS Code task),要确认那个包装器的 cwd,不是你终端的 cwd。

第 3 步:统一文件名

mv claude.md CLAUDE.md  2>/dev/null
mv Claude.md CLAUDE.md  2>/dev/null
git mv claude.md CLAUDE.md

提交这次重命名。macOS 上 git mv 因为大小写不敏感可能要加 --force

第 4 步:解决全局与项目级冲突

打开 ~/.claude/CLAUDE.md,把那些应该归属项目的指令删掉或注释掉。全局文件只保留真正跨项目的偏好(语气、语言)。

一份安全的全局文件大致是这样:

# Global preferences
- Prefer concise commit messages.
- Default response language: English.
- Always read the project CLAUDE.md first; project-level instructions override these.

第 5 步:精简 CLAUDE.md 或拆成 import

超过 10k token 就把章节拆出去:

# CLAUDE.md
@./docs/coding-conventions.md
@./docs/test-and-deploy.md
@./docs/architecture-notes.md

## Hard rules (must read)
- Package manager: pnpm. Never yarn or npm.
- Lint: pnpm run lint:fix before any commit.

CLAUDE.md 顶部留给最强约束。验证每个 @ 目标都存在且没被 gitignore。

第 6 步:子代理强制透传

派 Task 子代理时,把规则内联进任务提示:

Task: Research the auth module.
Constraints (from project CLAUDE.md):
- Do not run any package install.
- Test command: pnpm test --filter auth.
- Coding style: see @./docs/coding-conventions.md before suggesting changes.

这样不管子代理继承机制是否正常,规则都会被遵守。

第 7 步:会话中编辑后强制重新加载

CLAUDE.md 在会话开始时读取。如果你在会话进行中改了它,Claude 用的还是旧副本。要么重启会话,要么把更新后的章节贴进对话里,说一句”这段替代 CLAUDE.md 对应章节,本会话剩余时间生效”。

验证

  • 重启后请 Claude 复述 CLAUDE.md 前 200 个字符 —— 必须完全一致。
  • 跑一个依赖某条具体规则的提示(比如”装一个新依赖”),确认 Claude 用的是正确命令。
  • 派一个子代理,验证它也遵守同一条规则。
  • 在 Linux 机器 / CI 上跑一次,确认大小写也对。

长期预防

  • CLAUDE.md 进仓库,PR 模板里把它列为必备项。
  • @ 引入让根文件控制在 200 行以内;长篇细节放 docs/
  • 加一个 pre-commit hook,只要 CLAUDE.md 改成其他大小写就失败。
  • 多仓库 monorepo 既在工作区根放一份 CLAUDE.md,也在每个 package 根放一份;最近的那份生效。
  • 在 CLAUDE.md 自身写一句:“如果你没看到这条规则,说明文件没加载 —— 停下来问。”
  • 别把关键规则放在长文件底部;开头先写硬约束。
  • 定期做冷启动探测:开一个全新会话,让 Claude 确认它看到了项目文件。

常见坑

  • 改了 CLAUDE.md 就以为正在跑的会话已经吃到 —— 没有。
  • 把团队规范写进 ~/.claude/CLAUDE.md 让它”到处生效”,然后纳闷新同事的 Claude 为何完全不知道这些规范。
  • 因为 IDE 自动补全成了 Claude.mdclaude.md 就将错就错。
  • 完全依赖 @ 引入,却没意识到目标被 .gitignore 忽略了。
  • 把 30k token 的历史背景全塞进 CLAUDE.md,真正的规则反而被截掉。
  • 对项目架构的误解归咎于模型,实际上往往就是 CLAUDE.md 没加载。
  • 假定子代理自动继承文件;关于上下文交接的相关问题,参见子代理结果未回传

FAQ

Q: 工具调用里我看到 Claude 确实读了 CLAUDE.md,但还是不遵守。怎么回事?

读到不等于把它当作权威。在文件顶部加一行明确声明:“这些规则不可商量。任何工具调用前先确认你读过。“然后在一条具体规则上验证。

Q: 每次编辑 CLAUDE.md 都要重启吗?

要保证生效,是的。或者把改动章节贴进对话作为指令。没有热加载。

Q: 不同分支能有不同的 CLAUDE.md 吗?

可以 —— 它就在仓库里,分支级版本天然支持。worktree 里派的子代理要留意,可参考 Claude Code settings.json 未加载 里的路径解析相关问题。

Q: 多大算太大?

超过 8-10k token 你会开始丢尾部。超过 15k token,就算加载进去模型也无法稳定权衡 —— 量太大了。

Q: CLAUDE.local.md 怎么用?

同一个加载器,但当作个人覆盖,不进 git。.gitignore 加一笔。适合存放个人偏好而不污染团队文件。

标签: #Claude Code #claudemd #排查 #configuration #context