我刚开始用 Codex 时,以为 AGENTS.md 是项目说明书,后来发现不是。

我现在更愿意把它理解成一份给 Codex 的长期工作约定

每次在这个项目里开始新任务时,先告诉 Codex 这个项目怎么工作、哪些地方不要乱改、改完以后怎么验证。

比如:

Text
这个项目使用 pnpm,不要改用 npm。

修改代码后需要执行 lint 和 build。

没有明确要求时,不要执行 git commit 或 git push。

修改页面以后,需要实际检查受影响页面。

这些不是某一次任务临时提出的要求,而是之后很可能会反复影响 Codex 工作方式的规则。

这种内容就很适合写进 AGENTS.md

反过来,如果只是:

Text
这次不要修改 Header.vue。

这种只对当前任务有效的限制,直接写在当前 Prompt 里更合适。

所以我现在判断一条规则要不要放进 AGENTS.md,只有一个标准:

以后是不是还会反复影响 Codex 在这个项目里的工作。

1. 先让桌面端正确识别项目

如果使用 ChatGPT 桌面端里的 Codex,我会先确认本地项目配置正确。

打开项目后:

  1. 打开项目菜单;
  2. 选择 编辑项目
  3. 选择 添加文件夹
  4. 添加代码仓库;
  5. 将主要代码仓库设置为 主文件夹
  6. 再从这个项目中新建 Codex 任务。

这里的主文件夹非常重要。

ChatGPT 桌面端的本地项目现在可以同时附加多个文件夹,但新聊天会从主文件夹开始。

Codex 也会把主文件夹作为:

Text
默认工作目录

Git 操作目标

AGENTS.md 自动发现起点

Skills 自动发现起点

config.toml 自动发现起点

其他附加文件夹依然可以被 Codex:

Text
搜索
读取
编辑

但不会自动作为 AGENTS.md、Skills 和 config.toml 的项目发现位置。

所以如果项目结构是:

Text
frontend/
backend/
docs/

而我主要让 Codex 修改:

Text
frontend/

通常会把:

Text
frontend/

设置为主文件夹。

如果前后端本来就是一个 monorepo:

Text
my-project/
├── apps/
│   ├── web/
│   └── server/
├── packages/
└── package.json

则更适合直接把:

Text
my-project/

设置为主文件夹。

2. 在项目中创建第一份 AGENTS.md

对于普通项目,我通常先在代码仓库根目录放一份:

Text
AGENTS.md

例如:

Text
my-project/
├── AGENTS.md
├── package.json
├── pnpm-lock.yaml
└── src/

需要注意:

AGENTS.md 并不是技术上只能放在项目根目录。

Codex 支持分层的 AGENTS.md,后面还可以在子目录中增加更具体的规则。

但对于刚开始使用的人,我仍然建议:

第一份项目级 AGENTS.md 放在仓库根目录。

因为这里最适合保存整个项目都应该遵守的规则。

我一般不会直接手写第一版,而是先让 Codex 根据现有项目生成草稿。

例如在桌面端输入:

Text
只在当前项目中创建 AGENTS.md。

先读取 package.json、README、锁文件和现有开发文档,
提取项目中真实存在的启动、测试、Lint 和构建命令。

不要修改业务代码、依赖、配置或其他文件。

如果某个命令无法从项目文件中确认,不要猜,标记为待确认。

这样比直接让它:

Text
帮我生成一个 AGENTS.md

可靠得多。

因为后者很容易生成:

Text
npm test
npm run lint
npm run build

但你的项目可能实际上使用:

Text
pnpm lint
pnpm typecheck
pnpm build

甚至根本没有 test Script。

AGENTS.md 里最危险的不是规则少,而是写了一条项目根本不存在的命令。

3. 新手够用的 AGENTS.md 模板

下面这份是我现在比较推荐的新手模板。

假设项目是:

Text
Vue 3
Vite
pnpm

可以写成:

Markdown
# 项目约定

## 项目说明

- 这是一个 Vue 3 + Vite 项目,主要前端代码位于 `src/`。
- 页面接口封装位于 `src/api/`。
- 修改接口字段前先确认现有调用方式,不要根据字段名自行猜测后端行为。

## 开发与验证

- 项目使用 pnpm,不要改用 npm 或 yarn。
- 需要安装依赖时使用 `pnpm install --frozen-lockfile`。
- 本地开发使用 `pnpm dev`。
- 修改代码后先运行 `pnpm lint`,再运行 `pnpm build`。
- 如果项目存在更精确的测试命令,优先执行与本次改动相关的测试。
- 修改 UI 时,如果当前环境具有浏览器能力并且本地服务可用,实际验证受影响页面。

## 修改边界

- 不要修改 `.env`、锁文件和生成目录,除非当前任务明确要求。
- 新增生产依赖前先说明原因,并获得确认。
- 保留已有的未提交修改。
- 不使用 `git reset --hard`、`git clean -fd` 等可能覆盖现有工作的 Git 命令。

## Git

- 没有明确要求时,不执行 `git commit`。
- 没有明确要求时,不执行 `git push`。
- 修改结束后检查 Git diff,确认没有无关改动。

## 完成标准

最终回复需要说明:

- 修改了哪些文件;
- 实际执行了哪些命令;
- lint、测试和 build 的结果;
- 是否进行了页面验证;
- 哪些内容因为环境限制没有验证。

这里没有什么“高级 Prompt 技巧”。

重点只有两个字:

可执行。

比如:

Text
代码要优雅。

这种规则没有明确标准。

而:

Text
修改 TypeScript 后运行 pnpm lint。

就非常明确。

Codex 知道什么时候需要执行,也知道怎样判断完成。

4. 哪些内容值得放进 AGENTS.md

我现在主要放五类内容。

1. 项目地图

告诉 Codex:

Text
业务代码在哪里

API 在哪里

组件在哪里

测试在哪里

哪些目录是生成出来的

重要文档在哪里

例如:

Markdown
## 项目结构

- 页面位于 `src/views/`。
- 通用组件位于 `src/components/`。
- API 封装位于 `src/api/`。
- Pinia Store 位于 `src/stores/`。
- `src/generated/` 为自动生成内容,不要直接修改。

它不需要把整个目录树复制进去。

只告诉 Codex:

哪些地方容易判断错。

2. 项目真正使用的命令

这是我认为最重要的一部分。

例如:

Markdown
## 验证命令

- Lint:`pnpm lint`
- TypeScript:`pnpm typecheck`
- 单元测试:`pnpm test`
- 构建:`pnpm build`

不要从网上抄。

也不要从自己的另一个项目复制。

必须以当前项目:

Text
package.json
README
CI 配置
Makefile
项目脚本

里的真实命令为准。

3. 修改边界

例如:

Markdown
## 修改边界

- 不要修改生产环境配置。
- 不要修改数据库迁移记录,除非任务明确要求。
- 不要主动升级依赖版本。
- 不要覆盖用户已有的未提交修改。

这一类规则特别适合 Codex。

因为很多时候模型不是“不会写代码”,而是:

顺手改得太多。

4. 项目里不容易推断的知识

比如:

Markdown
## 项目约定

- `/api/admin/*` 只能用于后台管理页面。
- `userId` 来自登录态,不要从 URL 参数自行读取。
- `src/legacy/` 仍在线上使用,不是废弃目录。

这些信息 Codex 很难单纯靠代码结构完全判断出来。

5. 完成标准

例如:

Markdown
## 完成标准

- 修改后检查 diff。
- 执行与本次修改相关的测试。
- UI 改动需要进行页面验证。
- 最终回复列出未验证项。

这可以明显减少一种常见情况:

Text
Codex:
“已经完成。”

我:
“你 build 了吗?”

Codex:
“没有。”

把完成标准提前写进去,比每次任务结束后追问更省事。

5. 哪些内容不要放进去

我不会把下面这些东西塞进 AGENTS.md

密钥和隐私数据

包括:

Text
API Key
密码
Token
Cookie
数据库密码
私钥
生产环境凭据

AGENTS.md 是项目指令,不是密码管理器。

大段接口文档

例如几百行:

Text
API 请求字段
返回字段
状态码
数据库结构

更适合放:

Text
docs/
README
OpenAPI
独立技术文档

然后只在 AGENTS.md 告诉 Codex:

Markdown
修改支付接口前先阅读 `docs/payment-api.md`。

这样更合理。

构建日志和历史错误

不要把一次:

Text
npm ERR!
...
几百行日志

直接永久塞进 AGENTS.md

如果确实存在项目长期坑点,可以浓缩成:

Markdown
- Linux 环境区分文件名大小写,修改组件路径时必须检查 Git 中的真实大小写。

保存结论,而不是保存整段历史记录。

一次性任务要求

比如:

Text
这次只修改登录页面。

今天不要修改接口。

这一个任务不要执行 build。

这些直接写当前 Prompt。

否则几个月以后看到它,你可能已经完全忘了为什么存在。

真正需要强制执行的安全控制

例如:

Text
永远禁止访问某个目录。

绝不能执行某个危险命令。

绝不能访问网络。

可以在 AGENTS.md 中提醒 Codex,但不能把它当成真正的安全边界

AGENTS.md 本质上仍然是自然语言指令。

真正需要控制:

Text
文件访问
网络访问
命令执行
越出工作区
危险命令

应该依靠:

Text
Sandbox
Permissions
Approvals
Rules

来限制。

所以:

AGENTS.md 是工作约定,不是权限系统。

6. AGENTS.md 不要写得无限长

我刚开始很容易犯一个错误:

既然 Codex 每次都会读,那干脆把所有项目资料都塞进去。

实际上并不好。

规则越多:

Text
真正重要的信息越难突出
上下文占用越大
过期内容越难维护
规则之间越容易冲突

而且 Codex 对自动发现的项目指令还有大小预算。

项目指令链默认受:

Text
project_doc_max_bytes

限制,默认值是:

Text
32 KiB

达到限制以后,后面的指令文件可能不会继续加入。

所以我不会追求:

Text
AGENTS.md 越完整越好

而是追求:

Text
每一条留下来的规则都真的有用

我更倾向于:

Text
刚开始:
10~30 行

遇到一次重复问题:
考虑增加一条

几个月没意义:
删除

把它当成一份活的项目工作约定

7. 子目录有特殊规则时,再增加一层

小项目通常一份根目录:

Text
AGENTS.md

就够了。

例如:

Text
my-project/
├── AGENTS.md
├── src/
└── package.json

但如果是大型项目:

Text
my-project/
├── AGENTS.md
├── frontend/
├── backend/
└── services/
    └── payment/

不同区域可能有完全不同的规则。

这时可以增加:

Text
services/payment/AGENTS.md

例如根目录:

Markdown
# AGENTS.md

## 通用规则

- 修改 TypeScript 后运行 `pnpm lint`。
- 不要修改生产环境配置。

支付目录:

Markdown
# services/payment/AGENTS.md

## 支付服务额外规则

- 修改支付服务后运行 `pnpm test:payment`。
- 不要修改生产支付回调地址。
- 不要轮换任何支付密钥。

不过这里有一个非常容易理解错的地方:

Codex 并不是扫描整个仓库,把所有子目录里的 AGENTS.md 一次性全部加载。

它会从:

Text
项目根目录
↓
当前工作目录

沿着这条目录路径查找指令。

比如当前工作目录是:

Text
my-project/services/payment/

它可能组成:

Text
my-project/AGENTS.md
+
my-project/services/AGENTS.md
+
my-project/services/payment/AGENTS.md

越靠近当前工作目录的规则出现在越后面,因此在冲突时具有更高优先级。

但如果当前会话的工作目录只是:

Text
my-project/

就不要想当然地认为:

Text
services/payment/AGENTS.md

一定会因为你修改了支付目录里的某个文件而自动进入当前任务的指令链。

对于桌面端尤其要记住:

新聊天默认从项目的主文件夹开始。

所以需要整个仓库始终遵守的规则,最好还是放根目录。

子目录规则留给真正具有独立工作范围的模块。

8. AGENTS.override.md 是干什么的

Codex 除了:

Text
AGENTS.md

还支持:

Text
AGENTS.override.md

这个名字很容易让人理解成:

再额外加一份更高优先级规则。

实际上需要更准确一点理解。

Codex 在每一层目录会依次检查:

Text
AGENTS.override.md
↓
AGENTS.md
↓
配置中的 fallback 文件名

并且:

每一个目录最多只选择其中一个文件。

也就是说,同一个目录里同时存在:

Text
AGENTS.md
AGENTS.override.md

那么这一层使用的是:

Text
AGENTS.override.md

普通:

Text
AGENTS.md

在这一层不会同时被加入。

例如:

Text
my-project/
├── AGENTS.md
└── services/
    └── payment/
        ├── AGENTS.md
        └── AGENTS.override.md

如果当前工作目录是:

Text
services/payment/

那么最终可能是:

Text
根目录 AGENTS.md
+
payment/AGENTS.override.md

而不是:

Text
根目录 AGENTS.md
+
payment/AGENTS.md
+
payment/AGENTS.override.md

所以新手阶段我通常:

不用 AGENTS.override.md

只有真的需要:

Text
临时覆盖
特殊模块覆盖
特殊工作模式

时再使用。

否则以后很容易出现:

我明明改了 AGENTS.md,为什么 Codex 完全不听?

结果找半天发现旁边还有一个:

Text
AGENTS.override.md

9. 修改 AGENTS.md 后,怎么确认真的生效

保存 AGENTS.md 以后,我会新建一条 Codex 任务。

这是因为 Codex 会在一次新的运行或 Session 开始时构建当前的指令链。

修改已有 AGENTS.md 后,新建任务或重新启动 Codex 是最稳妥的方式。

然后我会先做一个只读测试

例如:

Text
按照当前项目约定,告诉我:

1. 这个项目使用什么包管理器;
2. 修改代码后需要执行哪些验证命令;
3. Git commit 和 git push 有什么限制;
4. 哪些文件或目录默认不要修改。

不要修改文件,也不要执行任何命令。

如果我的 AGENTS.md 写着:

Text
pnpm
pnpm lint
pnpm build
不主动 commit
不主动 push

Codex 正确回答了这些内容,基本就说明项目规则已经进入当前任务。

如果没有生效,我会检查:

Text
文件名是否准确叫 AGENTS.md

文件是否为空

桌面端主文件夹是否选对

当前任务的工作目录是否正确

是否存在 AGENTS.override.md

是否刚修改完规则但仍在旧任务中

如果依然表现异常:

Text
完全退出 Codex
↓
重新打开
↓
从正确项目创建新任务

再测试一次。

10. 全局 AGENTS.md 和项目 AGENTS.md

除了项目中的:

Text
项目根目录/AGENTS.md

Codex 还支持用户级的全局规则。

默认位置是:

Text
~/.codex/AGENTS.md

例如可以放:

Markdown
# 全局工作习惯

- 默认使用中文解释问题。
- 修改代码前先读取相关文件。
- 不主动执行 git push。

这些规则会作用于不同项目。

Codex 加载顺序大致是:

Text
全局规则
↓
项目根目录规则
↓
更深层目录规则

更具体的项目规则出现在后面。

不过我不建议刚开始就把大量内容写进全局规则。

原因很简单:

Text
Vue 项目的规则
不应该影响 Node 项目

公司项目规则
不应该影响个人项目

某一个仓库的特殊命令
不应该影响所有仓库

所以我的习惯是:

Text
个人长期习惯
→ ~/.codex/AGENTS.md

项目长期规则
→ 项目/AGENTS.md

模块特殊规则
→ 子目录 AGENTS.md

临时任务要求
→ 当前 Prompt

这样最不容易乱。

11. AGENTS.md 和 Skill 怎么分工

这两个东西刚开始也很容易混。

我现在只用一句话判断:

每次工作都要遵守的,写进 AGENTS.md;只有某一种任务发生时才需要执行的流程,做成 Skill。

例如:

Text
所有 UI 改动都必须进行页面验证

属于项目长期规则:

Text
AGENTS.md

而:

Text
每次正式发版前:
检查版本号
生成 changelog
执行测试
检查 Git 状态
生成发布报告

只在:

Text
发版

这个任务发生时使用。

更适合做:

Text
release-check Skill

再比如:

要求 更适合放哪里
项目统一使用 pnpm AGENTS.md
不主动执行 git push AGENTS.md
UI 修改后进行浏览器验证 AGENTS.md
发版前跑完整检查 Skill
PR Review 执行固定检查流程 Skill
根据模板生成发布记录 Skill

这样可以避免:

Text
AGENTS.md

最后越来越像一本几百行的操作手册。

12. 我现在会怎么维护 AGENTS.md

我不会在项目第一天就试图写一份“完美的 AGENTS.md”。

更实际的方法是:

Text
先写最基本的十几条规则
↓
开始正常使用 Codex
↓
发现 Codex 重复踩同一个坑
↓
判断是不是长期规则
↓
如果是,再补进 AGENTS.md

比如第一次:

Text
Codex 使用了 npm,但项目要求 pnpm。

我会补:

Markdown
- 项目统一使用 pnpm,不使用 npm 或 yarn。

后来又出现:

Text
Codex 修改代码以后直接说完成,没有 build。

再补:

Markdown
- 修改代码后运行 `pnpm lint` 和 `pnpm build`。

又发现:

Text
它为了修问题顺便执行了 git reset。

再补:

Markdown
- 保留用户已有未提交修改,不执行覆盖性 Git 命令。

久而久之,这份文件就会变成:

真正来自项目实践的工作约定。

而不是一份从网上复制来的“AI Prompt 大全”。

13. 最后检查清单

发布或正式使用一份 AGENTS.md 前,我会检查:

  1. 桌面端项目的主文件夹是否正确;
  2. 根目录 AGENTS.md 是否只包含整个项目都长期适用的规则;
  3. 所有命令是否真的存在于当前项目;
  4. 是否写清楚修改边界;
  5. 是否写清楚验证方式和完成标准;
  6. 是否避免了密码、Token、Key 和其他敏感信息;
  7. 是否没有塞入大量接口文档和历史日志;
  8. 是否存在容易忘记的 AGENTS.override.md
  9. 子目录规则是否真的与当前工作目录范围对应;
  10. 是否把真正的安全限制交给 Sandbox、Permissions 或 Rules;
  11. 修改规则后是否使用新任务进行了只读验证;
  12. 文件是否仍然足够短,重要规则能不能一眼看到。

如果这十二项基本都没问题,这份 AGENTS.md 对普通项目已经完全够用了。

总结

我现在不会把 AGENTS.md 当成:

Text
项目百科全书

也不会把它当成:

Text
万能 Prompt

它更像一张 Codex 加入项目第一天就应该看到的:

工作约定。

我只写那些:

Text
会重复发生

Codex 不容易自己判断

判断错了会造成额外工作

以后仍然长期有效

的规则。

对于一个普通前端项目,其实几十行已经可以解决很多问题:

Text
项目结构
+
真实命令
+
修改边界
+
验证要求
+
Git 规则
+
完成标准

剩下的大量:

Text
架构说明
接口文档
设计文档
业务知识

继续放在它们本来应该存在的位置。

让:

Text
AGENTS.md

只负责告诉 Codex:

在这个项目里,你应该怎样工作。

这反而是我认为最好维护、也最有效的写法。

阅读进度 0%