Codex CLI 入门:安装、AGENTS.md、审批模式与沙箱、常用命令
装好 Codex CLI,搞清它靠什么理解你的项目、靠什么防止它乱动文件,并用它完成第一个真实任务。
今日目标
- 能装好 Codex CLI 并用 ChatGPT 账号或 API key 登录,跑通第一个任务
- 能说清 AGENTS.md 的查找顺序、拼接规则和大小上限,并给自己的项目写一份
- 能解释 approval_policy 与 sandbox_mode 两组开关分别管什么,并按任务风险选组合
这门课不重讲怎么跟模型说话——四要素、少样本示例、思维链这些基础在提示词工程课 D1 里已经讲透,这里默认你会写一段清楚的需求。今天要解决的是另一件事:当模型不再只是「回答」,而是真的在你的仓库里改文件、跑命令时,你怎么把项目交代清楚,又怎么防止它越界。读完做完,回到页面顶部把三条目标勾掉。
小白版讲解
Codex 是什么:一个跑在你终端里的编程搭档
先说一个场景。你手上有一个小项目,来了一位新搭档,是另一家公司派来的外援:能力不差,但对你的项目一无所知,也不知道你们团队的规矩。你会怎么带他?大概三步:第一,给他一份入职手册,说清项目怎么装、怎么测、哪些地方不能碰;第二,头几天他要改东西之前得先问你一声;第三,给他一台只装了必要工具的电脑,别一上来就给生产库的密码。这门课的类比就是这个——同一件活,交给两位不同公司的搭档:这门课讲 OpenAI 派来的这位(Codex),隔壁的 Claude 高效使用课讲 Anthropic 派来的那位(Claude Code),最后一天我们把两位放在同一个任务上实测。要比的是工作方式,不是谁更聪明。
Codex 是 OpenAI 的 coding agent 产品线的统称,有好几个入口:终端里的 Codex CLI、编辑器里的 IDE 扩展、桌面上的 Codex 应用、跑在 OpenAI 服务器上的云端任务,还有挂在 GitHub 上的代码审查。今天只讲 CLI,因为它最透明——每一步读了什么文件、跑了什么命令都打在你眼前,最适合建立直觉;其它入口明天讲。CLI 本身是开源的,仓库在 openai/codex,用 Rust 写成,这意味着它启动快、也能在你的机器上做真正的系统级沙箱(下面会讲)。
它跟你在 ChatGPT 网页里聊代码的区别是什么?一句话:它有手。网页里的模型只能给你一段代码,复制粘贴、跑测试、看报错、再改,这个循环是你在转;Codex 把这个循环搬到了它自己身上——读你的文件、改、跑测试、看报错、再改,直到测试通过或者它卡住来问你。这正是 30 天课 D1 里那个公式「Agent = 模型 + 循环 + 工具 + 记忆」在编程场景里的具体样子:工具是文件读写和 shell,记忆是当前会话加上你写的项目说明。理解了这一点,后面所有「它为什么要问我」「它为什么读不到那个目录」的问题都有了答案:因为它是一个在你机器上执行动作的程序,不是一个只会说话的窗口。
安装与登录:五分钟装好,两种身份
安装只有一条命令,用 npm 或 Homebrew 都行:
npm install -g @openai/codex
# 或
brew install --cask codex装好以后在任何一个项目目录里敲 codex,第一次会让你登录。两种身份可选:用 ChatGPT 账号登录(走 OAuth,用你的 ChatGPT 订阅额度),或者用 API key(走你的 OpenAI 平台账单)。对个人学习者,用 ChatGPT 账号最省事;对团队或 CI 场景,API key 更可控,因为它可以按项目发、按项目撤。codex login 这条子命令可以单独重新登录或切换身份。
登录后你会看到一个全屏的终端界面,底部是输入框。先别急着提需求,敲一个 / 看看它列出的斜杠命令——/permissions(改审批与沙箱)、/review(审代码)、/clear(开新会话)、/rename(给会话起名)。这些命令是今天的主角之一,先记住它们存在。
AGENTS.md:Codex 的入职手册
回到新搭档的类比。他来的第一天,你最该给他的不是任务,是入职手册:项目怎么装、怎么跑测试、目录结构大概什么样、哪些是老代码别碰、提交信息什么格式。没有这份手册,他每次上手都要重新摸索,而且大概率会用他上一家公司的习惯来做事。Codex 的这份手册就是 AGENTS.md——一个放在仓库里的普通 Markdown 文件,Codex 在每次会话开始时把它读进上下文,当成对项目的「已知事实」。
它的查找规则值得记准,因为这决定了「规则写在哪才生效」:
- 全局层:先看
~/.codex/AGENTS.override.md,没有就看~/.codex/AGENTS.md。这是你个人跨项目的习惯,比如「回复用中文」「提交前一定跑 lint」。 - 项目层:从项目根目录一路走到你当前所在的子目录,每一层都找
AGENTS.override.md,没有就找AGENTS.md。找到的文件从根到当前目录依次拼接,中间用空行连起来。
拼接顺序有个直接后果:越靠近当前目录的文件出现在合并后提示的越后面,所以会覆盖前面的规则。这就是为什么你可以在根目录写「测试用 vitest」,在 legacy/ 子目录里再写一份「这个目录用 mocha,别改成 vitest」——在 legacy/ 下工作时,后一条会赢。
还有一个上限:所有拼起来的内容总大小默认 32 KiB,超过就不再往里加,配置项叫 project_doc_max_bytes,可以在 ~/.codex/config.toml 里调。这个上限不是障碍,而是提醒——入职手册不是百科全书。它逼着你只写「Codex 自己发现不了、又必须知道」的东西。一份好的 AGENTS.md 长这样:
# 项目:TODO API
## 怎么跑
- pnpm install && pnpm dev(端口 3181)
- 测试:pnpm test(vitest,改完代码必跑)
## 规矩
- 输入校验统一用 zod,不要手写 if 判断
- 不要改 src/legacy/ 下的任何文件
- 提交信息用 Conventional Commits,中文描述
## 已知坑
- pnpm test 前要先起 docker compose 里的 postgres注意它没写「这是一个用 Express 写的 TODO 应用,有三个路由」——这些 Codex 打开 package.json 和 src/ 自己就能看出来,写了只是浪费那 32 KiB。写的全是约定(用 zod 不用 if)、禁区(legacy 不能碰)和它猜不到的环境事实(测试前要起数据库)。这跟 Claude Code 的 CLAUDE.md 思路完全一致,只是文件名和查找规则略有差别——D5 会把两份手册摆在一起看。
审批模式与沙箱:两组独立的开关
新搭档要改东西了。你有两个互相独立的问题要回答:他动手之前要不要先问我? 以及 他的电脑上到底能碰到什么? 前者是流程问题,后者是权限问题。很多人把它们混成一个「安全级别」,其实 Codex 把它们拆成了两组配置,理解这一点,绝大多数关于「它为什么又问我」的困惑都能自己解决。
第一组:approval_policy,管什么时候问你。 四个取值:
| 取值 | 含义 |
|---|---|
untrusted | 只有明显安全的只读操作自动放行,其它命令执行前都问 |
on-request | 默认。在沙箱内的操作不问;需要越出沙箱(比如联网、写工作区外的文件)时才问 |
on-failure | 先在沙箱里跑,失败了再问你要不要放开限制重跑 |
never | 从不问;越不出沙箱的事就直接失败 |
第二组:sandbox_mode,管能碰什么。 三个取值:
| 取值 | 含义 |
|---|---|
read-only | 只能读文件,改文件和跑会写盘的命令都要审批 |
workspace-write | 默认。可以读,可以改当前工作区内的文件,可以跑常规本地命令;工作区外和网络默认不通 |
danger-full-access | 不设沙箱,名字里的 danger 是认真的 |
这两组可以任意组合,命令行上分别用 -a(--ask-for-approval)和 -s(--sandbox)指定,会话中用 /permissions 改。文档里给了三个常见组合的名字:Auto(workspace-write 加 on-request,有 git 的目录默认就是它)、Read-only(read-only 加 on-request,只让它看、让它讲,适合摸清一个陌生仓库)、Full access(--dangerously-bypass-approvals-and-sandbox,别名 --yolo,只该出现在一次性容器里)。你以前可能见过 --full-auto 这个旗标,它已经标记为废弃,等价于 --sandbox workspace-write。
沙箱是怎么做到「不能碰」的?不是靠提示词,是靠操作系统:macOS 上用系统自带的 Seatbelt,Linux 上用 bubblewrap 做用户命名空间隔离,Windows 上有原生沙箱,WSL2 里走 Linux 那套。所以当它在 workspace-write 下试图往 ~/.ssh 写东西,失败的不是「模型决定不写」,而是内核拒绝了那次写入。网络默认是关的,需要联网(比如 npm install)时要在 config.toml 的 [sandbox_workspace_write] 段里打开 network_access = true,或者在它请求时临时批准。
常用命令:交互、脱手、续上
Codex CLI 的命令不多,够用的就下面几个,按「你在不在旁边」分成三类。
你在旁边,交互式:直接敲 codex 进入全屏界面,或者 codex "把 src/todo.ts 的输入校验换成 zod" 带着第一句需求进去。会话里用 /permissions 改权限,用 /review 让它审当前改动(明天细讲),用 /clear 开新会话,用 /rename 给这次会话起个名字方便日后找回来。
你不在旁边,脱手跑:codex exec "……"(别名 codex e)不开界面,把需求直接扔给它,结果流式打到标准输出,也可以输出 JSONL 方便脚本解析。这是把 Codex 接进 CI 或者批处理脚本的入口——比如夜里跑一遍「给所有没有测试的模块补测试骨架」。注意脱手意味着没人点头,所以它通常和更严的沙箱、以及一个能随便弄坏的分支搭配。
回来接着干:codex resume 续上最近一次会话,或者按 id 续上某一次;codex fork 从一次旧会话分叉出新会话,保留原来的记录——适合「同一个起点试两种方案」。
一个小技巧:codex exec 加上 -s read-only,就是一个很好的「代码讲解器」。比如接手别人的仓库,先跑一句 codex exec -s read-only "用中文解释这个项目的目录结构和启动流程",几十秒后你就有了一份不会改动任何文件的导读。
第一个真实任务:给 TODO API 补输入校验
现在把今天学的东西串起来,做本课贯穿五天的示例任务:给一个 Express 或 FastAPI 写的 TODO API 补上输入校验和对应的单元测试。今天先做前半——输入校验,测试留到 D2 派到云端去做,D5 再拿它和 Claude Code 对比。
先准备一个最小的起点。下面是一个没有任何校验的创建接口,两个版本教的是同一件事:
import express from 'express'
const app = express()
app.use(express.json())
const todos: Array<{ id: number; title: string; done: boolean }> = []
// 问题:title 可以是空字符串、可以不是字符串、done 可以是任何东西
app.post('/todos', (req, res) => {
const { title, done } = req.body
const todo = { id: todos.length + 1, title, done: Boolean(done) }
todos.push(todo)
res.status(201).json(todo)
})
app.listen(3181)from fastapi import FastAPI, Request
app = FastAPI()
todos: list[dict] = []
# 问题:直接读原始 JSON,title 可以是空的、可以不是字符串
@app.post("/todos", status_code=201)
async def create_todo(request: Request):
body = await request.json()
todo = {"id": len(todos) + 1, "title": body.get("title"), "done": bool(body.get("done"))}
todos.append(todo)
return todo然后照前面那份样例给项目写一个 AGENTS.md,至少写清「校验统一用 zod(或 pydantic)」「测试用什么跑」两条。接着在项目根目录起 codex,保持默认的 Auto 权限,把需求交代清楚:
给 POST /todos 补上输入校验:title 必须是 1 到 200 字的非空字符串,done 可选且必须是布尔值。
校验失败返回 400 和一个 { error: string } 形状的 JSON。校验用 AGENTS.md 里规定的库。
改完跑一次测试确认没有破坏现有行为,最后用一句话告诉我你改了哪几个文件。跑起来以后,别只盯着最后的结果,观察它的过程:它先读了哪些文件(应该先看 AGENTS.md 和 package.json);它是不是按你规定的库来做校验(这是 AGENTS.md 生效的证据);它跑 pnpm test 的时候有没有弹审批(默认 Auto 下,本地测试命令在沙箱内,不该弹);如果它想 npm install zod,这一步会弹审批,因为要联网——这就是「网络默认关」在起作用。等它结束,用 git diff 看改动,你会发现它做的事跟一个认真读了入职手册的新同事很像:改了该改的文件,没碰不该碰的目录,最后还告诉你改了什么。
这次任务里最值钱的不是那几行校验代码,而是你亲眼看到了三样东西各自的作用:AGENTS.md 决定它按什么规矩做,沙箱决定它做不到什么,审批决定哪些事必须经过你。这三样东西的组合,就是 coding agent 从「会写代码的聊天窗口」变成「可以放心交活的搭档」的全部秘密。
源码导读
动手实验
今天是文档型实验,没有要 pnpm install 的代码,产出物就是那份 AGENTS.md。starter/ 里是挖了空位的模板,solution/ 是给本课 TODO API 写好的一份,照着它的结构填你自己的项目。
- 在自己的项目根目录跑一次
codex,先不放 AGENTS.md,让它「解释这个项目怎么启动和测试」,记下它猜错或没找到的地方——这些就是手册该写的内容。 - 照
starter/AGENTS.md的模板填空:怎么装、怎么测、哪些目录不能碰、提交信息格式,每一条都是它上一步没猜到的。 - 把一条规则挪进某个子目录的 AGENTS.md 并写成相反的内容,
cd进去再跑同一个任务,确认它遵守的是子目录那条。 - 用
codex -s read-only和默认权限各跑一次「补输入校验」任务,记录每一次审批弹在哪一步、你批了什么。 - 回头删:凡是它打开
package.json或src/自己就能看出来的信息,从 AGENTS.md 里删掉,直到只剩约定、禁区和环境事实。
面试题
今天 3 道题在下方题库区,侧重 coding agent 的项目上下文注入方式、审批与沙箱的边界,以及怎么向团队解释风险控制。展开后先看「分析过程」再看要点——照着推导练,比背要点管用。
检查清单与明日预告
- 能装好 Codex CLI 并用 ChatGPT 账号或 API key 登录,跑通第一个任务
- 能说清 AGENTS.md 的查找顺序、拼接规则和大小上限,并给自己的项目写一份
- 能解释 approval_policy 与 sandbox_mode 两组开关分别管什么,并按任务风险选组合
- 能说出「文字规则管应该、运行时限制管不能」这句话在 Codex 里分别对应什么
- 实验的 4 条验收标准全部通过
- 3 道面试题不看要点也能答出至少 2 道
明天(D2)我们把 Codex 从终端里的一个会话,扩展成一整套工作方式:把任务派到云端容器里并行跑、让它在 GitHub 上审 PR、用 MCP 给它接外部工具、在 IDE 里随手把选中的代码交给它。先学本地 CLI 再学云端是有意的:云端任务的审批边界、环境配置,全都是今天这两组开关和 AGENTS.md 在另一台机器上的翻版——本地搞懂了,云端只是换个地方。
面试题库
给 coding agent 写的项目说明文件(比如 Codex 的 AGENTS.md)应该写什么、不该写什么?为什么它要有大小上限?What belongs in a project instruction file for a coding agent (such as Codex's AGENTS.md), what does not, and why is there a size limit?
国内高频海外高频基础#coding-agent#context#agents-md分析过程 · 先想清楚再作答
- 这题考的不是文件格式,而是你对「上下文是有限资源」有没有工程直觉。把它答成「写项目介绍」会被判为没真用过。
- 拆法是一个判断句:这条信息 agent 打开文件自己能不能发现?能发现的不写(目录结构、用了什么框架),发现不了的才写(约定、禁区、环境事实、测试命令)。
- 再补一层查找规则:全局层在用户目录,项目层从根目录到当前目录依次拼接,越靠近当前目录越靠后、越优先,所以子目录可以覆盖根规则。
- 大小上限(Codex 默认 32 KiB)的意义是逼你做取舍:手册太长会挤占任务本身的上下文,还会让模型对每一条规则的遵守度下降。
- 可预期的追问:写在说明文件里的规则模型一定会遵守吗?不一定,它是提示词的一部分,会被长对话稀释;硬约束要靠沙箱与审批,不是靠文字。
How to reason about it · think before answering
- This probes whether you treat context as a scarce resource, not whether you know the file format; answering with a project overview signals inexperience.
- Use one test: can the agent discover this by opening files? If yes, leave it out (directory layout, framework); if no, write it down (conventions, no-go areas, environment facts, test commands).
- Add the lookup rules: a global file in the home directory, then project files concatenated from the repo root down to the current directory, so closer files override earlier ones.
- The size cap (32 KiB by default in Codex) forces prioritization: a long manual crowds out the task and dilutes adherence to every rule.
- Expect the follow-up: will the model always obey the file? No, it is prompt text and fades over long sessions; hard limits belong to the sandbox and approvals.
答题要点
- 写约定、禁区、环境事实和验证命令;不写 agent 自己打开文件就能发现的内容
- 查找顺序是全局文件在前、项目文件从根到当前目录拼接,越靠近当前目录越优先
- 大小上限逼你只保留高价值信息,避免挤占任务上下文、降低规则遵守度
- 文字规则是建议性的,真正不能越的线交给沙箱与审批
Key points
- Write conventions, no-go areas, environment facts and verification commands; skip anything discoverable from the files
- Lookup goes global first, then project files concatenated root-down, with closer files taking precedence
- The size cap forces you to keep only high-value guidance so the task itself keeps its context budget
- Instruction files are advisory; hard limits come from the sandbox and approval policy
Codex 把「什么时候问用户」和「能碰到什么」拆成 approval_policy 和 sandbox_mode 两组独立开关。为什么要拆?各自解决什么问题?Codex splits 'when to ask the user' and 'what can be touched' into two independent settings, approval_policy and sandbox_mode. Why separate them, and what does each solve?
国内高频海外高频进阶#coding-agent#security#sandbox分析过程 · 先想清楚再作答
- 题眼是「为什么拆」。只背出每组的取值等于没答,面试官要听的是两者正交带来的好处。
- 先给定义:审批策略是流程控制,决定动作执行前要不要人点头;沙箱是权限控制,决定即使模型想做、操作系统允不允许。
- 再说为什么正交:你可能想要「不打扰我,但绝不许出工作区」(on-request 加 workspace-write),也可能想要「每步都问,但只让它读」(untrusted 加 read-only);合成一个滑杆就表达不了这两种组合。
- 落到实现:沙箱靠操作系统机制(macOS Seatbelt、Linux bubblewrap),不是靠模型自觉,所以它是硬约束;审批则是唯一由人把关的环节。
- 可预期的追问:为什么网络默认关?因为联网是把内部代码送出去或把外部代码拉进来的通道,风险等级和改本地文件不同,需要单独授权。
How to reason about it · think before answering
- The discriminating part is 'why separate'; reciting the values without explaining orthogonality earns little.
- Define both: approval policy is process control, whether a human must nod before an action; sandbox is permission control, whether the OS allows the action at all.
- Then justify orthogonality with combinations a single slider cannot express: 'do not interrupt me but never leave the workspace' versus 'ask every time but read-only'.
- Ground it in implementation: the sandbox uses OS mechanisms (Seatbelt on macOS, bubblewrap on Linux) rather than model goodwill, so it is a hard limit, while approval is the one human checkpoint.
- Expect the follow-up: why is network off by default? Because network is the channel for code leaving or entering the machine, a different risk class from local edits.
答题要点
- approval_policy 管流程:untrusted / on-request / on-failure / never 决定动作前是否要人确认
- sandbox_mode 管权限:read-only / workspace-write / danger-full-access 决定操作系统放行什么
- 两者正交才能表达「不打扰但不越界」和「步步问但只读」这类组合
- 沙箱是操作系统级硬约束,审批是唯一的人工把关点;网络默认关闭需单独放开
Key points
- approval_policy governs process: untrusted / on-request / on-failure / never decide whether a human confirms first
- sandbox_mode governs permission: read-only / workspace-write / danger-full-access decide what the OS allows
- Orthogonality lets you express 'no interruptions but stay in the workspace' and 'ask each step but read-only'
- The sandbox is an OS-level hard limit, approval is the human checkpoint, and network is off by default
你要在团队里引入一个能在本地执行命令的 coding agent,怎么向不放心的同事解释它的风险边界?You want to introduce a coding agent that runs commands locally. How do you explain its risk boundary to skeptical teammates?
国内高频海外高频进阶#coding-agent#security#communication分析过程 · 先想清楚再作答
- 这题考的是沟通加工程两层:既要说清技术上的边界,又要用对方能验证的方式说,不能只说「它很安全」。
- 拆成三层防线来讲:第一层文字规则(AGENTS.md)管习惯;第二层沙箱管能力,只读或只能写工作区、网络默认关;第三层审批管例外,越界的每一步都要人批。
- 给出可验证的承诺:所有改动都在 git 工作区里,`git diff` 能看、`git checkout` 能撤;脱手运行只跑在一次性分支或容器里。
- 主动说出剩余风险:模型可能误读需求写出错误但能通过的代码,所以审查和测试不能省;密钥不要放在它能读到的文件里。
- 可预期的追问:能不能完全禁止它联网?可以,沙箱默认就不通网,需要装依赖时逐次批准,或在配置里给一个允许的域名清单。
How to reason about it · think before answering
- This tests communication as much as engineering: state the technical boundary in terms the listener can verify, not just 'it is safe'.
- Present three layers of defense: written rules (AGENTS.md) shape habits; the sandbox limits capability to read-only or workspace-only writes with network off; approvals gate every exception.
- Offer verifiable guarantees: every change lands in the git working tree, visible via diff and revertable via checkout; unattended runs stay on throwaway branches or containers.
- Name the residual risk yourself: the model can misread a requirement and produce wrong but passing code, so review and tests remain mandatory, and secrets stay out of readable files.
- Expect the follow-up: can network be fully blocked? Yes, the sandbox is offline by default; approve installs case by case or configure an allow-list of domains.
答题要点
- 三层防线:文字规则管习惯、沙箱管能力、审批管例外
- 改动全在 git 工作区,可 diff 可撤销;脱手运行只在一次性分支或容器
- 主动说明剩余风险:错误但能通过的代码、密钥暴露,所以审查与测试不能省
- 网络默认关闭,联网按次批准或配置允许域名清单
Key points
- Three layers: written rules for habits, the sandbox for capability, approvals for exceptions
- All edits live in the git working tree and are diffable and revertable; unattended runs use throwaway branches or containers
- State residual risks yourself: wrong-but-passing code and secret exposure, hence mandatory review and tests
- Network is off by default; approve per request or configure an allow-list
评论
登录后即可参与讨论
还没有评论,来说第一句。