你为仓库精心写了一份 CLAUDE.md —— 编码规范、测试命令、部署说明,事无巨细。Claude Code 一开新会话立刻违反了一半:用错包管理器、跑错测试命令、改了你明确标注为生成产物的文件。很多时候问题不在于 Claude 在”无视”规则 —— 而是这份文件根本没进上下文。
最快的修复: 在会话里运行 /memory。截至 2026 年 6 月,这个命令会列出本次会话实际加载的每一个 CLAUDE.md、CLAUDE.local.md 和 rules 文件。如果列表里没有你的项目文件,说明 Claude 根本看不到它 —— 那你遇到的是路径、大小写或工作目录问题,而不是规则问题。先把这个修好,再去改任何一条规则的措辞。
有一个关键点直接来自 Anthropic 官方文档:CLAUDE.md 是在 system prompt 之后,作为一条用户消息送进去的。Claude 会读它、尽量遵守,但它是上下文,而不是强制配置。所以这里其实有两种性质不同的失败,修法也不同:
- 文件没加载(本文重点):路径、大小写、工作目录、被排除,或者某个子代理跳过了它。用
/memory诊断。 - 文件加载了但 Claude 还是跑偏:指令含糊或互相冲突,或者这是个必须强制的动作。用更精确的措辞解决,或者把它改成一个 hook 来硬性强制(如果 hook 本身没触发,参见 Claude Code settings.json 未加载)。
常见原因
按真实场景中出现频率排序。
1. 从错误的工作目录启动
Claude Code 读 CLAUDE.md 的方式是从当前工作目录向上逐级走到文件系统根目录,一路读到每一个 CLAUDE.md 和 CLAUDE.local.md。位于 cwd 下方子目录里的文件不会在启动时加载 —— 只有当 Claude 读到那个子树里的文件时才会按需加载。所以如果你在 ~/projects 而不是 ~/projects/myrepo 里启动,下层的项目文件启动时根本不会被读进来。
怎么判断:启动 claude 前 pwd 的结果跟 CLAUDE.md 所在目录对不上;或者你在一个底下挂着多个仓库的父目录里跑了 claude。
2. 文件名或大小写错误
文件必须恰好叫 CLAUDE.md —— 全大写,.md 扩展名。Claude.md、claude.md、CLAUDE.MD、CLAUDE.markdown 在区分大小写的文件系统上(Linux、大多数 CI)都会被忽略。macOS 默认 APFS 不区分大小写,所以本地能跑,CI 一上就挂。
怎么判断:ls -la CLAUDE.md 没结果,但 ls -la | grep -i claude 显示文件存在,只是大小写不一样。
3. 文件放在了 Claude 不会加载的位置
项目级 CLAUDE.md 可以放在两个地方:仓库根目录的 ./CLAUDE.md,或者 ./.claude/CLAUDE.md。两者都有效。但放在 docs/CLAUDE.md 或任何其他子目录里的文件,只有当 Claude 读到那个目录里的文件时才会加载 —— 不在会话开始时加载。那些”为了保持根目录整洁”而挪走文件的人,常常就是这样把启动加载弄坏的。
怎么判断:/memory 没列出你的文件,而它既不在仓库根,也不在 .claude/ 里。
4. 文件被排除掉了
在 monorepo 里,claudeMdExcludes 设置(位于 .claude/settings.json、.claude/settings.local.json 或受管策略中)会按路径或 glob 跳过特定的 CLAUDE.md。同事写的一个过于宽泛的模式,比如 **/CLAUDE.md,可能悄悄把你的也排除了。另外,通过 --add-dir 加载的目录里的文件不会被读取,除非你设了 CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1。
怎么判断:/memory 漏掉了一个明明存在于有效路径的文件;检查每一层设置里的 claudeMdExcludes。
5. import(@path)没有解析
CLAUDE.md 支持 @path/to/file.md 这种 import,会在启动时展开进上下文。三个坑,都是截至 2026 年 6 月的现状:
- 相对路径是相对于包含这条 import 的文件解析,而不是工作目录。
- 写在 Markdown 代码块或行内代码里的 import 不会被解析(这是为了避免冲突的有意设计)。如果你把
@docs/x.md用反引号包了起来,它会被当作纯文本。 - import 最大深度是四跳。超过这个深度的文件不会被拉进来。
- 项目第一次用到外部 import(比如
@~/.claude/...)时,Claude 会弹一个授权对话框。如果你当时点了拒绝,import 会一直保持禁用状态,对话框也不会再出现。
怎么判断:你的 CLAUDE.md 很短,主要是几条 @ import;Claude 只知道 CLAUDE.md 的字面内容,完全不知道被 import 的内容。
6. 跨层级指令冲突(不是”被盖住”)
这是最容易被误解的一类原因。全局 ~/.claude/CLAUDE.md、项目 CLAUDE.md,以及受管策略文件,不是谁覆盖谁的关系 —— 它们全部被拼接进上下文。加载顺序从最宽泛到最具体(先受管策略,再用户级,最后项目级),同一目录内 CLAUDE.local.md 拼在 CLAUDE.md 之后,所以项目文件是最后被读到的,通常也就更占优。但如果两层给出互相矛盾的规则(全局”始终用 yarn”,项目里”用 pnpm”),Claude 可能任意挑一个 —— 并不保证一定听更具体的那个。
有两层确实会盖过你的项目文件:
- 受管策略
CLAUDE.md(macOS/Library/Application Support/ClaudeCode/CLAUDE.md,Linux/WSL/etc/claude-code/CLAUDE.md,WindowsC:\Program Files\ClaudeCode\CLAUDE.md,或受管设置里的claudeMd键)。它最先加载,而且无法被排除。在公司统一管理的机器上,这一层可能压过你的项目意图。
怎么判断:/memory 两个文件都列出来了;Claude 的行为跟另一层里某条相反的指令一致。找那种在两个地方都定义了的同一个键(包管理器、提交风格)。
7. 跳过 CLAUDE.md 的子代理
主代理产生子代理时,上下文怎么处理取决于子代理类型。截至 2026 年 6 月,内置的 Explore 和 Plan 子代理为了速度有意跳过 CLAUDE.md 和 git 状态;大多数其他内置及自定义子代理会加载它。另外还有一个未关闭的报告(anthropics/claude-code #29423),称某些 Task 工具产生的子代理没能可靠拿到项目 CLAUDE.md 或 .claude/rules/。结果就是:即便主代理在遵守规则,子代理跑起来还是可能无视项目规则。
怎么判断:直接发的提示遵守 CLAUDE.md;派发子代理的提示(“探索代码库并规划 X”)就不遵守。
开始前
- 确认你启动 Claude Code 时的 cwd(
pwd)。 - 记录问题出在主代理、子代理,还是两者都有。
- 抓一条
CLAUDE.md里被违反的具体指令 —— 你需要一个可确定复现的测试用例。 - 检查文件是否纳入版本控制(
git ls-files CLAUDE.md)。 - 跑一下
claude --version(auto-memory 相关功能需要 v2.1.59 及以上,而且命令名会随版本变动)。
一步步修复
按”哪个最常是真正的根因”排序。
第 1 步:运行 /memory —— 看清到底加载了什么
在会话里输入:
/memory
它会列出已加载的每个 CLAUDE.md、CLAUDE.local.md 和 rules 文件,可以切换 auto memory,也能在编辑器里打开任意文件。这一条命令就能解决大部分情况:
/memory 显示的内容 | 含义 | 跳到 |
|---|---|---|
| 列表里没有你的项目文件 | 它根本没加载 —— 路径/大小写/cwd/被排除 | 第 2-4 步 |
| 你的文件在列表里,旁边还有一个冲突文件 | 跨层级矛盾 | 第 5 步 |
| 列出来了,但内容比文件本身短 | 某条 @ import 或嵌套文件没解析 | 第 6 步 |
| 列出来了且正确,但 Claude 还是跑偏 | 加载没问题 —— 这是规则/强制层面的问题 | 第 7 步 |
你也可以直接让 Claude 把已加载的 CLAUDE.md 前 200 个字符原样打印出来,跟你的文件比对。需要持续诊断时,InstructionsLoaded hook 会记录到底哪些指令文件被加载、何时加载、为何加载。
第 2 步:修正 cwd 后重启
退出,cd 到仓库根目录,再启动:
cd ~/projects/myrepo
ls CLAUDE.md # 必须存在于此(或 .claude/CLAUDE.md)
claude
如果是通过包装器启动(tmux、VS Code task),要确认那个包装器的 cwd,而不是你终端的 cwd。
第 3 步:统一文件名
git mv claude.md CLAUDE.md
macOS 上仅改大小写的重命名可能失败,因为文件系统把两个名字当成同一个;改用一个临时名中转:
git mv claude.md tmp-claude && git mv tmp-claude CLAUDE.md
提交这次重命名,好让 CI(区分大小写)看到正确的名字。
第 4 步:把文件挪到会加载的位置 / 检查排除项
把 CLAUDE.md 放在仓库根或 .claude/ 里。如果 /memory 还是漏掉它,逐层设置搜一遍排除项:
grep -r "claudeMdExcludes" .claude/ ~/.claude/
删掉或收窄任何匹配到你文件的 glob。记住受管策略文件无法被排除。
第 5 步:解决跨层级冲突
打开 ~/.claude/CLAUDE.md,把那些应该归属项目的指令删掉 —— 全局文件只保留真正跨项目的偏好(语气、语言)。一份安全的全局文件:
# Global preferences
- Prefer concise commit messages.
- Default response language: English.
- Always read the project CLAUDE.md; project-level instructions take priority over these.
如果是某个受管策略文件在跟你冲突,那是 IT 设的 —— 你无法从项目设置里覆盖它,得找管理这份受管配置的人。
第 6 步:修好 import,或用 @path 拆分
根文件保持精简,开头先写最强的约束。Anthropic 建议每个文件控制在 200 行以内:文件越长越占上下文,而且会明显降低 Claude 遵守规则的可靠性。要让顶层文件小,把细节挪进 import:
# CLAUDE.md
@docs/coding-conventions.md
@docs/test-and-deploy.md
## Hard rules (must read)
- Package manager: pnpm. Never yarn or npm.
- Lint: pnpm run lint:fix before any commit.
然后逐条验证每个 import:
@那一行在普通正文里,不在代码块或反引号内。- 相对路径是相对于包含它的那个文件。
- 整条链最多四跳深。
- 目标没有被
.gitignore挡在工作树之外。
注意:拆成 import 有助于整理,但不会省上下文 —— 被 import 的文件在启动时会和内联文本一样展开进窗口。
第 7 步:处理子代理和会话中途的编辑
两个相关问题:
子代理。 如果某个子代理无视规则,就把规则内联进任务提示,让遵守不依赖于继承机制:
Task: research the auth module.
Constraints (from project CLAUDE.md):
- Do not run any package install.
- Test command: pnpm test --filter auth.
- Coding style: follow docs/coding-conventions.md before suggesting changes.
会话中途的编辑。 CLAUDE.md 在会话开始时读取。如果你在会话进行中改了它,要么重启,要么运行 /memory 重新打开文件,然后把改动章节贴进对话里,说一句”这段替代 CLAUDE.md 对应章节,本会话剩余时间生效”。好消息是:/compact 之后,项目根目录的 CLAUDE.md 会从磁盘重新读取并重新注入,所以压缩不会把它丢掉(子目录里的嵌套文件只有在 Claude 下次读到那个子树时才重新加载)。
如何确认已修好
- 运行
/memory—— 你的项目CLAUDE.md(以及任何 import)出现在列表里。 - 让 Claude 复述已加载文件的前 200 个字符;它跟你的文件完全一致。
- 跑一个依赖某条具体规则的提示(比如”装一个新依赖”),确认 Claude 用的是正确命令。
- 派一个子代理,验证它也遵守同一条规则,或者你已把规则内联进去。
- 在 Linux 机器或 CI(区分大小写)上确认文件依然能加载。
长期预防
CLAUDE.md进仓库,PR 模板里列为必备项。- 根文件控制在 200 行左右以内;细节推进
@import 或.claude/rules/(路径作用域规则只在 Claude 碰到匹配文件时才加载)。 - 加一个 pre-commit hook,只要
CLAUDE.md改成其他大小写就失败。 - 多仓库 monorepo:工作区根放一份
CLAUDE.md,每个 package 根也放一份;祖先文件会拼接,离 cwd 最近的那份最后被读到。 - 给人看的备注用块级 HTML 注释(
<!-- maintainer note -->)—— Claude Code 在注入上下文前会把它们剥掉,不占 token。 - 开头先写硬约束;绝不要把关键规则埋在长文件底部。
- 定期做冷启动探测:开一个全新会话,运行
/memory,确认项目文件已加载。
常见坑
- 改了
CLAUDE.md就以为正在跑的会话已经吃到 —— 没有,除非你重启或重新注入。 - 以为”全局覆盖项目”。各层是拼接的;项目文件最后被读到,但真正的矛盾仍可能任意收场。
- 把团队规范写进
~/.claude/CLAUDE.md让它”到处生效”,然后纳闷同事的 Claude 为何完全不知道(那个文件是机器本地的)。 - 因为 IDE 自动补全成了
Claude.md或claude.md就将错就错。 - 把
@import用反引号包起来,结果它变成了不起作用的纯文本。 - 以为 import 能省上下文 —— 不能;整棵树都在启动时加载。
- 把对项目架构的误解归咎于模型,实际上往往就是
CLAUDE.md没加载。 - 假定子代理会继承文件;关于上下文交接的相关问题,参见子代理结果未回传。
FAQ
Q:怎么判断到底是文件没加载,还是 Claude 只是不理它?
运行 /memory。如果文件在列表里,说明加载了 —— 问题在措辞或强制层面,那就把规则写具体,或改成 hook。如果不在列表里,说明它从没进上下文 —— 去修路径、大小写或工作目录。
Q:全局 ~/.claude/CLAUDE.md 会覆盖我的项目文件吗?
不会。它们是拼接的,项目文件最后被读到(因而权重更高)。唯一真正优先、而且无法被排除的一层是 IT 部署的受管策略 CLAUDE.md。各层之间的矛盾仍可能任意收场,所以把重复规则删掉。
Q:每次编辑 CLAUDE.md 都要重启吗?
要保证生效,是的。会话中途没有热加载。临时办法是把改动章节重新贴进对话。/compact 会自动从磁盘重新读取项目根目录的文件。
Q:多大算太大?
Anthropic 建议每个 CLAUDE.md 控制在 200 行以内。注意:CLAUDE.md 无论多长都会被完整加载 —— 不会被静默截断。那个 200 行 / 25KB 的加载上限是针对 auto-memory 的 MEMORY.md,不是针对 CLAUDE.md。超过几百行,你会丢的是遵守度和上下文预算,而不是内容。
Q:CLAUDE.local.md 怎么用?
同一个加载器;当作个人的、不入库的覆盖。它和 CLAUDE.md 一起加载,在同一目录里拼在 CLAUDE.md 之后。.gitignore 加一笔。因为被 gitignore 的文件只存在于某一个 worktree,要在多个 worktree 间共享个人规则,就从家目录 import:@~/.claude/my-project-instructions.md。
Q:为什么主代理遵守了 CLAUDE.md,子代理却无视它?
内置的 Explore 和 Plan 子代理按设计跳过 CLAUDE.md,而某些 Task 工具子代理一直没能可靠拿到它(anthropics/claude-code #29423)。把相关规则内联进任务提示,让遵守不依赖于继承。