Skip to content

C1|AGENTS.md:说明书是发现链,不是第二份 README ​

先别把仓库说明书写成小说 ​

给 coding agent 写「项目说明」时,第一反应往往是再写一份 README:架构故事、贡献流程、从零搭建的十步教程,再把 API key 示例贴进去。然后奇怪为什么模型不听话、窗口为什么先被说明书撑满、克隆下来的仓库为什么能改你的行为。

B4 已经说明:说明书进模型是有标记的 UserInstructions fragment,按差量追加,未信任项目根本不读仓库里的文件。这一章站在 写的人 这边:文件怎么被找到、每个目录取哪一份、/init 会生成什么、什么该写进 git、什么该留给 ExecPolicy / Skills / Memories。

判断先说清楚:AGENTS.md 是始终在场的项目政策,不是文档站,也不是 skill。 它该短、该可执行、该能被更近的目录覆盖。


1. 发现链:全局一份,项目从 git root 走到 cwd ​

三层来源,不要混成「随便放一个 md」。

全局(账号 / 本机)。 CodexHomeUserInstructionsProvider 在 CODEX_HOME 里按顺序找 AGENTS.override.md,找不到再找 AGENTS.md(codex-home/src/instructions/mod.rs:15-42)。找到第一份非空文件就返回,两份不拼接。这是你的个人偏好,不进 git。

项目。 agents_md.rs:1-16:向上找 project root(默认标记 .git,project_root_markers.rs:5, 45-49),再从 root 走到 cwd(含两端),每一层若有说明书就收进来,拼在一起。不越过 root。 子目录的文件不会让搜索爬出仓库。空的 project_root_markers 关掉向上走,只看 cwd。

拼的时候用户/thread 说明书在前,项目条目在后;从用户侧跨到项目侧时插入 --- project-doc ---(agents_md.rs:44-46, 388-401),让模型分得清「这是我的账号偏好」和「这是仓库政策」。多层项目文件之间只用空行。审查提示写明:冲突时 更具体的赢(prompts/templates/review/rubric.md:48)——cwd 近的条目后出现,就是给模型的就近信号。

未信任项目。 load_project_instructions 开头直接返回,只留 host 给的 user instructions(agents_md.rs:61-63)。B5 的信任闸在这里的产品面:克隆下来的 AGENTS.md 默认进不了 prompt。找 root 用的 project_root_markers 只从 非 Project 配置层 合并(:197-202),恶意仓库不能靠自己的 .codex/config.toml 把搜索范围扩到 /。

默认总预算 32 KiB(B4)。超了就截断并打 warn(agents_md.rs:153-162),不是再开一个窗口。写长了,先被切的是文件尾巴,通常是你最后才想起来的「重要补充」。

没有这条发现链会怎样?要么只认 cwd 一份,monorepo 里 packages/foo 看不到根上的禁令;要么从 cwd 走到 $HOME,把别人的说明书和密钥目录一起灌进模型。root 标记和 32 KiB 是硬边界,不是排版建议。


2. 每个目录只取一个文件名:override → AGENTS.md → fallback ​

同一目录里不是把所有 md 都拼上。candidate_filenames 的顺序是(agents_md.rs:269-282):

  1. AGENTS.override.md(本机覆盖,优先)
  2. AGENTS.md(仓库正本)
  3. project_doc_fallback_filenames 里配置的名字,去重、跳过空串

第一个在该目录存在且是文件的,就是这一层的说明书。默认 fallback 列表是 空的(config/defaults.toml:9,config_toml.rs:84-86)。Codex 不会在未配置时自动读 CLAUDE.md / GEMINI.md。

AGENTS.override.md 给「我想在本机改政策、但不想污染 git」用。团队正本仍是 AGENTS.md。override 在 candidate 列表最前,所以它会挡住同目录的 AGENTS.md——这是替换,不是合并。

Fallback 是跨工具的适配孔,不是第二套正本。你要和 Claude Code / Gemini CLI 共用仓库,可以把 CLAUDE.md、GEMINI.md 写进 project_doc_fallback_filenames。审查管线也认同一套次序:AGENTS.override.md,AGENTS.md,然后才是配置的 fallback(review/rubric.md:48)。从 Claude Code 迁入时,源文件名就是 CLAUDE.md(external-agent-migration/src/source/cla.rs:21)——那是 导入源,不是发现默认值。

没有「每层只取一份」会怎样?三个文件各写一套测试命令,模型同时看见三份互相打架的政策。优先序存在,就是为了让你只维护一份正本,覆盖和 fallback 各司其职。


3. /init 是一次生成提示,不是覆盖按钮 ​

TUI /init 的说明是「create an AGENTS.md file with instructions for Codex」(slash_command.rs:91)。实现是把一份内嵌 prompt 当成 用户消息交出去(slash_dispatch.rs:270-272),不是 Rust 直接写文件。

那份 prompt(tui/assets/prompt_for_init_command.md:1-13)自己定了三条纪律:

  • 文件名必须是 AGENTS.md
  • cwd 里 已经有就不要覆盖或修改
  • 目标 200–400 词,标题用 Markdown,语气像给贡献者的操作说明

建议章节是:目录结构、构建/测试/本地命令、代码风格、测试怎么跑、commit / PR。可选才加安全、架构、agent 专用指示。这就是产品对「说明书该有多长」的官方答案:一篇短文,不是一本书。

/init 走的是普通 Regular turn,所以仍受沙箱和审批约束。它生成的是 仓库政策草稿,生成完你应该打开文件删掉空话、补上真正的禁区和验证命令。不要把 /init 的输出当成已经正确的政策。


4. 该写什么,不该写什么 ​

对照这份仓库自己的 AGENTS.md:crate 命名、just test -p、禁止动哪些沙箱环境变量、clippy 规则、测试不测静态值、别往 docs/ 塞用户文档、别再把东西塞进 codex-core。全是 可执行的约束:命令、禁区、验证方式。

该写不该写
怎么跑测试 / lint / 生成 schema从零搭建的长教程(README 或 skill 的 references)
绝对不要改的文件、目录、环境变量API key、token、内网地址
改完怎么证明没坏(just test -p X)把 ExecPolicy 该 forbidden 的事写成「请不要」
本目录相对根目录的额外禁令把 Memories 当政策(C2:记忆默关,不替代说明书)
代码风格里 agent 会踩的坑把 MCP 安装步骤全文贴进来(那是 D1/D3)

长流程、逐步操作手册,放 Skill 的 references/,靠渐进披露;AGENTS.md 每轮都在,写长了就是在和 compact 抢窗口。密钥和「永远不许跑的命令」放 ExecPolicy / 沙箱,不放说明书——B3 已经证明 prompt 挡不住 sudo。

Monorepo 用发现链:根上写全局禁令和测试入口,packages/foo/AGENTS.md 只写这个包多出来的命令。不要在每个子包复制一份根文件。根走 git root,子包走 cwd,两份都会进模型,后出现的更具体。

没有这张「该写/不该写」会怎样?说明书变成第二份 README,32 KiB 被架构故事吃掉,真正的 just test 被截断;或者把密钥写进 git,模型每轮都能看见。政策短,是为了每轮都在且真的能执行。


5. 和 CLAUDE.md / GEMINI.md:一份正本,适配用 fallback ​

跨工具仓库里常见三份几乎一样的 md。Codex 的选择是:

  • 正本名字是 AGENTS.md。 /init 只生成这个名字。
  • Claude / Gemini 的文件名不是默认发现目标。 要读它们,显式配 project_doc_fallback_filenames。
  • 迁移可以从 CLAUDE.md 进来,进来之后应收敛到 AGENTS.md,而不是永远双写。
  • 审查和发现共用同一优先序:override → AGENTS.md → fallback。

三份文件一起维护,冲突时模型看见的仍只有每层第一份命中的那个。与其同步三份,不如一份 AGENTS.md 进 git,个人差异用 AGENTS.override.md,别的 agent 用它们自己的发现规则或你的 fallback 列表。

这也不是 Skill。Skill 是点名才注入的程序(D1);AGENTS.md 是未信任闸打开后 每轮都在 的项目政策。把「如何用 imagegen」写进 AGENTS.md,等于强迫每个 turn 都吃一份用不到的手册。

也不是 git 署名说明书。ext/git-attribution 往 world state 贡献「agent 怎么署名提交 / PR」的一段(GitAttributionExtension 实现 ContextContributor),那是进程内 Extension(B2),随账号政策开关,不进仓库的 AGENTS.md。项目政策写「用 just test」,署名政策别写进同一份文件。


6. 结语:带走一句话 ​

AGENTS.md 值得写进 git 的,是短而可执行的项目政策——测试命令、禁区、验证方式——靠从 git root 到 cwd 的发现链就近覆盖;长流程、密钥和「请不要」做不到的硬拦截,分别属于 Skill、本机隐私和 ExecPolicy。