第 02 章

AGENTS.md

让 Codex 记住你的项目规则,不再每次重复说明

一份文件,全局生效;一次写入,持久生效

从零开始

你反复解释同一个项目规则,Codex 全忘了

会话一:你教它规矩

"我们用 React + TypeScript,测试用 vitest,组件命名用 PascalCase。"

Codex 照做了。问题解决。

会话二:什么都没记住

你开新会话让它改个组件。它回到老习惯——用 plain JavaScript、camelCase 命名、jest 语法。

你又要解释一遍。第三次。第五次。

根本原因

Codex 是无状态的。每次新会话,之前的对话上下文全部清空。如果你不把规则写进文件,它就不存在。

开始之前

适合谁

  • 已经在用 Codex CLI,发现每次都要重复说相同规则
  • 想为团队统一项目规范,让所有人共享
  • 管理多个项目,需要不同的默认行为

你将学会

  • 创建和配置 AGENTS.md 文件
  • 理解文件发现与拼接机制
  • 用 /init 自动生成、用 /memories 管理
  • 设计多模块项目的分层规范

本章不覆盖

  • Skills(第 03 章):可复用的任务指令
  • MCP(第 06 章):工具扩展
  • 沙箱与权限(第 09 章):安全边界

是什么

给 Codex 的项目级"员工手册"

一句话定义

AGENTS.md 是放在项目中的 Markdown 文件,包含 Codex 应该遵守的指令、约定和背景知识。Codex 每次启动会话时自动加载它。

类似物

  • Claude Code 的 CLAUDE.md
  • Cursor 的 .cursorrules
  • .editorconfig(但面向 AI,不是编辑器)
核心差异:AGENTS.md 不是单一文件。Codex 可以发现并拼接路径上的多个文件——这意味着你可以在子目录放置局部规则,覆盖或补充根级约定。

文件发现机制

Codex 怎么找到你的 AGENTS.md

Step 1: 定位 project root

从当前工作目录(CWD)开始向上搜索,直到找到 project_root_markers 标记的目录。默认标记是 .git。

Step 2: 沿路径收集

从 project root 开始,沿目录树向下往 CWD 方向遍历,收集每一层遇到的 AGENTS.md。

Step 3: 拼接注入

按从根到 CWD 的顺序,将所有发现的 AGENTS.md 内容拼接,注入到系统提示词中。

额外文件名:除了 AGENTS.md,你还可以在 config.toml 中配置 project_doc_fallback_filenames 让它同时扫描 CONTRIBUTING.md、DEVELOPMENT.md 等文件。

发现路径可视化

project root 到 CWD 的完整路径

示意:文件发现从上到下
重要:Codex 是往 CWD 方向搜集,不是整个项目扫描。只在 root→CWD 的这条路径上查找。

作用员规则

一个 AGENTS.md 管多深?

子树覆盖

AGENTS.md 覆盖其所在目录的整个子树。也就是说:src/AGENTS.md 对 src/utils/、src/components/ 等所有后代目录都生效。

更深层优先

当两个 AGENTS.md 的内容冲突时,路径更深的文件优先级更高。src/AGENTS.md 的指令可以覆盖根目录 AGENTS.md 的指令。

scope 关键词(可选)

你可以在 AGENTS.md 中使用 scope 关键词进一步限定适用范围。如果不指定,默认覆盖整个子树。

指令加载链

Codex 启动时,这些指令按顺序拼接进上下文——越靠后越优先

顺序 来源 谁控制 典型内容
① 最先 模型内置 base_instructions OpenAI(不可改) 身份、安全边界、工具使用规则
② ~/.codex/AGENTS.md 你(全局) 跨项目的个人偏好:"始终先跑测试"
③ 项目根 → 子目录的 AGENTS.md 团队 / 你 项目约定:编码规范、测试命令、架构决策
④ 最后 你在对话中输入的 prompt 你(实时) "用 Python 写这个测试"
越靠后 = 优先级越高。后加载的指令在上下文里位置更靠后,模型更倾向于遵循。所以你在对话里实时说的话,会覆盖 AGENTS.md 里的旧约定——但无法覆盖第①层 OpenAI 的安全规则。
注:全局指令写在 ~/.codex/AGENTS.md 里,或在 config.toml 中用 model_instructions_file 指定一个替代文件。详见 官方文档。
冲突时怎么办?AGENTS.md 写"用 Python",你在对话里说"用 Go"——听你现在的。实时 prompt > 预置 AGENTS.md。但 AGENTS.md 的价值在于:你不必每次对话都重复说一遍。

覆盖文件

本地覆盖,不入库

作用

AGENTS.override.md 是可选的个人覆盖文件。它和 AGENTS.md 放在同一目录,优先级高于同级的 AGENTS.md。

典型用途

  • 个人偏好:用户名、邮箱、默认分支名
  • 本地路径:SDK 路径、模拟器配置
  • 实验性指令:不想污染团队规范的个人规则
# .gitignore 中应包含
AGENTS.override.md
为什么叫 override?因为它会替换或覆盖同名文件中的指令,而不是合并。放一颗"炸弹"进去,可以屏蔽掉团队规范中你不适用的部分。

配置项速查

在 config.toml 中自定义

配置项 默认值 作用
project_doc_fallback_filenames [] 额外扫描的文件名(如 ["CONTRIBUTING.md", "ARCHITECTURE.md"])
project_root_markers [".git"] 标记项目根的目录/文件名
# ~/.codex/config.toml 示例
[project]
project_root_markers = [".git", ".hg"]
project_doc_fallback_filenames = [
    "CONTRIBUTING.md",
    "DEVELOPMENT.md",
    "docs/project-rules.md",
]

最小可运行示例

从零创建你的第一个 AGENTS.md

在项目根目录创建一个 AGENTS.md,写入几条核心指令。这就是最小可运行版本——不需要任何特殊语法,就能让 Codex 自动遵守:

# 项目约定

## 技术栈
- React 18 + TypeScript + Vite
- 测试框架:vitest(不是 jest!)
- CSS:Tailwind CSS

## 编码规范
- 组件文件用 PascalCase命名
- 工具函数文件用 camelCase
- 所有导出的函数必须有 JSDoc 注释
- 不使用 any 类型,用 unknown 替代

## 常用命令
- 启动开发服务器:npm run dev
- 运行测试:npm test
- 构建:npm run build
- 类型检查:npm run typecheck

## 架构
- src/components/ — 通用组件
- src/features/ — 业务功能模块(每个子目录是一个独立 feature)
- src/api/ — 所有 API 请求集中在此,用 TanStack Query

写作有效指令

什么该写,什么不该写

✅ 该写的

  • 具体命令:"运行测试用 npm test",不是"跑一下测试"
  • 命名规范:文件命名、变量风格、分支策略
  • 技术决策:不用的库、避免的模式
  • 架构约束:目录职责、模块边界、依赖方向

❌ 不该写的

  • 模糊指令:"写干净的代码"——AI 不知道你的"干净"是什么
  • 项目管理:截止日期、人员分工、任务分配
  • 敏感信息:API 密钥、密码、私有 token
  • 冗长教程:不要在里面写完整的 React 教程

/init 命令

让 Codex 帮你写 AGENTS.md 骨架

是什么

/init 是 Codex CLI 的内置命令。执行后,它会扫描你项目的文件结构、配置文件、依赖清单,然后自动生成一份 AGENTS.md 骨架。

适合场景

  • 新项目,不知道从哪开始写
  • 接手别人的项目,想快速了解规范
  • 项目升级(如从 CRA 迁到 Vite),规则要更新
# 在 Codex 会话中输入
$ /init

# Codex 会分析项目并生成 AGENTS.md 草稿
# 你可以在此基础上编辑调整

/memories

控制当前线程的记忆开关——别和 AGENTS.md 搞混

先澄清一个常见误解:Memories 和 AGENTS.md 是两个完全不同的系统。AGENTS.md 是你手写的静态项目规则(官方文档);Memories 是 Codex 从历史会话中自动提取的动态背景回忆,存在 ~/.codex/memories/,默认关闭(官方文档)。

Memories vs AGENTS.md

对比AGENTS.mdMemories
谁写的你手写Codex 自动提取
存哪项目目录 / ~/.codex/~/.codex/memories/
能否入库✅ 团队共享❌ 本地生成状态
默认状态自动加载默认关闭

/memories 做什么

它是一个开关切换器,为当前线程控制两件事:

  • 当前对话是否使用已有的 memories
  • 当前对话是否生成新的 memories

线程级选择不会改你的全局设置。

启用前提:Memories 默认关闭。需先在 config.toml 中开启:
[features]
memories = true
官方建议:必须遵守的规则放 AGENTS.md,Memories 只当辅助回忆层。
一句话总结:AGENTS.md 是"项目说明书"(你写的,每次必读);Memories 是"经验笔记"(Codex 自动记的,可选参考)。/memories 只管后者。

多模块实战

分层 AGENTS.md 策略

大型项目往往包含多个独立模块。每个模块可能有自己的技术栈和约定。Codex 的多文件继承机制天然支持这种场景:

# 根目录 AGENTS.md(全局适用)
# — 通用约定 —
- 所有 Git 提交遵循 Conventional Commits
- PR 标题格式:type(scope): description
- 默认用 Node.js 20

---

# frontend/AGENTS.md(仅前端模块)
# — Frontend Rules —
- 技术栈:Next.js 14 + TypeScript + Tailwind
- 测试:Playwright(E2E)+ Jest(单元)
- 状态管理:只用 Zustand,不用 Redux

---

# backend/AGENTS.md(仅后端模块)
# — Backend Rules —
- 语言:Python 3.11
- 框架:FastAPI
- ORM:SQLAlchemy 2.0(async)
- 不用 Django、不用 Flask
文件发现验证:进入 frontend/ 目录启动 Codex,它会加载根目录 AGENTS.md + frontend/AGENTS.md,但不会加载 backend/AGENTS.md。

团队 vs 个人

仓库规范 + 本地覆盖

团队 AGENTS.md(入库)

放在 AGENTS.md,提交到 Git。所有人共享。内容聚焦在不可协商的团队约定:技术选型、代码风格、安全红线、架构约束。

个人 AGENTS.override.md(gitignore)

放在 AGENTS.override.md,不入库。存放个人偏好:喜欢的命名风格、本地 SDK 路径、试验性指令。不影响队友。

# .gitignore
AGENTS.override.md
选择规则:如果一条规则"所有人都必须遵守"→ AGENTS.md。如果"对你个人有用但不适合所有人"→ AGENTS.override.md。

实战模板

可直接复制的完整骨架

# 前端项目约定

## 启动与开发
- 安装依赖:pnpm install(必须用 pnpm,不是 npm 也不是 yarn)
- 启动:pnpm dev
- 端口:3000;如需修改,在 .env.local 中设置 PORT

## 技术栈
- Next.js 14 (App Router)
- TypeScript strict mode
- Tailwind CSS + shadcn/ui
- 状态管理:Zustand

## 编码规范
- 组件文件:PascalCase,与组件名一致
- 导出方式:每个组件一个文件,named export
- API 路由:全部放在 app/api/ 目录下
- 错误处理:统一用 ErrorBoundary,try/catch 后必须 log

## 测试策略
- 单元测试:vitest + React Testing Library
- E2E:Playwright(配置在 playwright.config.ts)
- 覆盖率门槛:行覆盖率 ≥ 70%

## 提交规范
- 分支命名:feat/fix/refactor/docs + 简短描述
- 提交格式:type(scope): description
- PR 描述中必须关联 issue 编号

## 禁止事项
- 不使用 any 类型(特殊情况需 code review 批准)
- 不使用 @ts-ignore
- 不在组件内直接调用 fetch(统一走 api/ 层)
- 不提交 .env 文件

常见错误

位置、冲突与长度

❌ 文件放错位置

把 AGENTS.md 放在 src/ 里。当你在项目根目录启动 Codex 时,不会发现它——因为它是从 root 往 CWD 找,root→root 路径上没有 src/AGENTS.md。

❌ 规则互相矛盾

根级说"用 Jest",子级说"用 Vitest"。不明确告诉 Codex 以哪个为准,它会困惑。原则:子级覆盖根级,但语义要清晰,让 AI 推断矛盾。

❌ 文件过长

500 行的 AGENTS.md 不是"详细",是"噪音"。Codex 的上下文窗口有限,太长会导致关键指令被淹没。建议控制在 100 行以内,把细节放到具体文档里。

常见错误补充

别把 AGENTS.md 也忽略了

⚠️ 新手陷阱

为了"保持仓库干净",有些人在 .gitignore 中把 AGENTS.md 也加进去了。结果:队友拉下代码后,Codex 读取不到任何项目规则,全部回到默认行为。

# ❌ 别这样做
# .gitignore
AGENTS.md
AGENTS.override.md

# ✅ 应该只 ignore override 文件
# .gitignore
AGENTS.override.md
记住:AGENTS.md 是团队共享的,必须入版本控制。只有 AGENTS.override.md 是个人本地的,需要 gitignore。

验证生效

写好了,怎么知道有没有用?

方法 1:直接对话测试

问 Codex:"用什么测试框架?"、"目录结构是怎样的?"。如果它能从 AGENTS.md 提取答案,说明机制工作正常。

方法 2:看系统提示词

在 verbose/trace 模式(某些版本支持)下查看 Codex 收到的系统提示词,确认 AGENTS.md 内容确实在其中。

方法 3:对比行为

在同一个目录,有/无 AGENTS.md 分别启动会话,让它做同一个任务。如果输出风格不同,说明配置生效了。

渐进式完善

别想一步到位

阶段 1:写下最痛的点

如果你每次都要说"我们用 vitest 不是 jest"——加一条。完成这一步,你就已经消除了 50% 的重复。

阶段 2:记录实时纠正

当你纠正 Codex 的某个行为时,顺手把正确规则写进 AGENTS.md。这是最自然的增量方式,比事后整理高效得多。

阶段 3:定期审视

每月用 /memories 回顾一次,删掉过时的条目,合并重复的内容。健康的 AGENTS.md 应该像活文档一样演化。

与 Skills

规则 vs 流程

AGENTS.md = 规则

Codex 应该怎么做事。是声明式的:"用 vitest"、"PascalCase 命名"、"不提交 .env"。它是持续生效的项目上下文。

Skills(第 03 章)= 流程

Codex 怎么执行特定任务。是操作性的:"提交 PR 前先跑 lint 和 typecheck"、"发布前先/update changelog"。按需触发。

选择指南:如果一个指令在任何时候都适用 → AGENTS.md。如果只在特定任务或流程中触发 → Skill。两者可以互相引用。

核心回顾

今天你学到了什么

AGENTS.md 本质

项目级指令文件,Codex 自动发现并加载。解决"每次从零开始"的痛苦。

发现与拼接

从 project root(由 .git 标记)向 CWD 方向拼接所有 AGENTS.md 文件。子级优先于根级。

工具链

/init 自动生成骨架;/memories 交互式编辑器;AGENTS.override.md 个人覆盖。

要点清单

下次启动前可以做的事

必做

  • 在你的主要项目根目录创建 AGENTS.md
  • 写进技术栈、测试命令、命名规范三条核心规则
  • 用 /init 快速生成骨架,再编辑

建议做

  • 在 .gitignore 中加入 AGENTS.override.md
  • 用 /memories 记下你个人偏好
  • 每次被 Codex 纠正时,顺手更新 AGENTS.md

警惕

  • 不要忽略 AGENTS.md 本身
  • 不要写超过 100 行
  • 不要让规则互相矛盾
第 02 章

小结

你已经掌握了 AGENTS.md 的核心机制

本章要点

  • AGENTS.md 是项目级指令文件,Codex 自动发现并加载
  • 从 project root 向 CWD 拼接多个文件,子级覆盖根级
  • /init 自动生成,/memories 交互管理
  • 栈规范入库 + personal覆盖 gitignore
下一步:第 03 章 Slash Commands —— 掌握内置的 / 前缀命令,让 Codex CLI 从"聊天"变成"指令操控"。