Carl Wang
造物2026年10月21日

Claude Code 读 AGENTS.md 的回退条件实测:为什么还不能删 CLAUDE.md

用 claude -p --debug 实测 Claude Code 2.1.304 读取 AGENTS.md 的回退条件:上层目录存在 CLAUDE.md 时子项目的 AGENTS.md 整份不加载,cwd 之外的 @ 导入在非交互模式下也不加载。

Claude Code 从 2.1.277 起支持在没有 CLAUDE.md 时直接读取 AGENTS.md。我的项目同时给 Codex 和 Claude Code 用,每个目录都维护一对入口:AGENTS.md 是唯一权威,CLAUDE.md 只写一行 @AGENTS.md。于是自然想问:这一行是不是可以删了?

答案是不能。下面是实测过程。

测试设计

在一个上层没有任何 CLAUDE.md 的临时目录里搭四组结构,每个文件埋一个独一无二的标记(MARKER_A_AGENTS 这样的 token),然后在各目录用 claude -p --debug 起一个非交互会话,看哪些标记真的进了上下文。

组结构想验证什么
A只有 AGENTS.md回退是否生效
B上层有 CLAUDE.md,子目录只有 AGENTS.md,在子目录启动删掉子项目的 CLAUDE.md 会怎样
C只有 AGENTS.md,内含一个 cwd 内的 @ 导入和一个 cwd 外的回退路径下 @ 导入怎么处理
D上层有 CLAUDE.md,子目录 CLAUDE.md 单行 @AGENTS.md + AGENTS.md(含 cwd 外导入)对照组,现有做法

证据不取模型的回答,取两处更硬的东西:

  • --debug 日志里内置插件 cc-plugin-agents-md 的输出,它会在加载 AGENTS.md 时写一行 no CLAUDE.md found; AGENTS.md loaded: <path>;
  • 会话记录(projects/<cwd>/<session>.jsonl)里实际注入的指令文件内容,直接数标记。

测试时 CLI 的 OAuth 恰好过期,模型一句话都没回。这反而证明了一点:指令文件在发出第一个请求之前就已经装配完毕并写入会话记录,加载结果与模型无关。

结果

组实际加载的标记结论
AMARKER_A_AGENTS回退生效,日志出现 AGENTS.md loaded
B只有上层的 MARKER_B_PARENT_CLAUDE子目录 AGENTS.md 整份未加载,日志里连祖先扫描都没有
CMARKER_C_AGENTS、MARKER_C_IMPORT_INSIDEcwd 内导入展开;cwd 外导入静默丢弃,没有任何提示
DMARKER_D_PARENT_CLAUDE、MARKER_D_CHILD_AGENTS配对入口正常;cwd 外导入同样未加载

B 组就是「删掉子项目 CLAUDE.md」之后的真实状态。只要祖先链上任何一层还有 CLAUDE.md,Claude Code 就把整个目录树当成 Claude 项目,不再查找任何 AGENTS.md。子项目的身份、状态声明、技术栈导入会一起静默消失,没有警告。

机制

从二进制里能看到判定顺序:插件先扫描祖先链有没有 CLAUDE.md、.claude/CLAUDE.md 或 CLAUDE.local.md,任一存在就标记 isClaudeProject,直接跳过 AGENTS.md 的查找。只有祖先链干净时才去找 AGENTS.md,并展开它的 @ 导入。

这解释了 B 组日志为什么连 AGENTS.md 的祖先扫描都没有:第一步就短路了。

一处没有分开的地方

C 和 D 的 cwd 外导入都没加载。我试过往 ~/.claude.json 的 projects[<cwd>] 写 hasClaudeMdExternalIncludesApproved: true 再跑,结果不变。所以在非交互的 claude -p 下,两条路径对仓外导入的处理一样:不加载。文档所说的「经 CLAUDE.md 导入时首次弹批准框」是交互行为,这次没有覆盖。

对我的意义

我的工作区是一个容器仓库,根目录有 CLAUDE.md,几十个子项目各自是独立 Git 仓库。它们全部命中 B 组的情形。删掉任何一个子项目的单行 CLAUDE.md,该项目的 AGENTS.md 就对 Claude Code 不可见。

那一行 11 字节的 @AGENTS.md 继续留着。回退机制省不出什么,却会在两种情况下静默丢规则:上层有 CLAUDE.md 时丢整份,没有时丢仓外导入。

复现

mkdir -p /tmp/fb/B/child
printf 'MARKER_B_PARENT_CLAUDE present.\n' > /tmp/fb/B/CLAUDE.md
printf 'MARKER_B_CHILD_AGENTS present.\n' > /tmp/fb/B/child/AGENTS.md
cd /tmp/fb/B/child && claude -p --debug 'reply NONE' >/dev/null 2>&1
grep -c MARKER_B_CHILD_AGENTS "$(ls -t ~/.claude/projects/*fb-B-child/*.jsonl | head -1)"

输出 0 即为 B 组现象。~/.claude 换成你的 CLAUDE_CONFIG_DIR。版本基准:Claude Code 2.1.304,2026-10-21 实测。