把多个站点放进一个仓库,再在每个站点的文件夹里放上 AI 规则(CLAUDE.md 或 AGENTS.md),AI 就会遵守对应站点的规则——这是很自然的想法,但无论 Claude Code 还是 Codex,都不会“总是读取”下层文件夹里的规则。从仓库根目录启动时,Claude Code 在接触该文件夹中的文件之前不会加载这些规则,Codex 则不会自动加载(AI 可能会自己打开,但没有保证)。本文依据两款工具的官方文档,逐项比较这些文件何时被加载、如何确认是否已加载,然后介绍如何用自动检查而不是文档来强制执行规则。内容来自我们在一个由 AI 智能体负责服务器运维和多个项目的环境中设计这套结构时的经验。

各站点文件夹里的规则何时被加载?(从仓库根目录启动)

repo/ ├─ CLAUDE.md, AGENTS.md ← 全仓库通用的规则 └─ sites/ ├─ blog/CLAUDE.md, AGENTS.md ← blog 的规则 ├─ shop/CLAUDE.md, AGENTS.md ← shop 的规则 └─ shared/ ← 共享组件

Claude Code

  • 启动时根目录的 CLAUDE.md
  • 接触时读取、写入或编辑 sites/blog/ 中的文件时,加载 blog 的 CLAUDE.md
  • 尚未还没接触过的文件夹(shop)的规则不会被加载

Codex

  • 启动时根目录的 AGENTS.md
  • 无保证sites/blog/ 中的 AGENTS.md 不会被自动加载(Codex 不会搜索启动目录以下的位置)
  • 无保证sites/shop/ 中的 AGENTS.md(同上)

因此,站点的工作要从该站点的文件夹启动,必须遵守的事项不要依赖文档。运行一个“只要负责的文件夹之外有改动就停止发布”的自动检查,并用每个 worktree 各自的设置来定义每个智能体的负责范围。规则文档则保留下来,用于向 AI 说明理由和步骤。

来源:Anthropic 的 How Claude remembers your project 和 OpenAI 的 Custom instructions with AGENTS.md(均于 2026 年 11 月 1 日确认)。

1. 在每个站点的文件夹里放规则后学到的事

在一个由 AI 智能体负责服务器运维和多个站点的环境中,我们考虑过这样一种设计:把多个站点放进一个仓库,并把每个站点的规则放在该站点的文件夹里(可能暴露地点或名称的细节不予公开,技术内容已做一般化处理)。目标是分工:负责 blog 的 AI 只读取 blog 的规则,绝不碰 shop。

但查阅两款工具的官方文档后发现,放好的规则并不能保证在开始工作前被加载。加载哪些规则,取决于从哪个文件夹启动。此外,Claude Code 的文档把 CLAUDE.md 描述为上下文,而不是强制执行的配置。即使规则被加载了,也无法保证一定会被遵守。

  1. !

    仅靠把规则放进文件夹,无法划分职责

    风险
    从根目录启动的 AI 在没读过该站点规则、或在读到之前就修改了文件
    对策
    站点的工作从站点文件夹启动,并用发布前的检查拦下范围外的改动(第 4 节)
    确认
    用工具确认加载了哪些规则(第 3 节),并故意改动范围外的内容,看发布是否会停止

AI 不遵守规则的一般原因及解决办法,请参阅《AI 为什么不遵守规则:排查 CLAUDE.md、Cursor Rules 与 AGENTS.md》。本文聚焦于把规则分散到各个文件夹时会发生什么。同一环境中关于把多个仓库交给 AI 的另外两点注意事项,见第 5 节。

2. 各文件夹的规则何时被加载?

各站点文件夹里的规则是否被加载,取决于从哪个文件夹启动和使用哪款工具。下面把两款工具官方文档的说法并排列出。

项目Claude CodeCodex
启动时加载启动目录及其上方所有目录中的每个 CLAUDE.md 和 CLAUDE.local.md从项目根目录(通常是 git 根目录)到启动目录,每个目录一个文件:AGENTS.override.md,没有则为 AGENTS.md
启动目录以下启动时不加载;当 Claude 读取、写入或编辑该文件夹中的其他文件时加载不会自动加载(搜索在启动目录处停止;AI 可能会自己打开)
会话中会追加吗?会(接触到的文件夹的规则会在之后追加)不会(每次运行开始时构建一次)
大小限制每个文件以 200 行以内为参考(更长的文件遵守得不那么可靠);下层文件夹的 CLAUDE.md 每个文件超过 40,000 个字符的部分(200K token 上下文时)会被截掉,只传入开头部分总量超过 32 KiB(project_doc_max_bytes 的默认值)后不再追加
另一款工具的规则文件当启动目录及其上方没有 CLAUDE.md、.claude/CLAUDE.md 或 CLAUDE.local.md 时读取 AGENTS.md(默认)不读取 CLAUDE.md(只读取添加到 project_doc_fallback_filenames 中的文件名)

来源:Anthropic 的 How Claude remembers your project 和 Monorepos and large repos,以及 OpenAI 的 Custom instructions with AGENTS.md(2026 年 11 月 1 日确认)。Claude Code 对下层文件夹的限制自 v2.1.309 起适用。使用 1M token 上下文时为 150,000 个字符(Opus 4.6 和 Sonnet 4.6 为 200,000 个字符)。Claude Code 自 v2.1.277 起直接读取 AGENTS.md;下层文件夹中的 AGENTS.md 会在该文件夹没有 CLAUDE.md、且 Claude 用 Read 工具打开其中的文件时被读取。若要两者都读取,请在 /config 中把 Project instructions 设为 claude-md-and-agents-md。

启动位置不同,加载的规则也不同

即使是同一个仓库,结果也取决于从哪里启动。从站点的文件夹启动,两款工具从一开始就会读取该站点的规则。

启动位置Claude CodeCodex
仓库根目录只有根目录的规则;各站点的规则在 Claude 接触该站点的文件时追加只有根目录的规则;站点的规则不会自动加载
sites/blog/启动时读取 blog 和根目录的规则(编辑启动目录以外的文件时会请求批准)先读根目录,再读 blog;shop 的规则不在这条路径上,因此不会自动加载

容易忽略的是“接触时加载”中的“接触”指什么。Claude Code 的文档中算作读取的,是用其工具读取、写入或编辑文件,以及 cat、head 等显示单个文件的命令。用其他方式修改文件的操作,例如跨多个站点文件夹的批量查找替换,不在这个列表中。站点的文件可能在其规则被读取之前就已经被改动。

在 Codex 中,如果从仓库根目录启动并要求“把 blog 和 shop 都改一下”,两个站点的 AGENTS.md 都不会被自动加载。文档写明 Codex 在到达当前工作目录时停止搜索,因此只有从该文件夹或其下方启动时,下层文件夹的规则才能在启动时可靠地纳入。

不过,Codex 仓库中的默认指令(base_instructions/default.md)大意是告诉模型:在当前工作目录以下或以外工作时,要检查适用的 AGENTS.md 文件。AI 可能会自己打开站点的 AGENTS.md,但那是 AI 的判断,而不是加载机制的保证。

各文件夹的设置文件,继承方式也不同

除了规则文档,两款工具对权限等设置文件的文件夹处理方式也不同。

项目Claude CodeCodex
项目设置文件.claude/settings.json.codex/config.toml
读取哪个文件夹的文件启动目录(primary working directory)中的;与 CLAUDE.md 不同,不从父文件夹继承从项目根目录到启动目录(越近优先级越高)
与信任(trust)的关系allow 等规则在你信任该文件夹后生效;deny 和 ask 立即生效只在受信任的项目中读取 .codex/

来源:Anthropic 的 Claude Code settings 和 Monorepos and large repos,以及 OpenAI 的 Config basics(2026 年 11 月 1 日确认)。

3. 确认规则是否已加载

放好规则后,启动后要确认它们是否真的被加载了。方法因工具而异;在 Claude Code 中,启动时加载的规则和之后加载的规则要在不同的地方查看。

确认内容Claude CodeCodex
启动时加载的规则/context 中的 Memory files 列表询问“Show which instruction files are active.”(这是 AI 自己的报告;要确保准确,请用下面的日志)
会话中加载的规则不显示在 Memory files 中;加载时终端会出现一行带路径的 Loaded会话中不会追加(同上)
留下记录用 InstructionsLoaded hook 记录加载了哪些规则、何时以及为何加载(直接读取的 AGENTS.md 不会触发)运行 codex -c log_dir=./.codex-log 写出 TUI 日志(./.codex-log/codex-tui.log),查看加载了哪些规则

来源:Anthropic 的 How Claude remembers your project 的故障排除部分,以及 OpenAI 的 Custom instructions with AGENTS.md 中的“Verify your setup”(2026 年 11 月 1 日确认)。请把日志文件夹加入 .gitignore,以免进入 git。

在 Claude Code 中测试新添加的下层文件夹规则文件时,请按文档的建议:在 shell 中创建规则文件,而不是让 AI 来写,然后让 AI 读取该文件夹中的某个文件,看是否出现 Loaded 行。

4. 用自动检查而不是文档来强制执行规则

如第 2 节所示,放在文件夹里的规则可能因启动位置和所用工具而不被加载。而且即使被加载,也无法保证被遵守。因此,请把强制执行分为三层来考虑。

规则文档
说明理由和步骤 CLAUDE.md 和 AGENTS.md。它们可能不被加载,即使被加载也无法保证被遵守。但 AI 需要它们来理解为什么某件事被拦下了
工具防护
在动作发生之前拦下 AI 工具中的 hooks 和权限设置(本文称之为“工具防护”)。每款工具的配置方式不同,并且可能因启动位置和信任设置而不生效
发布前检查
无论用哪款工具工作,都是最后一道关 只要负责的文件夹之外有改动,发布流程本身就会停止。它不依赖 AI 工具

在这个环境中,我们把最下层的发布前检查作为决定性的防线。无论是更换 AI 工具,还是由人直接操作,都要经过同一个检查。

用每个 worktree 各自的设置来定义每个智能体的负责范围

为每个站点分配各自的 worktree(git worktree),并在 worktree 的顶层放一个小设置文件(.agent-owner),列出在那里工作的智能体可以修改的文件夹。如果把范围写在仓库内的规则文档里,它在每个 worktree 中都是一样的,无法因位置而异。设置文件不要纳入 git(加到 .git/info/exclude),并在创建 worktree 时写好。

请注意,启动 AI 的位置不是 worktree 的顶层,而是其中的站点文件夹。worktree 的顶层与仓库根目录相同,从那里启动的结果与第 2 节中的“仓库根目录”一样。

# 在主检出(/srv/repo)中,为 sites/blog 在 /srv/work-blog 创建 worktree
cd /srv/repo
git worktree add /srv/work-blog -b blog-work
printf 'sites/blog/\n' > /srv/work-blog/.agent-owner
echo '.agent-owner' >> .git/info/exclude

# 从 worktree 内的 sites/blog/ 启动 AI
cd /srv/work-blog/sites/blog
claude        # Codex 的话用 codex

# 发布前,在 worktree 顶层运行主检出中的检查
cd /srv/work-blog
bash /srv/repo/tools/check-owner.sh origin/main

检查脚本要从主检出(AI 不在那里工作)或 CI 运行,而不是运行 worktree 内的副本。如果运行 worktree 中的副本,改写了检查脚本本身的 AI 就能直接通过。

范围之外有改动时停止发布

把下面的检查(即上面的 tools/check-owner.sh)放在发布流程的开头。它假定只从提交发布:如果还有未提交的改动就停止;如果相对基准(origin/main 等)的已提交 diff 中哪怕有一个文件在负责的文件夹之外,也会停止。它会读取 .agent-owner,所以要在 worktree 顶层运行。

#!/usr/bin/env bash
# 发布前在 worktree 顶层运行:负责的文件夹之外有改动就停止
set -euo pipefail

base="${1:-origin/main}"
owner_file=".agent-owner"   # 位于 worktree 顶层,不纳入 git

if [ ! -s "$owner_file" ]; then
  echo "没有范围文件($owner_file)。停止发布" >&2
  exit 1
fi

# 有未提交的改动就停止(只从提交发布)
if [ -n "$(git status --porcelain)" ]; then
  echo "存在未提交的改动。停止发布" >&2
  exit 1
fi

# --no-renames:把从其他文件夹的移动同时算作删除和新增
# 给每个范围条目末尾加上 /(这样 sites/blog 不会匹配 sites/blog-old)
# 已用 gawk(Git Bash)测试。-v 的值含换行时 BSD awk 可能失败
outside=$(git diff --name-only --no-renames "$base"...HEAD |
  awk -v list="$(tr -d '\r' < "$owner_file")" '
    BEGIN { n = split(list, own, "\n")
            for (i = 1; i <= n; i++) if (own[i] != "" && substr(own[i], length(own[i])) != "/") own[i] = own[i] "/" }
    { ok = 0; for (i = 1; i <= n; i++) if (own[i] != "" && index($0, own[i]) == 1) ok = 1
      if (!ok) print }')

if [ -n "$outside" ]; then
  echo "范围之外的文件有改动。停止发布:" >&2
  echo "$outside" >&2
  exit 1
fi
echo "只有范围内的改动"

以下是撰写本文的 Claude Code 于 2026 年 11 月 1 日用 Git 2.56(Windows 上的 Git Bash)搭建一个含两个站点和一个共享文件夹的测试仓库并运行检查的结果。

尝试的操作结果
blog 的智能体只改了 blog 的文件通过
把 shop 的文件移到 blog 文件夹停止(列出原来的 shop 文件)
修改共享文件夹中的文件停止(共享文件夹未列出时属于范围外)
范围不带末尾的 / 并添加了 sites/blog-old/停止(不补 / 的版本会放行)
在 shop 中留下未提交的改动停止(只检查已提交 diff 的版本会漏掉)
删除范围文件停止

防止移动被漏掉的正是 --no-renames。没有它,git 会把它认定为移动的改动只按目标名称列出,因此从其他站点搬来文件的改动不会被发现。另外,设置文件缺失时检查会“停止”而不是“通过”,这样从未设置范围的 worktree 就无法通过。

这个检查防的是混淆,而不是故意违规。如果 AI 改写了 .agent-owner,检查就会通过。要连这一点也防住,请用下面的工具防护把对该设置文件的编辑也禁止掉。

加上工具防护

只在发布前拦截,意味着要等 AI 已经改写了范围外的内容之后才会发现。要在写入之前拦下,请加上工具本身的功能。

项目Claude CodeCodex
禁止写入文件在权限设置的 deny 中添加 Edit(路径)(适用于内置工具以及 Claude Code 能识别的命令,如 sed、tee 和重定向)在 PreToolUse hook 中检查 apply_patch(也会以 Edit 和 Write 匹配)写入的位置,并以 permissionDecision 返回 deny
禁止命令在 deny 中添加 Bash(命令 *),或从 PreToolUse hook 返回退出码 2 或拒绝的 JSON规则 prefix_rule(pattern=[...], decision="forbidden")(实验性)和 PreToolUse hooks
拦住所有进程沙箱(deny 拦不住自己打开并写入文件的脚本)沙箱(sandbox_mode = "workspace-write" 把写入限制在启动目录;writable roots 会增加可写位置,不要随意添加)
放在项目中时的条件读取启动目录中的 .claude/settings.json;deny 在你信任该文件夹之前就生效只有项目受信任时才读取项目的 .codex/;hooks 在你审阅并信任之前不会运行

来源:Anthropic 的 Configure permissions 和 Hooks guide,以及 OpenAI 的 Hooks 和 Rules(2026 年 11 月 1 日确认)。

在 Claude Code 中,阻止 blog 的 worktree 修改范围文件(.agent-owner)、检查脚本(tools/)、根目录规则、shop 和共享文件夹的设置如下(假设 worktree 位于 /srv/work-blog)。以 // 开头的路径是绝对路径。worktree 的位置因机器而异,所以请在创建 worktree 时把这些添加到该机器的用户设置(~/.claude/settings.json)中,而不是放进仓库里的设置。

{
  "permissions": {
    "deny": [
      "Edit(//srv/work-blog/.agent-owner)",
      "Edit(//srv/work-blog/tools/**)",
      "Edit(//srv/work-blog/CLAUDE.md)",
      "Edit(//srv/work-blog/AGENTS.md)",
      "Edit(//srv/work-blog/sites/shop/**)",
      "Edit(//srv/work-blog/sites/shared/**)",
      "Edit(//srv/repo/**)"
    ]
  }
}

在 Codex 中,把检查脚本注册到 hooks 配置(个人的 ~/.codex/hooks.json、仓库的 .codex/hooks.json 等)的 PreToolUse 下,并以 apply_patch 作为 matcher。hooks 在你于 Codex 中用 /hooks 审阅并信任之前不会运行(修改后需要重新信任)。

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "^apply_patch$",
        "hooks": [ { "type": "command", "command": "python3 ~/.codex/hooks/owner_guard.py" } ] }
    ]
  }
}

检查脚本从 apply_patch 输入中的 *** Add File:、*** Update File:、*** Delete File: 和 *** Move to: 行提取目标路径,只要有一个在范围外或受保护,就返回 deny。下面是一个最小示例。

import json, posixpath, re, sys

# Codex 的 PreToolUse hook:apply_patch 修改范围外或受保护的文件时停止
OWN = ["/srv/work-blog/sites/blog/"]                  # 负责范围(末尾带 /)
PROTECT = ["/srv/work-blog/.agent-owner", "/srv/work-blog/tools/"]

event = json.load(sys.stdin)
command = event.get("tool_input", {}).get("command", "")
if isinstance(command, list):
    command = "\n".join(command)

bad = []
for m in re.finditer(r"^\*\*\* (?:Add File|Update File|Delete File|Move to): (.+)$", command, re.M):
    path = posixpath.normpath(posixpath.join(event.get("cwd", ""), m.group(1).strip()))
    if not any(path.startswith(o) for o in OWN) or any(path.startswith(p) for p in PROTECT):
        bad.append(path)

if bad:
    print(json.dumps({"hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "范围外的文件:" + ", ".join(bad)}}, ensure_ascii=False))

撰写本文的 Claude Code 用按 Codex 传入格式手工构造的输入(范围内、shop、.agent-owner、移入 shared,以及删除 tools/ 下的文件)运行了这个脚本,确认只有范围内的改动通过。我们没有在 Codex 内部运行过它。

Bash 命令的写法多种多样,所以 hook 无法完全判断它们会写到哪里。OpenAI 自己也称 hooks 为“a useful guardrail, not a complete enforcement boundary”(有用的护栏,而不是完整的强制边界)。想要阻止的命令(如 rm)用带 decision = "forbidden" 的规则禁止,其余的交给发布前检查来拦。规则放在配置层的 rules/ 文件夹中,例如 ~/.codex/rules/default.rules。项目的 .codex/rules/ 只在该项目受信任时才会被读取。

工具防护必须针对每款工具重写,并且可能因启动位置和信任设置而不生效。因此,请以所有改动最终都要经过的发布前检查为基础,再叠加工具防护以便更早发现问题。Claude Code hooks 的写法见《什么是 Claude Code hooks?确定性地运行 shell 命令》;只读设置见《Codex 与 Claude Code 只读使用方法:仅调查与提供建议》。

5. 另外需要注意:仓库混淆与环境变量

在同一个环境中,把多个仓库交给 AI 时还发生过另外两件事。两者都在酿成严重事故之前被发现了,但与规则怎么放无关,请为它们制定步骤。

用远程 URL 区分名称相似的仓库

AI 把另一个名称非常相似的服务的仓库判断为“同一服务的旧副本”,并把它移到了别处(随即恢复,内容没有变化)。它的理由是“没有本地改动,而且最后更新很久以前”,但这只说明“没有正在进行的改动”和“最近没人编辑过”。服务运行得越稳定,更新就越少。

在移动或删除任何东西之前,在目标文件夹和生产环境使用的文件夹中分别运行以下命令,并把结果并排比较。

# 远程 URL(显示前去掉 URL 中嵌入的 token 或密码)
git -C <文件夹> remote get-url origin | sed -E 's#://[^/@]+@#://#'

# 先确认不是浅克隆(如果为 true,下一个结果不可靠)
git -C <文件夹> rev-parse --is-shallow-repository

# 根提交(从同一历史分出的副本共享它)
git -C <文件夹> rev-list --max-parents=0 HEAD
  • 按主机和仓库路径比较远程 URL:https://github.com/org/app.git 和 git@github.com:org/app.git 是同一个仓库的不同写法;反过来,因镜像或主机别名,同一个仓库也可能看起来不同
  • 浅克隆中的根提交不是真正的第一个提交:用 --depth 1 获取的克隆,得到的是已获取的最旧提交(在我们的测试中就是 HEAD 本身)
  • 不要显示嵌入在 URL 中的 token:远程 URL 可能包含认证 token,原样输出会把机密泄露到输出中,与下面的环境变量一样

即使比较结果显示这是“没在使用的副本”,也不要马上删除;先把它移到别处。记下移到了哪里、原来在哪里以及恢复的命令,确认一段时间没有出问题后再删除。在这个环境中,正是因为文件夹被移动而不是被删除,混淆才得以立即撤回。

只看环境变量的名称

AI 运行了一条查看容器配置的命令,它把环境变量连同值一起输出,数据库连接字符串(包括密码)出现在了输出中。值一旦出现在输出中,就会留在对话记录里,并且还会发送给模型。如果只想看设置了什么,名称就足够了。

容器的环境变量

会显示值(不要用)

docker inspect <容器>
docker exec <容器> printenv
docker exec <容器> sh -c 'env | cut -d= -f1'

只显示名称

docker inspect --format '{{range .Config.Env}}{{index (split . "=") 0}}{{println}}{{end}}' <容器>
docker exec <容器> awk 'BEGIN{for(k in ENVIRON) print k}'

不带选项时,docker inspect 会输出全部配置,其中的 Env 原样包含值。在没有 awk 的容器中,请使用 docker inspect --format。

Docker Compose 的配置

会显示值(不要用)

docker compose config

不展开变量

docker compose config --no-interpolate

使用 --no-interpolate 时,${DB_URL} 原样显示,env_file 只显示文件路径。直接写在 compose.yaml 中的变量值会被显示。

本地 shell

会显示值(不要用)

env
printenv
Get-ChildItem Env:

只显示名称

compgen -e                  # bash
(Get-ChildItem Env:).Name   # PowerShell

以下是撰写本文的 Claude Code 于 2026 年 11 月 1 日用 Docker 29.8 和 Docker Compose v5.6、以虚拟值测试的结果。在一个有个值含换行(传递密钥文件内容时使用的形式)的容器中,运行 env | cut -d= -f1 会把该值的第二行和第三行原样输出,混在变量名中。awk 的 ENVIRON 和 docker inspect --format 没有显示值。docker compose config 显示了写在 .env 和 env_file 中的虚拟值;使用 --no-interpolate 时两者都没有出现,只显示了直接写在 compose.yaml 中的值。

为保险起见,请在规则文档中写上“只看环境变量的名称”,同时用第 4 节的工具防护禁止会输出值的命令。如果值还是被输出了,就当作“已被看到”,并判断是否需要更换。关于让环境变量本身不传给 AI 命令的 Codex 设置,请参阅《如何防止 Codex 读取机密文件:权限、审批与网络限制》的第 6 节。

6. 交付工作前的检查清单

  • 已决定站点的工作从 worktree 内的站点文件夹启动 AI
  • 启动后已确认包含了站点的规则:Claude Code 看 /context 中的 Memory files,Codex 看生效的指令文件列表
  • 对于从根目录启动的工作,已准备好查看下层文件夹规则是否在会话中被加载的方法(Claude Code 的 Loaded 行、InstructionsLoaded hook)
  • 已加入负责的文件夹之外有改动就停止发布的检查,并亲眼看到它在故意做出的范围外改动上停止
  • 每个 worktree 的范围都带末尾的 / 写好,并让检查在范围文件缺失时停止
  • 已用工具防护禁止对范围外和范围文件的写入
  • 已在规则中写入:移动或删除文件夹前与生产环境比较远程 URL 和根提交,并且移动而不是删除
  • 已在规则中写入只显示环境变量名称的命令,并用工具防护禁止会输出值的命令
规则文档的示例文字(可直接使用)
## 处理多个项目时的规则
- 本 worktree 的负责范围仅限 .agent-owner 中列出的文件夹。不要修改范围外的文件
  (那里的改动会让发布前检查停止)
- 移动或删除文件夹前,把 git remote get-url origin 和
  git rev-list --max-parents=0 HEAD 与生产环境比较(注意浅克隆)。
  移动而不是删除,并记下恢复方法
- 只看环境变量的名称。不要使用 env、printenv、docker inspect(不带 --format)或
  docker compose config(不带 --no-interpolate)

文档不要写成强制手段,而要写成说明,以便在某件事被拦下时,AI 能理解原因并选择正确的步骤。

总结

  • 从根目录启动时,放在各站点文件夹里的规则,Claude Code 要等到接触该文件夹的文件时才加载,Codex 则不会自动加载(AI 可能会自己打开,但没有保证)
  • 无论哪款工具,从站点文件夹启动都会从一开始就加载该站点的规则(使用 worktree 时,从其中的站点文件夹启动)
  • 启动时加载了什么,用 Claude Code 的 /context 或 Codex 的生效指令文件列表确认;Claude Code 在会话中加载了什么,用 Loaded 行或 InstructionsLoaded hook 确认
  • 把必须遵守的事项做成负责的文件夹之外有改动就停止发布的自动检查,再叠加工具防护以便更早发现问题
  • 另外,用远程 URL 和根提交区分名称相似的仓库,并且只看环境变量的名称

常见问题

问:子目录中的 CLAUDE.md 会被加载吗?

答:会,但不是在启动时。Claude Code 会在 Claude 读取、写入或编辑某个文件夹内的文件时加载该文件夹的 CLAUDE.md。这时它不会出现在 /context 的 Memory files 中,而是在终端中出现一行带路径的 Loaded。如果从该文件夹启动,它会在启动时被加载并显示在 Memory files 中。

问:怎样让 Codex 读取子目录中的 AGENTS.md?

答:从该文件夹启动 Codex(CLI 中为 codex --cd <文件夹>)。Codex 启动时读取从项目根目录到启动目录的 AGENTS.md 文件,不会搜索启动目录以下的位置。如果从根目录启动,下层文件夹的 AGENTS.md 只有在 AI 自己打开时才会被读取,官方文档没有提供能可靠加载它的设置。

问:在 monorepo 中,应该把规则文档合并成根目录下的一个文件吗?

答:两款工具的文档都建议把全仓库通用的规则放在根目录,把站点特有的规则放在站点的文件夹里。不过,不从站点文件夹启动的话,该站点的规则可能不会被加载,所以被忽略就会出问题的内容,请从文档移到发布前检查或工具防护中。

问:怎样让 Claude Code 同时读取 CLAUDE.md 和 AGENTS.md?

答:默认情况下,如果启动目录或其上方有 CLAUDE.md、.claude/CLAUDE.md 或 CLAUDE.local.md,就不会读取 AGENTS.md。可以在 CLAUDE.md 中用一行 @AGENTS.md 导入它,或在 /config 中把 Project instructions 设为 claude-md-and-agents-md。

参考资料