← 极客知识库本地镜像
主流 Agent 入门教程 · AGENTS.md / Skills / MCP / 自动化

Codex

从任务规划到代码交付,掌握 Codex 的开发工作流。

来源 time.geekbang.org/space/wiki/Codex_Tutorial 27 讲 主流 Agent 入门教程

01 学习交流群

知识库之外,我们还建了「主流 Agent 入门交流群」。

进群和大家一起交流主流 Agent 的使用方法、适用场景和入门实践,分享不同工具的上手经验、工作流与真实案例,也会同步专题最新更新和实战资料。

扫码加入,一起找到适合自己的 Agent,真正用起来。

【知识库】主流 Agent 入门交流群


02 Codex是什么

预计阅读时间:12 分钟
本篇目标:理解 Codex 的定位、工作方式和几种使用入口,知道什么任务适合交给它。

如果你以前用过 ChatGPT,一开始很容易把 Codex 理解成“更会写代码的聊天机器人”。这个理解不能说完全错,但会让你低估它。

普通对话工具通常停留在“告诉你怎么做”:你把报错贴进去,它解释原因,再给你一段代码。至于找到对应文件、修改代码、运行测试和检查结果,通常还得由你自己完成。

Codex 更像一个可以进入工作现场的协作者。只要你把它放进一个项目目录,并授予合适的权限,它就可以读取项目文件、搜索代码、运行命令、修改文件、执行测试,再根据测试结果继续调整。

这也是为什么 Codex 被称为 Coding Agent,而不只是代码生成工具。

先用一个例子理解 Codex

假设你接手了一个陌生项目,运行后发现“导出订单”功能报错。

如果使用普通对话工具,你可能要自己完成下面这些事情:

  1. 找到与订单导出有关的文件。
  2. 把部分代码复制到聊天窗口。
  3. 把错误日志也复制进去。
  4. 根据回答修改代码。
  5. 回到终端运行测试。
  6. 如果还有错误,再把新错误复制回去。

使用 Codex 时,你可以在项目目录中启动它,然后直接说:

订单导出功能运行时报错。请先阅读项目说明和相关代码,复现问题,解释根因,
然后给出最小修复方案。修改完成后运行相关测试,不要改动无关文件。

接下来,Codex 可以自己搜索相关文件、查看日志、运行程序、修改代码和执行测试。它会在需要额外权限时停下来询问你,也会把最终修改和验证结果报告给你。

这里真正重要的,不是它一次写出了多少代码,而是它可以围绕一个目标连续完成多步工作。

Codex 的基本工作过程

在实际使用中,Codex 通常会经历下面几个步骤:

  1. 理解任务:判断你想完成什么、有哪些限制、怎样才算完成。
  2. 收集上下文:读取目录结构、项目说明、配置文件、代码和测试。
  3. 制订方案:决定先检查哪里、修改哪些文件、如何验证。
  4. 执行操作:搜索内容、运行命令、创建或修改文件。
  5. 验证结果:运行测试、构建程序、检查输出或审查差异。
  6. 汇报结果:说明做了什么、验证了什么、还有哪些风险。

这个过程不会每次都完整出现。让 Codex 修改一句文案时,它可能很快完成;让它升级一个跨越多个模块的功能时,它可能需要反复检查和验证。

你给出的目标越清楚,项目提供的上下文越完整,它越容易沿着正确方向工作。

Codex 能做什么

Codex 最擅长处理与代码、项目文件和开发工具有关的任务。

1. 理解陌生项目

它可以读取目录和关键文件,帮你回答:

  • 这个项目是做什么的?
  • 应该怎样启动?
  • 核心模块在哪里?
  • 数据从哪里进入,又流向哪里?
  • 修改某个功能可能影响哪些地方?

2. 开发功能

你可以让它从需求出发,完成方案设计、代码修改、测试补充和文档更新。小功能可以一次完成,复杂功能则适合拆成几个可以独立验收的阶段。

3. 修复问题

Codex 可以根据错误日志和复现步骤运行程序、定位原因、编写回归测试,再完成修复。

比起直接说“帮我修一下”,更可靠的做法是要求它先复现问题,再解释根因。

4. 补充测试和文档

它可以分析现有代码的测试缺口,补充单元测试、集成测试、README、接口说明和变更记录。

5. 审查代码

Codex 可以查看 Git Diff,检查逻辑错误、遗漏的边界情况、测试缺口和潜在风险。它也可以审查尚未提交的本地修改。

6. 处理重复工作

借助非交互模式,Codex 可以进入脚本或持续集成流程,例如分析测试日志、生成发布说明,或者把检查结果输出成结构化 JSON。

Codex 不会自动替你承担判断责任

Codex 可以执行很多操作,但最终结果仍然需要人来验收。

下面几类情况尤其需要谨慎:

  • 需求本身含糊,团队也没有达成共识。
  • 修改涉及支付、权限、隐私或生产数据。
  • 项目缺少测试,无法快速判断修改是否正确。
  • Agent 需要访问工作目录之外的文件或外部系统。
  • 一次修改范围很大,同时跨越多个模块。

使用 Codex 的关键能力,不只是“会写提示词”,还包括会限定范围、会检查差异、会运行验证、会在结果不可靠时及时停下来。

后面的教程会一直围绕这套工作方法展开。

Codex 的几种使用入口

Codex 并不只有一个界面。不同入口解决的问题不完全相同。

使用入口 更适合的任务 主要特点
Codex CLI 在终端中开发、调试、审查和自动化 离项目和开发工具最近,控制细致,是本教程的重点
桌面客户端中的 Codex 管理本地项目、查看修改、并行处理较长任务 界面直观,适合查看文件变化和管理多个任务
IDE 扩展 围绕当前打开的代码和编辑器上下文工作 适合边阅读代码边提问或修改
Codex Cloud 在云端环境中执行代码任务 不占用本机环境,适合已经配置好的远程项目

为什么先学 Codex CLI

CLI 是理解 Codex 工作方式最直接的入口。

在终端中,你能清楚看到它从哪个目录启动、读取了哪些上下文、运行了哪些命令、获得了什么权限。之后再使用桌面客户端或 IDE 扩展,很多概念就不会显得陌生。

CLI 还可以通过 codex exec 进入脚本和自动化流程,这是图形界面不容易替代的能力。

桌面客户端适合什么人

当前桌面客户端同时提供面向开发工作的 Codex,以及面向文档、表格、演示文稿等交付物的 ChatGPT Work。

程序员可以用 Codex 处理代码项目;产品经理、运营、编辑等非技术用户,则可以在同一个客户端中使用 Work 处理文件整理、数据分析和方案比较。

本教程会把桌面客户端放在最后讲。到那时,你已经理解工作目录、权限和任务上下文,再处理本地文件会更稳妥。

我们会开发什么项目

整套教程会围绕一个名为 TaskFlow 的小项目展开。

TaskFlow 是一个本地任务管理工具。第一版只支持添加、查看和完成任务,后面会逐渐增加:

  • 按状态和日期筛选任务;
  • 从 CSV 导入数据;
  • 生成任务统计;
  • 导出 Markdown 报告;
  • 自动测试和发布前检查。

这个项目规模不大,不要求你先掌握复杂框架,但足以覆盖项目规划、功能开发、调试、测试、代码审查、项目规则、多 Agent 和自动化执行。

如果你不是程序员,也不用担心看不懂所有代码。教程的重点是理解怎样把一个真实任务交给 Codex,并判断它是否完成了任务。

学习时请保留三个习惯

习惯一:从正确的目录启动 Codex

Codex 会把当前目录视为重要的工作上下文。进入错误目录,轻则让它找不到文件,重则让它看到不该处理的内容。

习惯二:先说明完成标准

不要只说“帮我做个功能”。告诉它功能要解决什么问题、不能改动什么、需要运行哪些测试、最终应该交付什么。

习惯三:每次都检查结果

查看修改的文件,阅读 Git Diff,运行程序和测试。Codex 的总结可以帮助你理解结果,但不能代替验收。

开始前的小练习

先不用安装任何东西。请判断下面几项任务是否适合交给 Codex:

  1. 阅读一个陌生项目,说明它如何启动。
  2. 修复一个能够稳定复现的错误。
  3. 在没有任何需求说明的情况下,决定公司下一季度应该开发什么产品。
  4. 根据现有代码补充测试。
  5. 直接连接生产数据库并批量删除历史数据。

前两项和第四项很适合。第三项需要人先明确业务目标,第五项涉及高风险外部操作,不能只凭一句自然语言直接执行。

下一篇,我们会在 Windows、macOS 或 Linux 上安装 Codex CLI,完成登录,然后在一个专门的练习目录中启动它。

参考资料


03 安装Codex_CLI并完成登录

预计阅读时间:25 分钟
本篇目标:在 Windows、macOS 或 Linux 上安装 Codex CLI,完成登录,并在一个安全的练习目录中成功启动。

这一篇会涉及不少终端命令,但不要求你有丰富的命令行经验。每一步都会告诉你在哪里操作、输入什么,以及成功后应该看到什么。

如果你的电脑由公司统一管理,安装软件、执行脚本或浏览器登录可能受到限制。遇到权限或网络策略提示时,不要反复绕过限制,先确认公司的使用规则。

安装之前准备什么

开始前,请确认你具备下面几个条件:

  • 一台运行 Windows、macOS 或 Linux 的电脑;
  • 可以打开终端或 PowerShell;
  • 可以访问 ChatGPT 登录页面;
  • 一个可以使用 Codex 的 ChatGPT 账号,或者一个 OpenAI API Key;
  • 一个专门用于练习的空目录。

Codex CLI 的官方独立安装脚本会安装可直接运行的 codex 命令,不要求你为了安装 CLI 而单独准备 Node.js。

在 macOS 上安装

第 1 步:打开终端

按下 Command + 空格,输入“终端”或“Terminal”,按回车打开。

你会看到一行等待输入的提示符,末尾通常是 % 或 $。

第 2 步:运行安装命令

复制下面这条命令,粘贴到终端,然后按回车:

curl -fsSL https://chatgpt.com/codex/install.sh | sh

安装脚本会下载 Codex,并把可执行命令放到用户级安装目录。按照终端里的提示完成安装。

第 3 步:检查安装结果

输入:

codex --version

如果安装成功,终端会输出 Codex CLI 的版本号。

如果出现 command not found: codex,先完全关闭终端,再重新打开一个终端窗口,然后再次运行 codex --version。安装程序可能刚刚更新了 PATH,而旧终端还没有重新加载。

仍然找不到命令时,可以运行:

command -v codex

正常情况下,它会输出 codex 所在的完整路径,你可以复制这条完整路径到命令行,然后再按回车。

在 Linux 上安装

Codex 在 Linux 上使用 Bubblewrap 和 Seccomp 提供本地沙箱能力。不同发行版的安装命令略有差异。

第 1 步:安装 Bubblewrap

Ubuntu 或 Debian 用户可以运行:

sudo apt update
sudo apt install -y bubblewrap

Fedora 用户可以运行:

sudo dnf install bubblewrap

Arch Linux 用户可以运行:

sudo pacman -S bubblewrap

如果系统提示找不到软件包,请查询当前发行版的软件仓库,确认对应包名。容器或裁剪过的 Linux 环境还可能缺少 Codex 沙箱所需的命名空间或 Seccomp 能力。

第 2 步:安装 Codex CLI

运行:

curl -fsSL https://chatgpt.com/codex/install.sh | sh

按照安装脚本的提示完成安装。

第 3 步:验证版本

运行:

codex --version

看到版本号就说明安装成功。

如果提示找不到命令,关闭当前终端并重新打开。仍然无效时,运行 command -v codex 检查完整路径。

在 Windows 上安装

Windows 用户可以选择原生安装,也可以在 WSL2 中安装。

如果你的项目和开发工具都在 Windows 中,先使用原生安装。如果你平时已经把代码、Git 和开发环境放在 WSL2 中,就在 WSL2 内安装 Codex。

不要在两个环境中来回混用同一个项目路径。例如,你在 WSL2 中使用 Codex 时,项目最好放在 Linux 主目录下,而不是长期放在 /mnt/c 中。

方式一:在 Windows 原生环境中安装

第 1 步:打开 PowerShell

点击开始菜单,搜索“PowerShell”,打开 Windows PowerShell 或 PowerShell 7。

普通用户权限通常足以完成用户级安装;除非安装程序明确要求,否则不必以管理员身份运行。

第 2 步:运行安装命令

在 PowerShell 中输入:

irm https://chatgpt.com/codex/install.ps1 | iex

按照窗口中的提示完成安装。

第 3 步:检查版本

关闭当前 PowerShell 窗口,重新打开一个 PowerShell,然后运行:

codex --version

如果成功,屏幕会显示 Codex CLI 的版本号。

如果出现“无法将 codex 识别为 cmdlet、函数、脚本文件或可运行程序”,运行:

Get-Command codex

如果依然找不到,重新运行安装脚本,并注意它是否提示你重新打开终端或添加 PATH。

方式二:在 WSL2 中安装

适合下面这些情况:

  • 你的代码本来就放在 WSL2 中;
  • 你依赖 Linux 工具链;
  • 团队开发环境以 Linux 为主。

先用管理员身份打开 PowerShell,运行:

wsl --install

按照系统提示完成安装并重启电脑。重启后打开 WSL 终端,先确认当前确实处于 WSL:

echo $WSL_DISTRO_NAME

如果输出类似 Ubuntu 的发行版名称,说明你已经进入 WSL。

接着安装 Bubblewrap 和 Codex:

sudo apt update
sudo apt install -y bubblewrap
curl -fsSL https://chatgpt.com/codex/install.sh | sh

最后运行:

codex --version

从 Codex 0.115 开始,Linux 沙箱依赖 Bubblewrap,WSL1 不再受支持。Windows 用户应使用 WSL2。

使用 ChatGPT 账号登录

对于个人学习和日常交互使用,如果你的 ChatGPT 订阅包含 Codex,优先使用 ChatGPT 账号登录。

在终端或 PowerShell 中运行:

codex login

接下来通常会发生这些事情:

  1. Codex 在浏览器中打开登录页面。
  2. 你登录自己的 ChatGPT 账号。
  3. 如果账号属于多个工作空间,选择要使用的工作空间。
  4. 浏览器显示登录完成。
  5. 回到终端,Codex 显示登录成功。

登录后运行:

codex login status

这条命令会显示当前是否已经登录,以及正在使用的身份验证方式。

浏览器没有自动打开怎么办

查看终端是否打印了一个登录地址。复制该地址,在浏览器中手动打开。

如果你在服务器、SSH 或没有图形界面的环境中使用 Codex,可以尝试设备代码登录:

codex login --device-auth

终端会显示一个网址和一次性代码。在另一台能够打开浏览器的设备上访问该网址,登录后输入代码。

设备代码登录是否可用,还取决于个人账号设置或工作空间管理员的配置。

使用 OpenAI API Key 登录

API Key 登录与 ChatGPT 订阅登录使用不同的计费方式。使用 API Key 时,费用计入 OpenAI Platform 账户,并按 API 实际用量结算。

先从 OpenAI Platform 创建 API Key。不要把密钥直接写进教程文件、代码仓库或聊天记录。

macOS 和 Linux

在当前终端会话中设置环境变量:

export OPENAI_API_KEY="请替换为你的API-Key"

然后通过标准输入完成登录:

printenv OPENAI_API_KEY | codex login --with-api-key

Windows PowerShell

在当前 PowerShell 会话中设置环境变量:

$env:OPENAI_API_KEY = "请替换为你的API-Key"

然后运行:

$env:OPENAI_API_KEY | codex login --with-api-key

完成后运行:

codex login status

确认 Codex 正在使用 API Key 身份验证。

上面的环境变量只对当前终端窗口有效,关闭窗口后就会消失。长期保存密钥时,优先使用操作系统的凭据管理工具或团队规定的密钥管理方案。

ChatGPT 登录和 API Key 登录怎么选

情况 更合适的方式
已有包含 Codex 的 ChatGPT 订阅,主要进行人工交互 ChatGPT 登录
需要把 Codex 放进脚本或 CI API Key
需要使用 ChatGPT 工作空间权限和相关服务 ChatGPT 登录
希望用 API 账户单独统计和控制费用 API Key

API Key 登录时,部分依赖 ChatGPT 工作空间或云服务的功能可能受到限制。教程主线默认使用 ChatGPT 登录;第三篇会讲怎样配置其他 Provider,以及如何切换回来。

创建专门的练习目录

不要一开始就在桌面、下载目录或存放重要项目的目录中练习。

macOS、Linux 或 WSL2

运行:

mkdir -p ~/codex-course/taskflow
cd ~/codex-course/taskflow

然后检查当前位置:

pwd

输出路径的末尾应该是 codex-course/taskflow。

Windows PowerShell

运行:

New-Item -ItemType Directory -Force "$HOME\codex-course\taskflow"
Set-Location "$HOME\codex-course\taskflow"

然后检查当前位置:

Get-Location

输出路径的末尾应该是 codex-course\taskflow。

第一次启动 Codex

确保终端当前位于刚才创建的 taskflow 目录,然后运行:

codex

第一次进入某个目录时,Codex 可能会询问你是否信任这个工作目录。此处是我们刚创建的空目录,可以按界面提示信任它。

进入交互界面后,先输入:

请告诉我当前工作目录中有哪些文件。不要创建或修改任何文件。

因为目录还是空的,Codex 应该告诉你没有可处理的项目文件,或者只列出系统自动生成的隐藏内容。它不应该创建新文件。

接着输入:

/status

检查当前模型、工作目录、权限策略和上下文状态。不同版本的排版可能不同,但你应该能够找到这些核心信息。

更新 Codex CLI

先查看当前版本:

codex --version

支持自更新的正式版本可以运行:

codex update

更新完成后再次运行 codex --version,确认版本发生变化。

如果当前安装方式不支持自更新,命令会提示你重新运行安装程序。此时使用本篇对应操作系统的官方安装命令即可。

常见问题

1. 安装后提示找不到 codex

先关闭终端并重新打开,再运行 codex --version。如果仍然失败:

  • macOS、Linux、WSL2:运行 command -v codex;
  • Windows PowerShell:运行 Get-Command codex。

没有输出通常说明安装没有完成,或者安装目录没有加入 PATH。

2. 登录后终端一直没有反应

先确认浏览器是否显示登录成功,再回到启动登录的那个终端窗口。如果网络阻止本地回调,可以改用:

codex login --device-auth

3. 登录了错误的账号

运行:

codex logout
codex login

第二次登录时,确认浏览器中选择了正确的账号和工作空间。

4. WSL 中运行很慢

检查项目是否放在 /mnt/c 等 Windows 挂载目录中。长期开发项目建议放在 WSL 的 Linux 主目录,例如 ~/code 或本教程的 ~/codex-course。

5. 公司电脑无法执行安装脚本

这通常是终端执行策略、软件安装策略、网络代理或证书配置造成的。记录终端中的完整错误信息,联系管理员确认允许的安装方式。不要为了安装 Codex 长期关闭系统安全策略。

本篇完成检查

继续下一篇之前,请确认下面几项都已经完成:

  • codex --version 能显示版本号;
  • codex login status 能显示有效登录状态;
  • 已经创建独立的 taskflow 练习目录;
  • 能够从该目录启动 codex;
  • /status 中显示的工作目录正确;
  • Codex 能读取目录,但没有在未授权的情况下创建文件。

下一篇,我们会配置第三方模型 API 和中转平台,并建立几套可以随时切换的 Provider 配置。

参考资料


04 接入第三方模型API并切换模型提供方

预计阅读时间:35 分钟
本篇目标:理解模型与 Provider 的关系,接入第三方模型或中转平台,并能够随时恢复 ChatGPT 订阅登录。

完成第二篇后,你已经可以使用 ChatGPT 账号或 OpenAI API Key 启动 Codex。很多读者还会遇到另外几个需求:

  • 想调用某个第三方模型;
  • 想通过公司内部网关或中转平台访问模型;
  • 想在本地运行 Ollama 或 LM Studio;
  • 想为不同项目准备不同的模型配置;
  • 试用第三方模型后,想切回 ChatGPT 订阅账号。

这些需求都与 Provider 配置有关。

这一篇的配置操作比前两篇多(如果暂时没有第三方平台或模型的配置需求,可以跳过本篇)。请在修改前完整读一遍对应小节,并使用专门的练习目录测试。第三方平台的接口、模型名称和认证方式并不统一,示例中的地址和模型名需要替换为平台实际提供的值。

先分清四个概念

1. 模型

模型负责理解你的任务并决定下一步做什么。例如,它会判断应该读取哪个文件、运行什么命令、怎样修改代码。

模型名称只是一个标识,而且不同平台的命名方式可能不同。不要根据宣传页面猜模型名,要使用平台文档中明确给出的模型 ID。

2. Provider

Provider 负责告诉 Codex:

  • 请求应该发送到哪个地址;
  • 用哪个环境变量读取密钥;
  • 使用什么协议;
  • 是否需要额外请求头或查询参数。

同一个模型可能通过不同 Provider 提供。例如,你可以直接访问 OpenAI,也可以通过公司的大模型网关访问同一个 OpenAI 模型。

3. 身份验证

身份验证解决的是“你以什么身份使用服务”。

Codex 使用 OpenAI 模型时,常见方式有两种:

  • 使用 ChatGPT 账号登录,享用订阅权益;
  • 使用 OpenAI API Key 登录,按 API 用量计费。

第三方 Provider 通常要求自己的 API Key。这个密钥一般通过环境变量提供,不应该写死在配置文件中。

4. 配置文件

Codex 的个人配置默认保存在:

  • macOS、Linux、WSL2:~/.codex/config.toml
  • Windows:%USERPROFILE%\.codex\config.toml

Provider 和认证路由属于用户级配置,应放在个人配置中。出于安全原因,项目里的 .codex/config.toml 不能覆盖 model_provider、model_providers 和 openai_base_url 等认证或路由配置。项目可以选择模型,但不能悄悄把请求改到另一个服务商。

打开并备份配置文件

macOS、Linux 或 WSL2

先创建配置目录:

mkdir -p ~/.codex

如果配置文件已经存在,先备份:

cp ~/.codex/config.toml ~/.codex/config.toml.backup

如果复制时提示文件不存在,说明你还没有创建过配置文件,可以忽略。

接着使用自己熟悉的编辑器打开:

nano ~/.codex/config.toml

在 Nano 中,按 Ctrl + O 保存,按回车确认文件名,再按 Ctrl + X 退出。

Windows PowerShell

先创建配置目录:

New-Item -ItemType Directory -Force "$HOME\.codex"

如果配置文件已经存在,运行:

Copy-Item "$HOME\.codex\config.toml" "$HOME\.codex\config.toml.backup"

如果提示源文件不存在,说明还没有配置文件,可以忽略。

然后用记事本打开:

notepad "$HOME\.codex\config.toml"

先认识默认的 OpenAI Provider

没有特别配置时,Codex 使用内置的 openai Provider。

下面是一份最小示例:

model_provider = "openai"

使用 ChatGPT 登录时,建议在交互界面中通过 /model 选择账号当前可用的模型。这样可以避免把一个已经下线或当前账号没有权限的模型名称长期写死在配置文件中。

如果配置文件中已有其他设置,不要直接覆盖整个文件。只调整与模型相关的键,并保留现有的权限、界面或工具配置。

TOML 有两个容易踩到的规则:

  1. 同一个键不能重复定义。
  2. 顶层键应放在各个 [表格] 之前。

如果启动时提示配置解析失败,请先检查是否重复写了 model 或 model_provider。

场景一:通过中转平台调用模型

中转平台大致分为两类。

第一类只是把 OpenAI 请求转发到另一个网关,而且仍然使用 OpenAI 身份验证。官方配置为这种情况提供了 openai_base_url。

第二类平台会发放自己的 API Key,模型名称和接口能力也由平台定义。这种情况更适合配置一个自定义 Provider。

方式 A:修改内置 OpenAI Provider 的访问地址

只有当网关明确说明可以使用这种方式,并且它处理的是 OpenAI 身份验证时,才使用下面的配置:

model_provider = "openai"
openai_base_url = "https://你的网关地址/v1"

保存文件,重新启动 Codex。

如果网关要求它自己发放的 API Key,不要只改 openai_base_url。请使用下一种自定义 Provider 方式。

方式 B:为中转平台创建自定义 Provider

假设平台提供了这些信息:

  • API 地址:https://relay.example.com/v1
  • API Key 环境变量:我们自己命名为 RELAY_API_KEY
  • 模型 ID:provider-model-id
  • 协议:Responses API

先在当前终端中设置密钥。

macOS、Linux 或 WSL2:

export RELAY_API_KEY="请替换为平台提供的密钥"

Windows PowerShell:

$env:RELAY_API_KEY = "请替换为平台提供的密钥"

然后在 ~/.codex/config.toml 中加入:

model = "provider-model-id"
model_provider = "relay"

[model_providers.relay]
name = "My Relay"
base_url = "https://relay.example.com/v1"
env_key = "RELAY_API_KEY"
wire_api = "responses"

需要替换的内容有三个:

  • provider-model-id:平台文档给出的准确模型 ID;
  • https://relay.example.com/v1:平台给出的 API 基础地址;
  • RELAY_API_KEY:你为密钥选择的环境变量名。

relay 是这个 Provider 在本机配置里的 ID,你可以换成更容易识别的英文名称,但不要使用保留的内置 ID,例如 openai、ollama 或 lmstudio。

保存配置后,从同一个终端窗口启动:

codex

必须从刚才设置环境变量的终端启动,否则 Codex 读不到密钥。

场景二:接入第三方模型 API

第三方模型的配置方法与中转平台相似。区别主要在于模型名称、接口地址以及支持的能力。

假设第三方平台提供了一个兼容 Responses API 的端点:

model = "third-party-model-id"
model_provider = "thirdparty"

[model_providers.thirdparty]
name = "Third-party Model Platform"
base_url = "https://api.example.com/v1"
env_key = "THIRD_PARTY_API_KEY"
wire_api = "responses"

在启动 Codex 之前设置密钥。

macOS、Linux 或 WSL2:

export THIRD_PARTY_API_KEY="请替换为第三方平台密钥"
codex

Windows PowerShell:

$env:THIRD_PARTY_API_KEY = "请替换为第三方平台密钥"
codex

API 兼容不等于 Codex 能力完整

一个平台能够回答普通聊天问题,只能证明最基础的文本请求可用。Codex 还依赖模型和接口正确处理工具调用、流式事件、长上下文和错误反馈。

因此,接入第三方 Provider 后,至少测试下面四项:

  1. 能否正常回答一个简单问题。
  2. 能否列出当前目录的文件。
  3. 能否读取指定文件并总结内容。
  4. 能否在练习目录中创建文件并正确报告修改。

某些平台还可能不支持图片输入、网页搜索或完整的工具调用。教程后面使用到这些能力时,如果第三方 Provider 表现异常,先切回内置 OpenAI Provider 进行对照。

目前 Codex 对 Chat Completions 的兼容属于逐步淘汰方向。准备长期使用的第三方平台时,优先选择明确支持 Responses API 的服务。

需要额外请求头时怎么配置

部分企业网关或平台除了 API Key,还要求额外请求头。

固定且不敏感的请求头可以写在 http_headers 中:

[model_providers.company]
name = "Company Gateway"
base_url = "https://gateway.example.com/v1"
env_key = "COMPANY_MODEL_API_KEY"
wire_api = "responses"
http_headers = { "X-Client-Name" = "codex-course" }

如果请求头的值本身是敏感信息,应该从环境变量读取:

[model_providers.company]
name = "Company Gateway"
base_url = "https://gateway.example.com/v1"
env_key = "COMPANY_MODEL_API_KEY"
wire_api = "responses"
env_http_headers = { "X-Company-Token" = "COMPANY_EXTRA_TOKEN" }

这里的 COMPANY_EXTRA_TOKEN 是另一个环境变量名,而不是 Token 本身。

临时切换 Provider,避免频繁修改配置文件

你可以用 -c 临时覆盖当前运行的 Provider,并用 -m 指定模型。

假设 relay 已经在配置文件中定义:

codex -c 'model_provider="relay"' -m "provider-model-id"

这条命令只影响本次启动,不会修改 config.toml。

进入 Codex 后输入:

/status

检查当前模型是否已经变化。

注意:/model 主要用于选择当前 Provider 提供的模型。切换到另一个 Provider 时,更稳妥的方式是重新启动 Codex,并通过配置或启动参数指定 Provider。

使用 Profile 保存多套配置

如果你经常在 ChatGPT 登录和第三方 Provider 之间切换,建议使用 Profile。

Codex 的 Profile 是单独的配置文件,放在 ~/.codex 目录下,文件名格式为:

配置名.config.toml

1. 保持默认配置使用 ChatGPT

在 ~/.codex/config.toml 中保留:

model_provider = "openai"

[model_providers.relay]
name = "My Relay"
base_url = "https://relay.example.com/v1"
env_key = "RELAY_API_KEY"
wire_api = "responses"

这里先定义 relay,但不把它设为默认 Provider。

2. 创建第三方 Profile

创建 ~/.codex/relay.config.toml:

model_provider = "relay"
model = "provider-model-id"

3. 启动不同配置

默认使用 ChatGPT 登录:

codex

使用中转平台:

codex --profile relay

这种方式的优点是,退出当前会话后再次运行普通的 codex,就会回到默认 OpenAI Provider,不需要反复编辑配置文件。

使用本地模型

Codex 内置了针对 Ollama 和 LM Studio 的本地 OSS 模式。

先确保本地模型服务已经安装、启动,并下载了适合工具调用的模型。然后运行:

codex --oss --local-provider ollama

或者:

codex --oss --local-provider lmstudio

也可以在 config.toml 中设置默认本地 Provider:

oss_provider = "ollama"

本地模型的效果取决于模型能力、上下文长度、工具调用支持和电脑性能。能在本地聊天,不代表能够稳定完成多步骤代码任务。

从第三方 Provider 切回 ChatGPT 订阅

如果你使用了 Profile,并且默认配置一直是 openai,退出第三方会话后直接运行:

codex

通常就能回到 ChatGPT 登录对应的 OpenAI Provider。

如果之前直接修改了默认配置,按照下面的步骤彻底恢复。

第 1 步:恢复 Provider 配置

打开 ~/.codex/config.toml,将顶层配置恢复为:

model_provider = "openai"

删除或注释掉顶层的自定义 model = "...",之后进入 Codex 使用 /model 选择账号实际可用的模型。

如果配置中存在为了中转平台添加的:

openai_base_url = "https://某个中转地址/v1"

也要删除或注释掉。定义在 [model_providers.relay] 下的第三方 Provider 可以保留,只要没有把它设置为默认 Provider,就不会自动使用。

第 2 步:清除旧登录状态

运行:

codex logout

如果当前本来就是有效的 ChatGPT 登录,这一步不一定必需。但当你无法确认以前使用的是 ChatGPT 账号还是 OpenAI API Key 时,重新登录最容易排除身份残留。

第 3 步:重新使用 ChatGPT 登录

运行:

codex login

在浏览器中选择正确的 ChatGPT 账号和工作空间。

第 4 步:检查登录方式

运行:

codex login status

确认当前身份验证方式是 ChatGPT 登录。

第 5 步:检查运行配置

启动:

codex

进入后输入:

/status

确认当前 Provider 已恢复为 OpenAI,并检查模型是否符合预期。

用同一个任务测试不同 Provider

为了减少变量,请回到第二篇创建的 taskflow 空目录。为每个 Provider 使用完全相同的任务:

请检查当前目录。不要修改现有文件。创建一个名为 provider-test.md 的文件,
写入当前时间、你观察到的目录内容,以及本次调用是否成功使用了文件工具。
完成后重新读取该文件,确认内容已经写入。

每次测试前,把上一轮生成的文件移动到单独的测试子目录,或者换一个新的空目录,避免不同 Provider 互相看到之前的结果。

记录下面几项:

检查项 ChatGPT 登录 第三方模型 中转平台
能否正常启动
能否读取目录
能否创建文件
能否重新读取并验证
工具调用是否稳定
响应速度
错误信息是否清晰

这张表比单独问模型“你支持什么能力”更可信,因为它记录的是当前环境中的实际表现。

常见错误与排查

1. 401 Unauthorized

通常表示密钥缺失、错误或已经失效。

先检查环境变量是否存在。

macOS、Linux 或 WSL2:

test -n "$RELAY_API_KEY" && echo set || echo missing

Windows PowerShell:

Test-Path Env:RELAY_API_KEY

为了避免泄露密钥,不要把完整值截图或发到聊天中。

2. 404 Not Found

常见原因包括:

  • base_url 路径多写或少写了 /v1;
  • 平台不提供 Responses API;
  • 模型 ID 不正确;
  • 账号没有对应模型权限。

对照平台文档检查完整请求地址和模型 ID,不要仅凭控制台中的展示名称猜测。

3. 429 Too Many Requests

这可能代表余额不足、并发过高、触发分钟限额或模型暂时拥堵。查看平台控制台中的余额、速率限制和错误日志。

4. 可以回答问题,但不会操作文件

这通常说明文本请求可用,但模型或平台没有正确实现工具调用。先切回 OpenAI Provider 运行同一个任务进行对照,再向第三方平台确认是否完整支持 Responses API 和工具调用事件。

5. 关闭终端后又提示缺少密钥

本篇用 export 或 $env: 设置的是当前会话变量,关闭终端后会消失。这是正常现象。

如果要长期使用,选择操作系统的凭据管理方式、启动脚本或团队统一的密钥工具。无论使用哪种方式,都不要把真实密钥提交进 Git。

6. 明明已经切换,仍然走旧平台

依次检查:

  1. 启动命令里是否带有 --profile 或 -c。
  2. ~/.codex/config.toml 中是否仍设置了旧 model_provider。
  3. 是否仍然存在 openai_base_url。
  4. 当前会话是否在修改配置前就已经启动。

修改配置后,退出旧会话并重新启动 Codex,再通过 /status 检查。

本篇完成检查

继续学习之前,请确认你已经理解并完成这些内容:

  • 能说明模型、Provider、API Key 和 ChatGPT 登录的区别;
  • 知道用户级 config.toml 的位置;
  • 知道 Provider 配置不能依赖项目级配置覆盖;
  • 能使用环境变量提供第三方密钥;
  • 能配置一个自定义 Provider;
  • 能使用 Profile 在不同 Provider 之间切换;
  • 能通过 codex login status 和 /status 检查当前状态;
  • 能从第三方 Provider 恢复到 ChatGPT 订阅登录;
  • 知道 API 兼容不代表所有 Codex 功能都能正常工作。

下一篇,我们会正式进入 Codex CLI 的交互界面,学习权限、状态、文件修改和结果检查,并让它完成 TaskFlow 项目的第一次真实操作。

参考资料


05 第一次使用Codex_CLI

预计阅读时间:30 分钟
本篇目标:认识 Codex CLI 的基本界面,理解工作目录与权限的关系,完成第一次可检查、可撤销的文件修改。

前面三篇解决了“Codex 是什么”、“怎样安装”和“怎样选择模型”。从这一篇开始,我们正式进入 Codex CLI。

第一次使用 Coding Agent 时,人很容易走向两个极端:一种是不敢让它做任何事情,只把它当成问答工具;另一种是一开始就开放全部权限,希望它替自己完成所有工作。

更稳妥的方式是从一个独立练习目录开始,让 Codex 先观察,再修改,然后由我们检查结果。你会在这一篇中完整走一遍这个过程。

确认你位于正确的目录

第二篇已经创建了 taskflow 练习目录。现在重新进入它。

macOS、Linux 或 WSL2

打开终端,运行:

cd ~/codex-course/taskflow
pwd

最后一行应该以 codex-course/taskflow 结尾。

Windows PowerShell

打开 PowerShell,运行:

Set-Location "$HOME\codex-course\taskflow"
Get-Location

输出路径应该以 codex-course\taskflow 结尾。

如果目录不存在,请回到第二篇,重新创建练习目录。不要为了省一步,直接在桌面、下载目录或保存正式项目的目录中练习。

用 Git 为练习项目准备安全网

Git 能记录文件变化,方便我们检查和恢复。先检查电脑是否已经安装 Git:

git --version

如果看到类似 git version 2.x.x 的输出,说明 Git 可以使用。

如果提示找不到命令,可以暂时跳过本节,后面的 /diff 和 /review 功能会受到影响。建议在继续正式项目之前,从 Git 官方网站 安装适合当前系统的版本。

在 taskflow 目录中运行:

git init

接着运行:

git status

你应该看到当前分支信息,以及“没有提交内容”或含义相近的提示。项目还没有任何文件,这是正常的。

git init 只会在当前目录中创建 Git 元数据,不会把文件上传到互联网,也不会自动创建 GitHub 仓库。

以只读方式启动 Codex

为了先观察界面,我们让 Codex 以只读模式启动。

在 macOS、Linux、WSL2 或 PowerShell 中都可以运行:

codex --sandbox read-only --ask-for-approval on-request

如果 Codex 询问是否信任当前目录,请先确认提示中的路径确实是刚才创建的 taskflow,再按照界面提示继续。

进入后,你会看到终端式交互界面。不同版本的颜色和排版可能略有变化,但通常能看到下面几类信息:

  • 当前项目或工作目录;
  • 当前模型;
  • 当前对话记录;
  • 底部用于输入任务的区域;
  • 状态、上下文或使用量提示。

不必记住每个界面元素。真正重要的是:你知道 Codex 正在哪个目录工作,以及当前是否允许修改文件。

用 /status 检查当前会话

在输入区域键入:

/status

按回车后,Codex 会显示当前会话信息。请重点检查:

  • 工作目录是不是 taskflow;
  • Sandbox 是否为 read-only;
  • 当前使用的模型是否符合预期;
  • 当前还有多少上下文空间;
  • 哪些目录属于本次工作区。

不同版本可能使用“writable roots”“workspace”“sandbox”等不同标签。只读模式下,Codex 可以查看允许读取的文件,但不能直接写入工作目录。

如果工作目录不正确,输入:

/exit

退出后,在终端中进入正确目录,再重新运行 Codex。

让 Codex 先观察,不要马上修改

输入下面这段任务:

请检查当前工作目录,并告诉我:

1. 当前有哪些文件和目录;
2. 这里是否已经是 Git 仓库;
3. 当前是否具备开始一个新项目的基本条件。

只读取和分析,不要创建或修改任何文件,也不要访问当前工作目录之外的位置。

Codex 应该检查目录,并告诉你这里基本是一个空的 Git 仓库。由于当前是只读模式,即便它误解了要求,也没有权限直接创建项目文件。

这一步演示了一个很实用的习惯:面对陌生目录时,先让 Codex 盘点现状,再决定下一步。

观察只读模式如何阻止写入

现在故意给它一个需要写文件的任务:

请在当前目录创建 PROJECT_BRIEF.md,并写入项目标题“TaskFlow”。

因为当前处于只读模式,Codex 不能直接完成写入。根据客户端版本和权限策略,它可能会:

  • 说明当前权限不允许写入;
  • 请求你调整权限;
  • 给出准备写入的内容,但不真正创建文件。

如果它弹出越过只读边界的授权请求,这一步选择拒绝。无论出现哪一种情况,都不要把它理解成故障。只读模式正在按预期工作。

使用 /permissions 切换权限

输入:

/permissions

界面会显示三个权限选项:Ask for approval、Approve for me 和 Full access。对于本教程的本地练习目录,选择 Ask for approval。

这三个选项不要只按字面理解:

  • Ask for approval:Codex 可以在当前工作区内读写和运行常规命令;需要越过工作区、访问受限网络等资源时,由你决定是否批准。本教程默认使用它。
  • Approve for me:工作区边界基本不变,但越界请求交给自动审查器判断,适合已经熟悉权限边界后减少手动确认。
  • Full access:可以访问工作区之外的文件和网络,风险明显更高;本教程的本地练习不需要选择它。

有些旧版本或旧资料把第一类工作方式称为 Auto,但你当前界面里没有这个选项。后文凡是需要在项目内改代码、跑测试,默认都选择 Ask for approval。

在命令行参数中,Ask for approval 对应本教程一直使用的组合:

codex --sandbox workspace-write --ask-for-approval on-request

它表示:

  • Codex 可以读取工作区中的文件;
  • Codex 可以修改当前工作区;
  • 网络访问默认仍然受限;
  • 写入工作区之外的位置时需要额外授权;
  • 超出沙箱边界的操作不会静默执行,而是由你决定是否批准。

切换完成后,再输入一次:

/status

确认当前不再是只读模式,并且可写范围仍然只包括练习工作区和系统临时目录。

完成第一次文件修改

输入下面的完整任务:

请在当前目录创建 PROJECT_BRIEF.md,内容包括:

- 项目名称:TaskFlow
- 项目定位:一个用于学习 Codex 的本地命令行任务管理工具
- 第一阶段目标:支持添加任务、查看任务和完成任务
- 当前状态:尚未确定技术方案,暂时不要创建程序代码

要求:
1. 使用清晰的 Markdown 结构;
2. 只创建这一个文件;
3. 创建后重新读取文件,确认内容完整;
4. 最后说明你修改了什么,不要继续实现项目。

这段提示词包含目标、范围、限制和完成标准。Codex 不需要猜测你是否希望它顺手写代码。

任务完成后,它应该报告已经创建 PROJECT_BRIEF.md,并说明进行了重新读取或检查。

不退出 Codex,也能检查文件

Codex CLI 支持在输入行前加 !,直接运行本地终端命令。输入:

!git status

你应该看到 PROJECT_BRIEF.md 是一个尚未跟踪的新文件。

接着输入:

/diff

/diff 会展示 Git 工作区中的变化,包括尚未被 Git 跟踪的新文件。检查以下内容:

  • 是否只新增了 PROJECT_BRIEF.md;
  • 文件名是否正确;
  • 内容是否与要求一致;
  • 是否出现你没有要求的代码或配置文件。

检查完没问题之后,可以按字母键 "Q" 返回交互式命令行界面。

如果结果不符合要求,比如它私自添加了选型建议,那么你可以直接告诉 Codex:

PROJECT_BRIEF.md 中不要加入技术选型建议。请删除相关内容,只保留已经确认的信息,修改后再次展示差异。

使用 /review 做一次独立检查

输入:

/review

如果出现审查范围选择,选择“Review uncommitted changes (审查未提交的修改)”。

这次修改非常简单,审查结果很可能是没有发现问题。我们的重点是熟悉流程:Codex 完成修改后,你可以再让审查流程从完整性、风险和遗漏角度检查工作区。

/review 需要当前目录是 Git 仓库。如果没有初始化 Git,该命令可能不会出现,或者提示没有可审查的工作树。

学会在运行过程中补充要求

当 Codex 正在工作时,你不一定要等它结束后再纠正。

  • 在 CLI 中直接输入补充说明并按回车,可以把新要求加入当前任务;
  • 按 Tab 发送,可以把内容排队,等当前任务结束后再处理。

例如,你发现 Codex 正准备创建多余文件,可以立即输入并按回车:

只保留 PROJECT_BRIEF.md,不要创建其他文件。

这叫做对当前任务进行引导。它很适合补充遗漏条件,但不能替代一开始就说清楚关键范围。

如果 Codex 启动了不需要的后台命令,可以使用:

/ps

查看后台终端,再使用:

/stop

停止当前会话启动的后台终端。

批准操作时应该看什么

当你后续要执行一些更复杂的任务时,可能会收到 Codex 请求额外权限的提示,要注意,批准时不要只看“允许”和“拒绝”两个按钮。先读清楚:

  1. 它准备执行什么操作;
  2. 操作目标是哪个文件或目录;
  3. 为什么当前任务需要这项权限;
  4. 是否有范围更小的替代方案。

例如,任务只是修改 taskflow 项目,却请求写入整个用户目录,这个范围就不合理。更合适的做法是拒绝请求,并告诉它只在当前工作目录内完成任务。

网络访问也是一样。安装依赖可能需要联网,读取本地文件则通常不需要。权限应该跟着任务需要走,而不是一次性全部打开。

为什么不使用 --yolo

Codex CLI 提供 --dangerously-bypass-approvals-and-sandbox,也可以写成 --yolo。它会绕过审批和沙箱限制。

这不是日常学习模式,也不适合直接用于保存个人文件或正式项目的电脑。只有当 Codex 已经运行在专门隔离的虚拟机或容器中,并且外层环境本身提供了可靠限制时,才有讨论它的意义。

本教程默认使用工作区可写、越界操作需要确认的模式。

保存本次练习结果

先退出 Codex:

/exit

回到普通终端后运行:

git status
git diff -- PROJECT_BRIEF.md

对于尚未跟踪的新文件,普通 git diff 可能不会显示内容,这是 Git 的正常行为(想要退出的话,可以在英文输入法状态下按 Q 键退出)。你仍然可以直接打开文件检查,或者先运行:

git add PROJECT_BRIEF.md
git diff --cached

确认内容无误后,可以创建第一次提交:

git commit -m "docs: add TaskFlow project brief"

如果 Git 提示没有配置用户名或邮箱,按照提示配置后重新提交;也可以暂时不提交,下一篇仍然能够继续。

提交只保存在本机,除非你以后主动添加远程仓库并执行推送。

本篇完成检查

继续下一篇之前,请确认:

  • Codex 从正确的 taskflow 目录启动;
  • 你能使用 /status 检查目录、模型和权限;
  • 你体验了只读模式对写入操作的限制;
  • 你能使用 /permissions 切换到工作区可写模式;
  • 当前只新增了 PROJECT_BRIEF.md;
  • 你能使用 /diff 查看修改;
  • 你知道 /review 需要 Git 仓库;
  • 你知道怎样在任务运行时补充要求;
  • 你没有为练习任务开放整个电脑的写入权限。

下一篇,我们不会急着写程序,而是让 Codex 把 TaskFlow 的模糊想法整理成一份可以执行、可以验收的开发计划。

参考资料


06 让Codex规划第一个完整功能

预计阅读时间:35 分钟
本篇目标:把一个模糊想法整理成明确需求,让 Codex 先调查、提问和规划,再决定如何实现。

上一篇我们创建了 PROJECT_BRIEF.md,里面只有几条简单信息:TaskFlow 是一个本地命令行任务管理工具,第一阶段支持添加、查看和完成任务。

这些信息足够表达方向,却不足以直接开发。我们还不知道用什么语言、任务保存在哪里、命令长什么样、出错时如何处理,以及怎样判断第一版已经完成。

如果现在直接说“帮我把 TaskFlow 写出来”,Codex 也许能做出一个能运行的版本,但它需要替你做很多决定。那些决定未必符合你的真实需求。

这一篇先不写代码。我们要做的是把想法变成一份可以执行和验收的计划。

确认项目仍处于正确状态

进入 taskflow 目录。

macOS、Linux 或 WSL2

cd ~/codex-course/taskflow
git status

Windows PowerShell

Set-Location "$HOME\codex-course\taskflow"
git status

如果上一篇创建了 Git 提交,工作区应该是干净的。如果没有提交,应该只看到 PROJECT_BRIEF.md。

确认文件存在:

ls

Windows PowerShell 也可以使用 ls,它是 Get-ChildItem 的别名。

你应该能看到:

PROJECT_BRIEF.md

检查 Python 环境

为了让示例在不同系统上尽量简单,TaskFlow 1.0 使用 Python 标准库开发,不安装第三方依赖。

macOS、Linux 或 WSL2

运行:

python3 --version

Windows

先运行:

py --version

如果 py 不存在,再尝试:

python --version

建议使用 Python 3.11 或更高版本。看到 Python 3.x.x 就说明命令可用。

如果系统没有 Python,请从 Python 官方网站 安装 Python 3。Windows 安装界面中要留意“Add Python to PATH”选项。安装完成后关闭并重新打开终端,再检查版本。

本教程后续命令约定如下:

  • macOS、Linux、WSL2 使用 python3;
  • Windows 优先使用 py,没有 py 时使用 python。

什么样的任务值得先规划

并不是所有任务都需要 Plan 模式。修改一个错别字、解释一个函数、调整一条错误提示,直接做通常更快。

下面这些任务更适合先规划:

  • 需求中存在多种合理实现;
  • 修改会跨越多个文件或模块;
  • 需要先理解现有项目;
  • 有兼容性、安全或数据迁移要求;
  • 任务会持续较长时间;
  • 你希望先审查方案,再决定是否允许修改。

TaskFlow 虽然不大,但这是我们第一次建立完整项目,正适合用 Plan 模式练习。

在只读模式下进入 Plan 模式

从项目目录启动 Codex:

codex --sandbox read-only --ask-for-approval on-request

进入后输入:

/plan

Codex 会进入 Plan 模式(在界面右下角可以看到 Plan mode)。在这个模式中,它可以调查现有上下文、提出问题并整理方案,但重点是规划,而不是直接实现。

你也可以把任务直接写在 /plan 后面。不过第一次练习时,先单独进入模式,更容易观察状态变化。

先给出一段故意不够完整的需求

输入:

我想把当前目录里的 TaskFlow 做成一个真正可以使用的命令行任务管理工具。
请先阅读 PROJECT_BRIEF.md,然后规划第一版怎么做。

这是一个很常见的需求表达,但仍然缺少大量信息。观察 Codex 的反应:

  • 它是否先读取了 PROJECT_BRIEF.md;
  • 它是否发现技术方案和验收标准尚未确定;
  • 它是否提出澄清问题;
  • 它是否直接假设了很多细节。

Codex 有可能会弹出一些选项让你选择,你可以根据下面的约束来针对性地答复它:

第一版按下面的要求规划:

1. 使用 Python 3.11 或更高版本,只使用标准库,不安装第三方依赖。
2. 程序入口为项目根目录下的 taskflow.py。
3. 任务保存在 JSON 文件中,默认路径为 data/tasks.json。
4. 命令格式统一为:
   python taskflow.py --data <数据文件> <子命令> [参数]
5. 第一版只支持三个子命令:
   - add <任务标题>
   - list
   - done <任务ID>
6. 每条任务至少包含整数 ID、标题、完成状态和创建时间。
7. 数据文件不存在时按空任务列表处理,并在第一次写入时自动创建父目录。
8. 测试统一放在 tests/,使用 unittest 和临时目录,不能读写用户真实的 data/tasks.json。
9. 暂时不要实现删除、修改、截止日期、标签、网络同步和图形界面。
10. 先输出计划,不要创建或修改文件。

如果 Codex 立刻给出实现方案,却没有询问关键问题,可以继续说:

先不要确定实现方案。请列出会明显影响项目结构、用户操作方式和验收结果的问题,
最多问我 6 个。不要询问无关紧要的偏好。

一个好的规划过程,不是问题越多越好,而是优先解决那些会改变方案的问题。

把关键选择明确下来

接下来,计划生成后,Codex 会询问你接下来怎么处理。当前界面通常有三个选项:

  • Yes, implement this plan:退出 Plan 模式,保留当前上下文,并开始执行刚刚确认的计划;
  • Yes, clear context and implement:先清理前面的对话上下文,再带着最终计划进入执行;
  • No, stay in Plan mode:暂不执行,继续留在 Plan 模式补充或修改计划。

如果计划中还有规则没说清楚,选择 No, stay in Plan mode,继续追问。

这里我们为了统一学习进度,建议选择“No,stay in plan mode”(在其他场景下,如果它给出的方案已经足够令你满意,你可以选择让它直接实施方案)。

然后请它按第五节十条约束确认尚未决定的接口:固定 taskflow.py 入口、全局 --data 参数、tests/ 目录和错误退出码。已有答案不再整段重发;有变动只提交差异,并要求计划同步更新。

定义“完成”是什么样子

功能列表只能说明“要做什么”,还不能说明“怎样算做完”。继续告诉 Codex:

请把下面这些验收条件加入计划:

- 添加任务后,JSON 文件中出现一条新任务;
- 连续添加任务时,ID 递增;
- list 能清楚区分未完成和已完成任务;
- done 能按 ID 将任务标记为完成;
- 对不存在的 ID 执行 done 时,程序给出明确错误并返回非零退出码;
- 空任务列表不会报错,而是显示友好提示;
- 所有自动测试通过;
- README 同时给出 macOS/Linux/WSL2 与 Windows 示例;
- 最后实际运行一遍 add、list、done,报告运行结果。

请根据现有目录和这些条件,给出分步骤实施计划。每一步都写明会修改哪些文件,以及如何验证。

现在,Codex 获得了四类关键信息:

信息 本次内容
目标 创建可以使用的 TaskFlow 1.0
上下文 PROJECT_BRIEF.md 和当前空项目
限制 Python 标准库、三个子命令、不做扩展功能
完成标准 测试、手动操作和文档全部通过

这是以后编写 Codex 任务描述时最值得保留的结构。

检查 Codex 给出的计划

一份适合执行的计划通常应该接近下面的结构:

  1. 检查现有项目和 Python 环境。
  2. 设计任务数据格式和存储函数。
  3. 实现 add、list、done 三个子命令。
  4. 使用临时目录编写测试。
  5. 编写 README 和运行示例。
  6. 执行自动测试。
  7. 完成一次端到端手动验证。
  8. 审查最终差异。

不要求 Codex 的表述与这里完全一致,但要检查几个问题。

1. 每一步能否独立验证

“实现整个项目”不是一个好步骤,因为失败后很难知道问题在哪里。“实现存储层并运行相关测试”更容易检查。

2. 有没有超出第一版范围

如果计划加入数据库、Web 界面、账号系统、插件架构或复杂打包流程,说明方案已经过度设计。

可以直接纠正:

第一版不需要扩展架构。请去掉数据库、插件系统、网络能力和打包发布,
保留能够完成三个命令的最小结构。

3. 有没有验证步骤

如果计划只写“完成代码”,却没有自动测试和手动运行,任务就缺少验收闭环。

4. 是否保护测试数据

测试必须使用临时目录,不能修改正式的 data/tasks.json。这是计划中需要明确写出的边界。

5. 是否明确了预计修改的文件

第一版预计产生:

taskflow.py
tests/test_taskflow.py
README.md
.gitignore
PLAN.md

data/tasks.json 会在手动运行时生成,不应该在测试过程中提前写入真实数据。

让 Codex 把最终计划整理成可保存版本

当计划已经满足要求,输入:

请把最终计划重新整理一遍,要求:

- 开头写清项目目标和本次范围;
- 列出最终预计产生的文件;
- 每个实施步骤包含“修改内容”和“验证方法”;
- 单独列出不在第一版范围内的功能;
- 最后给出完成检查清单;
- 仍然不要修改文件。

阅读最终计划。确认没有问题后,按“shift+tab”键退出 Plan 模式。

由于当前 Codex 仍然以只读沙箱启动,需要先输入:

/permissions

选择 Ask for approval。它允许 Codex 在当前工作区内写入,越过工作区或访问其他受限资源时会停下来请你确认。不要选择 Full access;本篇只需要写入 TaskFlow 项目目录。

然后输入:

请把刚才确认的最终计划写入项目根目录的 PLAN.md。
同时更新 PROJECT_BRIEF.md,使其包含已经确认的技术方案、命令格式、范围和验收条件。

只修改这两个 Markdown 文件,不要创建程序代码。完成后重新读取两个文件,并说明它们是否一致。

检查规划文件

任务完成后输入:

/diff

重点检查:

  • PLAN.md 是否完整记录实施顺序;
  • PROJECT_BRIEF.md 是否反映已经确认的需求;
  • 两个文件是否使用同样的命令格式;
  • 是否明确只使用 Python 标准库;
  • 是否明确测试不能读写真实数据;
  • 是否混入了尚未同意的功能;
  • 是否只修改了两个 Markdown 文件。

发现不一致时,不要自己默默记住,直接让 Codex 修改文档。例如:

PLAN.md 使用的是 tasks.json,PROJECT_BRIEF.md 写成了 task.json。
请统一为 data/tasks.json,并重新检查两个文件中的所有路径。

如何把模糊想法交给 Codex

以后遇到类似需求,可以复用下面的任务模板:

我想实现:<目标>。

请先阅读:<相关文件或目录>。

在开始修改前:
1. 说明你对现状和目标的理解;
2. 找出会影响方案的缺失信息;
3. 最多向我提出 <数量> 个关键问题;
4. 根据我的回答给出分步骤计划;
5. 每一步说明涉及文件和验证方式。

限制条件:
- <不能改变的内容>
- <不在本次范围内的内容>
- <技术或安全约束>

完成标准:
- <测试要求>
- <行为要求>
- <最终交付物>

在我确认计划前,不要修改文件。

模板不需要每次逐字填写。任务越简单,提示词越可以缩短。它的价值在于提醒你:目标、上下文、边界和完成标准缺一不可。

保存规划结果

退出 Codex:

/exit

回到终端后运行:

git status
git diff

你应该看到 PLAN.md 和 PROJECT_BRIEF.md 的变化,不应该看到 Python 程序文件。

确认无误后可以按 Q 退出,然后执行下面的提交命令:

git add PROJECT_BRIEF.md PLAN.md
git commit -m "docs: define TaskFlow 1.0 plan"

如果上一篇没有成功提交,可以把当前两个文档和之前的项目说明一起提交。提交信息不必与示例完全一致,但应能说明这一阶段完成了什么。

本篇完成检查

继续下一篇之前,请确认:

  • Python 3 可以在终端中运行;
  • 你能进入和退出 Plan 模式;
  • Codex 在规划阶段没有创建程序代码;
  • PROJECT_BRIEF.md 已包含明确需求和验收条件;
  • PLAN.md 已列出分阶段步骤和验证方式;
  • 第一版只包含 add、list、done;
  • 测试必须使用临时目录;
  • 计划中没有数据库、网络同步或图形界面;
  • 你已经用 /diff 检查规划文件。

下一篇,我们会把这份计划交还给 Codex,让它逐步完成 TaskFlow 1.0,并亲自运行测试和三个核心命令。

参考资料


07 完成TaskFlow第一版

预计阅读时间:50 分钟
本篇目标:让 Codex 根据已经确认的计划完成 TaskFlow 1.0,并通过自动测试、手动操作和代码审查验证结果。

现在,项目里应该有两份关键文档:

  • PROJECT_BRIEF.md:说明 TaskFlow 1.0 要解决什么问题;
  • PLAN.md:说明准备如何实现和验证。

这一篇开始写代码。我们的关注点不只是“Codex 能不能生成一个程序”,而是怎样让它在明确范围内工作,并给出可以检查的证据。

开始前检查项目状态

进入项目目录。

macOS、Linux 或 WSL2

cd ~/codex-course/taskflow

Windows PowerShell

Set-Location "$HOME\codex-course\taskflow"

检查文件和 Git 状态:

git status

目录中至少应该有:

PROJECT_BRIEF.md
PLAN.md

如果规划文件还没有提交也可以继续,但先确认其中没有未检查的错误。Codex 会把它们当作本次任务的重要依据。

以工作区可写模式启动 Codex

运行:

codex --sandbox workspace-write --ask-for-approval on-request

进入后输入:

/status

确认:

  • 当前目录是 taskflow;
  • 权限模式是 Workspace(Ask for approval);
  • 当前模型符合你的预期。

TaskFlow 只使用 Python 标准库,不需要下载依赖,因此本篇没有开启网络访问的必要。

把关键文档明确交给 Codex

在 Codex CLI 中输入 @,可以搜索工作区文件并把路径加入提示词。

比如,我们可以提交实现任务:

请根据 @PROJECT_BRIEF.md 和 @PLAN.md 实现 TaskFlow 1.0。

执行要求:

1. 开始前先用几句话说明你理解的范围和预计修改的文件;
2. 按 PLAN.md 的顺序实施,不增加计划外功能;
3. 使用 Python 3.11+ 标准库,不安装第三方依赖;
4. 测试必须使用临时目录,不能读写真实的 data/tasks.json;
5. 每完成一个阶段就运行对应检查;
6. 全部实现后运行完整测试;
7. 再实际运行一次 add、list、done;
8. 最后检查 Git Diff,报告修改文件、测试结果和仍然存在的限制。

如果计划和项目现状冲突,请先说明冲突,不要自行扩大范围。

这段提示词没有逐行告诉 Codex 怎样写代码。我们已经通过项目文档明确了目标和边界,具体实现细节可以由它完成。

观察 Codex 的执行过程

Codex 开始后,通常会依次读取规划文件、检查目录、创建程序、编写测试并运行命令。

你不需要盯着每一行输出,但应该留意几类信号。

1. 它有没有先读项目文档

如果 Codex 没有读取 PROJECT_BRIEF.md 和 PLAN.md 就开始写代码,可以立即输入并按回车:

先暂停实现,完整读取 PROJECT_BRIEF.md 和 PLAN.md,再按其中的范围继续。

2. 它有没有安装依赖

第一版只使用标准库,不应该运行 pip install、npm install 或访问外部网络。如果它准备安装依赖,拒绝相关权限请求,并提醒:

本项目只使用 Python 标准库,不要安装任何依赖。请调整方案。

3. 它有没有修改范围外文件

预计新增或修改的文件是:

taskflow.py
tests/test_taskflow.py
README.md
.gitignore
PROJECT_BRIEF.md(只在发现必要的小修正时)
PLAN.md(一般不需要再改)

如果出现数据库配置、Web 页面、打包脚本或其他大型结构,说明实现已经偏离范围。

4. 它有没有真正运行测试

“已经编写测试”和“测试已经通过”是两件事。观察它是否实际执行了测试命令,并报告测试数量和结果。

TaskFlow 1.0 应该长什么样

实现完成后,项目结构应大致如下:

taskflow/
├── .gitignore
├── PLAN.md
├── PROJECT_BRIEF.md
├── README.md
├── taskflow.py
└── tests/
    └── test_taskflow.py

手动运行后还会出现:

data/
└── tasks.json

data/tasks.json 是运行数据,不应该由自动测试写入,也通常不需要提交进 Git。

你的实际结构可能略有差异。例如,本课程统一使用 tests/ 目录;如果生成的测试在根目录,先移动到 tests/ 并核对导入路径和测试发现。只要没有引入不必要的复杂度,并且命令、测试和文档保持一致,就不必为了完全匹配示例而返工。

先检查文件变化

Codex 报告完成后,输入:

/diff

不要急着看每一行 Python 语法,先从范围开始检查:

  1. 新增了哪些文件?
  2. 是否修改了计划外文件?
  3. 是否包含真实 API Key、账号信息或本机绝对路径?
  4. .gitignore 是否忽略运行数据和 Python 缓存?
  5. README 中的命令是否与程序实际接口一致?

.gitignore 至少应覆盖类似内容:

__pycache__/
*.pyc
data/tasks.json

不要求内容逐字相同,但不应把 PROJECT_BRIEF.md、PLAN.md、README 或测试文件误加入忽略列表。

自己运行自动测试

Codex 已经运行过测试,你仍然应该亲自再运行一次。这可以确认测试不依赖 Agent 会话中的临时状态。

先退出 Codex,或者在 Codex 输入行前使用 ! 执行命令。

macOS、Linux 或 WSL2

在 Codex 中输入:

!python3 -m unittest discover -s tests -v

Windows

输入:

!py -m unittest discover -s tests -v

如果你的 Windows 只能使用 python,把 py 替换成 python。

成功时,你应该看到每个测试后面显示 ok,最后出现类似:

Ran 6 tests in 0.0xxs

OK

测试数量不一定正好是 6,但至少应覆盖:

  • 添加第一条任务;
  • 连续添加时 ID 递增;
  • 查看空任务列表;
  • 查看未完成与已完成任务;
  • 完成存在的任务;
  • 完成不存在的任务时返回错误。

如果测试失败

不要只把最后一行“FAILED”交给 Codex。把完整测试命令和失败输出留在会话中,然后说:

刚才的完整测试出现失败。请先阅读失败输出,说明哪个行为与需求不一致,
再做最小修改。不要跳过或删除测试。修复后重新运行完整测试。

这会让修复过程围绕行为和证据展开,而不是为了让测试变绿随意修改测试本身。

手动完成一次真实操作

自动测试通过后,再用真实数据文件走一遍用户流程。

macOS、Linux 或 WSL2

添加第一条任务:

!python3 taskflow.py --data data/tasks.json add "完成 Codex 教程第六篇"

查看任务:

!python3 taskflow.py --data data/tasks.json list

标记第一条任务完成:

!python3 taskflow.py --data data/tasks.json done 1

再次查看:

!python3 taskflow.py --data data/tasks.json list

Windows

添加任务:

!py taskflow.py --data data\tasks.json add "完成 Codex 教程第六篇"

查看任务:

!py taskflow.py --data data\tasks.json list

完成任务:

!py taskflow.py --data data\tasks.json done 1

再次查看:

!py taskflow.py --data data\tasks.json list

输出格式由实现决定,可能是:

Added task 1: 完成 Codex 教程第六篇

[ ] 1  完成 Codex 教程第六篇

Completed task 1

[x] 1  完成 Codex 教程第六篇

文字不必完全相同,但应该能够清楚看出任务 ID、标题和完成状态。

测试错误路径

再尝试完成一个不存在的任务:

macOS、Linux 或 WSL2:

!python3 taskflow.py --data data/tasks.json done 999; echo $?

Windows:

!py taskflow.py --data data\tasks.json done 999; $LASTEXITCODE

程序应该给出明确错误,并返回非零退出码,而不是悄悄报告成功。

检查 JSON 数据文件

运行完手动流程后,让 Codex 检查数据:

请读取 data/tasks.json,确认:

1. 文件是合法 JSON;
2. 第一条任务包含整数 ID、标题、完成状态和创建时间;
3. 完成状态已经更新;
4. 没有重复 ID;
5. 不要修改文件,只报告检查结果。

你也可以直接查看文件。

macOS、Linux 或 WSL2:

!python3 -m json.tool data/tasks.json

Windows:

!py -m json.tool data\tasks.json

如果 JSON 合法,命令会把内容格式化输出;如果格式损坏,它会显示解析错误。

让 Codex 解释实现,而不是只给总结

现在项目已经可以运行,可以要求 Codex 帮助你理解代码:

请解释 TaskFlow 1.0 的实现,面向刚开始学习 Python 的读者。

按下面的顺序说明:
1. 命令行参数怎样进入程序;
2. JSON 数据怎样读取和保存;
3. add、list、done 分别调用了哪些函数;
4. 测试怎样避免修改真实数据;
5. 如果以后增加筛选功能,最可能修改哪里。

请引用实际文件和函数名,不要修改代码。

这类解释比让它逐行翻译代码更有用,因为它展示了程序的结构和数据流。

如果解释与实际代码不一致,指出具体位置,让它重新读取后回答。Agent 的总结也需要以文件内容为准。

检查 README 是否真的能用

打开 README.md,确认至少包含:

  • 项目是做什么的;
  • Python 版本要求;
  • 三个子命令的用途;
  • macOS、Linux、WSL2 使用 python3 的示例;
  • Windows 使用 py 或 python 的示例;
  • 怎样运行测试;
  • 当前版本不支持哪些功能;
  • 数据默认保存在哪里。

可以让 Codex 做一次“从零使用”检查:

请只根据 README.md,模拟一个第一次接触项目的用户。
检查他是否能够完成安装前检查、添加任务、查看任务、完成任务和运行测试。
列出缺失或含糊的步骤。先报告问题,不要直接修改。

确认问题后,再决定是否让它更新 README。

使用 /review 做一次代码审查

输入:

/review

选择审查未提交修改(Review uncommitted changes)。

审查结果可能包含真正的问题,也可能只是改进建议。处理前先判断:

  • 这个问题能否实际触发?
  • 是否违反 PROJECT_BRIEF.md 的验收条件?
  • 修改会不会扩大第一版范围?
  • 是否可以用测试证明问题和修复?

如果审查发现明确问题,可以说:

请先为这个问题补充一个能够失败的测试,再做最小修复。
不要处理其他风格建议。完成后运行完整测试。

让 Codex 做最终验收

输入:

请对照 PROJECT_BRIEF.md 和 PLAN.md 做最终验收。

逐项检查:
- 三个子命令是否完成;
- 数据格式是否符合要求;
- 错误路径是否返回非零退出码;
- 测试是否使用临时目录;
- README 是否覆盖不同系统;
- 是否出现计划外功能或依赖;
- 完整测试是否通过。

请把每项标记为“通过”“未通过”或“无法确认”,并给出对应证据。
不要为了让结果全部通过而继续修改文件。

“无法确认”并不一定代表失败。它提醒你还有某些结果需要亲自检查。比起笼统地说“全部完成”,带证据的验收表更值得信任。

保存 TaskFlow 1.0

退出 Codex:

/exit

回到终端后检查:

git status
git diff

确认 data/tasks.json 没有出现在待提交文件中。如果出现,检查 .gitignore 是否正确。

将项目文件加入暂存区:

git add .

查看即将提交的内容:

git diff --cached

确认没有密钥、本机隐私路径或运行数据后,提交:

git commit -m "feat: implement TaskFlow 1.0"

这一篇真正学到的流程

回顾刚才的操作,你已经完成了一次完整的 Agent 开发循环:

确认上下文
→ 提交有边界的任务
→ 观察执行范围
→ 查看文件差异
→ 运行自动测试
→ 完成手动验证
→ 检查数据文件
→ 审查代码
→ 对照需求验收
→ 保存结果

以后不管开发的是命令行工具、网站还是后端服务,都可以复用这条主线。项目会更复杂,验证方法会变化,但“目标、执行、证据、验收”的顺序不会变。

本篇完成检查

继续后面的调试教程之前,请确认:

  • taskflow.py 可以运行;
  • add 能新增任务;
  • list 能显示任务状态;
  • done 能完成指定 ID 的任务;
  • 不存在的 ID 会返回错误;
  • data/tasks.json 是合法 JSON;
  • 自动测试全部通过;
  • 测试没有修改真实数据文件;
  • README 中的命令可以直接执行;
  • /diff 中没有计划外文件;
  • /review 的问题已经逐项判断;
  • TaskFlow 1.0 已经保存到 Git 提交中。

下一篇,我们会给 TaskFlow 制造一个可以稳定复现的问题,再学习怎样让 Codex 先定位根因、补充回归测试,最后完成最小修复。

参考资料


08 先复现再修复-让Codex可靠地调试

预计阅读时间:40 分钟
本篇目标:用一次真实故障修复,走完“复现问题——定位原因——补回归测试——最小修复——完整验证”的全流程。

TaskFlow 1.0 已经可以添加、查看和完成任务。接下来我们先不增加新功能,而是处理一个更接近真实开发的问题:数据文件一旦损坏,程序就会把整段 Python Traceback 扔给用户。

你当然可以直接对 Codex 说“把这个报错修了”,但这样做的风险很大:Codex 可能猜对原因,也可能只是把异常藏起来。可靠的调试不是从“改代码”开始,而是从“拿到证据”开始。

OpenAI 的 Codex 最佳实践也建议,修改代码时要给出明确目标、相关上下文、约束和完成标准,并通过测试、实际行为和 Diff 验证结果。官方参考:Best practices。

先确认起点是干净的

进入 TaskFlow 项目。

macOS、Linux 或 WSL2:

cd ~/codex-course/taskflow
git status
python3 -m unittest 
或 
python3 -m unittest discover -s tests -v

Windows PowerShell:

Set-Location "$HOME\codex-course\taskflow"
git status
py -m unittest 
或 
py -m unittest discover -s tests -v

这里要确认两件事:

  • 上一篇完成的测试仍然全部通过;
  • Git 工作区里没有一批来路不明的改动。

如果基线测试本来就失败,先不要把新故障混进去。否则修复之后,你很难判断某个失败究竟是旧问题,还是新改动引起的。

本篇要刻意制造一份损坏的 tasks.json,但不要直接破坏自己的 data/tasks.json。我们会让测试在临时目录中生成故障数据,测试结束后自动清理。

把“程序报错了”改成可验收的问题

启动 Codex:

codex --sandbox workspace-write --ask-for-approval on-request

输入:

先探测你的 TaskFlow 读取损坏 JSON 时的行为:若显示 Traceback,按本篇修复;若已输出友好提示并非零退出,则作为补覆盖练习,无需故意破坏当前主线。

请先不要修改代码。请:
1. 找到数据文件的读取入口和现有测试;
2. 在测试临时目录中创建一份不合法的 tasks.json;
3. 运行最小复现,记录完整命令、退出码和关键输出;
4. 说明异常从哪里产生,又在哪一层没有被转换成用户错误;
5. 给出最小修复方案,等我确认后再改。

预期行为:显示简短、可理解的错误信息,不显示 Traceback,并以非 0 状态结束。
不要读写真实的 data/tasks.json。

这段任务把一句模糊的“修好报错”拆成了四个可检查的事实:

  1. 什么输入能够触发问题;
  2. 当前实际输出是什么;
  3. 期望输出是什么;
  4. 怎样才算修复完成。

判断 Codex 是否真的复现了问题

在当前版本中,Codex 的实际输出可能会因代码结构不同而略有差异,但证据至少应该包含下面几项:

复现文件:<临时目录>/data/tasks.json
文件内容:{not valid json
运行目录:TaskFlow 项目根目录
运行命令:python3 taskflow.py --data "<临时文件绝对路径>" list(先替换路径占位符)
实际结果:输出 Traceback,末尾为 JSONDecodeError
退出码:非 0
真实数据:未读写

只说“我看代码后认为这里有问题”,不算复现。复现必须有实际输入、运行命令和可观察的结果。

如果 Codex 说无法复现,先核对三个路径:

  • 损坏文件写在哪里;
  • 程序实际从哪里读数据;
  • 运行命令时的当前目录是哪里。

这三者不一致,往往就会出现“测试写了损坏文件,程序却读了另一份文件”的情况。

把根因写成一条因果链

一份合格的调查结果,不应只说“JSON 解析失败”,而应该把事情说完整:

tasks.json 包含不合法 JSON
  ↓
数据加载函数调用 json.load
  ↓
json.load 抛出 JSONDecodeError
  ↓
命令入口没有把该异常转换成面向用户的错误
  ↓
Python 默认向终端输出完整 Traceback

这条因果链会直接决定修复位置。如果错误只应该在 CLI 中转换成用户提示,就不必为了这一个问题重写整个数据层。

先补一个会失败的回归测试

确认根因后输入:

请先补一个回归测试,暂时不修改业务代码。

测试必须:
- 在临时目录中创建不合法 tasks.json;
- 走用户真正会走的 CLI 入口,而不是只直接调用一个内部辅助函数;
- 断言退出码为非 0;
- 断言输出中有“数据文件损坏”或同等明确的提示;
- 断言输出中没有 Traceback;
- 确认真实 data/tasks.json 没有被读写。

写完后只运行这个测试,向我展示它在当前代码上失败的关键输出。

修复前的理想证据应类似:

FAIL: test_list_reports_corrupted_data
AssertionError: 'Traceback' unexpectedly found in output

Ran 1 test
FAILED (failures=1)

测试名和输出不必与示例完全相同,但失败原因必须正好指向我们要修的问题。

如果新测试立即通过,先核对临时文件、CLI 路径和断言;若实现原本已正确,这就是有效的覆盖补充。要练习先红后绿,可在独立副本暂时移除对应异常转换,再证明测试失败并恢复,不修改个人数据或强行要求主线报错。

只允许最小修复

看到稳定的失败后,再输入:

现在实施最小修复。

约束:
1. 只处理可以明确识别的 JSON 解析错误;
2. 不改变正常数据的读取和保存格式;
3. 不要用 except Exception 吞掉其他异常;
4. 用户看到简短错误,程序返回非 0 状态;
5. 先运行新增回归测试,再运行完整测试;
6. 展示 Diff,说明为什么修改位置和范围已经足够。

要特别小心下面这种写法:

try:
    data = load_tasks()
except Exception:
    data = []

它看似没有再报错,实际上却可能把权限错误、磁盘错误和程序缺陷全部伪装成“任务列表为空”。如果之后再保存数据,还可能覆盖原文件。

更合理的方向是只捕获 json.JSONDecodeError,然后在贴近 CLI 的边界把它转换成用户可理解的提示。具体放在数据层还是命令入口,要根据 TaskFlow 的实际结构决定,不必为了套示例强行重构。

验收修复

macOS、Linux 或 WSL2:

!python3 -m unittest 
或 
!python3 -m unittest discover -s tests -v

Windows:

!py -m unittest 
或 
!py -m unittest discover -s tests -v

最后看 Diff,不要只看结论

输入:

/diff

重点检查:

  • 是否只改了数据加载、命令错误处理和相关测试;
  • 是否误改了 JSON 结构或正常保存流程;
  • 是否在仓库中留下临时损坏文件;
  • 是否将真实任务数据加入 Git;
  • 测试是否真的检查了用户行为。

还可以让 Codex 从风险角度自审一次:

请审查当前 Diff,只报告可能导致行为错误、数据丢失、异常被过度吞掉或测试失真的问题。不要为了代码风格扩大修改范围。

确认后再提交:

!git add .
!git commit -m "handle corrupted task data"

三种常见偏差

Codex 一上来就改代码

让它暂停写入,回到“复现命令、实际输出、根因链”。没有证据时,不要用修改幅度来伪装调试进展。

Codex 顺手做了大范围重构

让它说明每个文件与当前缺陷的关系。无法直接对应的变更,原则上都应从本次修复中移出。

测试通过,用户体验却没改变

这通常说明测试绕过了真实 CLI,只验证了内部函数。保留单元测试,再增加一个从用户入口出发的测试或临时目录实跑。

一份可复用的调试提示词

请先复现问题,不要立即改代码。

实际现象:<用户看到了什么>
最小复现:<已知操作或输入>
期望结果:<应该发生什么>
安全边界:<不能触碰的数据或系统>

请依次完成:
1. 确认环境和当前版本;
2. 构造最小复现并记录证据;
3. 用代码路径解释根因;
4. 补一个在当前版本上会失败的回归测试;
5. 给出最小修复方案。

得到我确认后再实施。实施后运行局部测试、完整测试和真实入口验证,最后审查 Diff。

本篇小结

修复缺陷时,证据的顺序比代码生成的速度更重要:

  1. 确认干净基线,保护真实数据;
  2. 用最小输入复现问题;
  3. 把根因写成可检查的因果链;
  4. 让回归测试在缺陷版本上先失败;
  5. 只修已经证实的问题;
  6. 用局部测试、完整测试和真实行为共同验收;
  7. 最后用 Diff 检查修改范围。

下一篇,我们会给 TaskFlow 加上 CSV 导入功能,并借这次开发看清沙箱和审批各自在保护什么。


09 权限沙箱与安全边界

本课按能力区分调查 read-only 与实施 workspace-write。若 /permissions 未显示只读,退出后用 codex --sandbox read-only --ask-for-approval on-request 启动;写入前明确切换 workspace-write 并提供计划。以实际权限摘要为准。

预计阅读时间:45 分钟
本篇目标:通过给 TaskFlow 增加 CSV 导入,理解沙箱、审批和权限范围的区别,并学会判断一次授权是否合理。

Codex 与普通聊天工具最明显的不同,是它不只给建议,还可以读文件、改代码和运行命令。因此,一个任务除了要说清“要做什么”,还要说清“允许在哪里做、可以使用什么资源”。

这一篇不会用故意危险的命令测试安全性。我们会用一个正常需要读写文件、却完全不需要联网的功能,观察 Codex 如何在边界内工作。

先分清沙箱和审批

可以把它们理解成两个不同的问题:

  • 沙箱回答“Codex 当前可以自主访问哪些文件和资源”;
  • 审批策略回答“当操作需要越过边界时,Codex 是否会停下来请求批准”。

官方文档列出的常见沙箱模式包括:

模式 能做什么 适合场景
read-only 主要用于检查文件,不在工作区写入 读代码、解释项目、做只读审查
workspace-write 可以在工作区内读写文件并运行常规本地命令 日常开发、测试、文档修改
danger-full-access 取消沙箱的文件系统和网络边界 只在你确实愿意提供完整访问时使用

常见审批策略中,on-request 表示 Codex 先在沙箱内工作,必须越界时再请求审批;never 则表示不会停下来向用户发起审批。never 不等于自动获得更多权限:沙箱边界仍然由当前配置决定。

官方文档:Sandbox。

先检查权限,再开始写功能

在 TaskFlow 目录中启动:

codex --sandbox workspace-write --ask-for-approval on-request

进入交互界面后输入:

/permissions

当前版本会打开权限选择器。本篇需要修改 TaskFlow 项目内的代码、测试和样例文件,因此不能继续使用只读沙箱。

在你当前看到的三个选项中,应该选择 Ask for approval。它对应本篇启动命令中的 workspace-write 加 on-request:Codex 可以在 TaskFlow 工作区内修改文件和运行常规命令,越过边界时则由你决定是否批准。

另外两个选项不是本篇默认值:

  • Approve for me 仍保留工作区边界,但把越界请求交给自动审查;
  • Full access 会放开文件系统和网络边界,本篇完全不需要。

本篇不需要:

  • 读取桌面、下载目录或其他项目;
  • 安装第三方依赖;
  • 访问公网;
  • 读取 .env、SSH 密钥或云服务凭据;
  • 使用 Full Access。

先写出“不需要什么”很有用。如果之后出现与这些范围冲突的申请,你就知道应该先停下来问为什么。

先定义 CSV 导入的行为

这一节只定义功能,还没有开始创建文件或修改代码。此时项目中还不 存在 samples/ 目录和 samples/tasks.csv文件,所以下面的命令暂时不要执行。

我们希望新增的命令用法是:

python3 taskflow.py --data <任务数据文件> import-csv <CSV 文件>

例如,功能完成后,可以让它读取:

samples/tasks.csv

本篇使用的 samples/tasks.csv 是一份固定的练习文件。它的完整内容如下:

title,completed
整理会议纪要,false
提交报销,true
准备周报,false

其中:

  • 第一行是表头;
  • 后面三行是准备导入的三条任务;
  • false 表示未完成;
  • true 表示已完成。

这份文件将在第五节创建。现在不需要现在手动创建,也不要现在运行导入命令,我们在这里只需要先确定导入规则:

  • CSV 必须包含 title 和 completed 两列;
  • title 去掉首尾空格后不能为空;
  • completed 只接受 true 或 false;
  • 只读取命令参数指定的 CSV 文件;
  • 新任务追加到现有列表,不覆盖旧数据;
  • 任意一行不合法时,整次导入失败,原数据保持不变;
  • 本版不做重复任务去重,重复导入会照实追加,并在 README 中说明。

让 Codex 先解释权限需求

输入:

我要为 TaskFlow 增加 import-csv 命令。

请先检查现有代码、数据保存方式和测试,给出实现计划,暂时不修改文件。

功能规则:
1. CSV 必须包含 title 和 completed 两列;
2. title 去掉首尾空格后不能为空;
3. completed 只接受 true 或 false;
4. 只读取命令参数指定的 CSV 文件;
5. 新任务追加到现有列表,不覆盖旧数据;
6. 任意一行不合法时,整次导入失败,原数据保持不变;
7. 本版不做重复任务去重,重复导入会照实追加,并在 README 中说明。

安全边界:
1. 只读取命令参数明确指定的 CSV;
2. 测试使用临时目录,不触碰真实 data/tasks.json;
3. 不访问网络,不安装依赖;
4. 不读取工作区外的文件;
5. 导入失败时不能留下部分写入。

请在计划中单独说明:本任务需要读取和写入哪些路径,为什么 workspace-write 已经足够。

理想的权限说明应该很简单:

需要读:taskflow.py、tests/、README.md、用户指定的 CSV
需要写:taskflow.py、tests/、README.md、samples/tasks.csv
不需要:网络、第三方依赖、工作区外目录

如果它声称需要 Full Access,让它指出哪一个具体步骤无法在当前工作区中完成。对这个功能来说,通常没有充分理由扩大权限。

先在工作区内准备样例

确认计划后,把下面的完整任务交给 Codex:

请先完成下面的准备工作:

1. 如果 samples 目录不存在,就创建它;
2. 创建 samples/tasks.csv;
3. 文件内容必须严格如下:

title,completed
整理会议纪要,false
提交报销,true
准备周报,false

创建后重新读取这个文件,确认表头和三行数据正确。

然后按照已经确认的计划实现 import-csv,补充自动测试并更新 README。完成后先运行导入功能的测试,再运行完整测试。

测试必须使用临时任务数据,不能读写真实的 data/tasks.json。不要申请网络权限,也不要访问工作区外的文件。

创建完成后,学员可以亲自检查文件。

macOS、Linux 或 WSL2:

!cat samples/tasks.csv

Windows PowerShell:

!Get-Content samples\tasks.csv

看到完整的表头和三行任务后,才能确认样例已经准备好。

实际测试导入功能时,也不要直接运行:

python3 taskflow.py import-csv samples/tasks.csv

因为这可能写入默认的真实数据文件。应让 Codex通过 --data 明确指定临时的 tasks.json,例如:

请在系统临时目录中创建一份独立的 tasks.json,然后执行完整 CLI:

python3 taskflow.py --data <临时tasks.json路径> import-csv samples/tasks.csv

不要读取或修改项目中的 data/tasks.json。执行后报告退出码、导入数量和临时数据文件内容。

这一步的关键不是一定要用 samples/。关键是第一次练习时,样例、代码和测试都留在一个可检查的项目边界中。

如果真实 CSV 位于工作区之外,对初学者来说,最容易检查的方法是先复制一份脱敏副本到项目的 imports/ 目录。如果确实需要使用额外目录,应当只增加那一个明确路径,并先用当前版本的 codex --help 确认命令行选项,不要为了一个文件开放整个主目录。

看到审批时,具体看什么

审批弹窗的外观可能随版本变化,但判断方法基本不变。

先看操作

它是要读文件、写文件、运行测试、联网,还是执行删除、发布等会改变外部状态的操作?

再看对象

目标路径或网络地址是什么?它是否与当前任务直接相关?

再看范围

这次授权只针对当前操作,还是会对后续一类命令持续生效?能批准单次操作,就不要因为方便而扩大成宽泛规则。

最后看是否必要

可以在工作区内完成的任务,为什么要读取其他目录?可以用标准库完成的功能,为什么要下载依赖?

对本篇任务来说,下列操作一般符合预期:

  • 在 TaskFlow 项目中创建样例和测试;
  • 修改 taskflow.py 和 README;
  • 运行 unittest;
  • 读取你明确放入项目的 CSV;
  • 查看 Git Diff。

下列情况则应该先拒绝或暂停确认:

  • 读取无关项目、SSH 目录、钥匙串或云凭据;
  • 将 CSV 发送到外部服务;
  • 下载一个本任务根本不需要的依赖;
  • 覆盖或删除真实任务数据;
  • 没有具体理由地切换到 danger-full-access。

验证正常导入,也验证失败时不写一半

完成后先运行完整测试。

macOS、Linux 或 WSL2:

!python3 -m unittest
# 二选一,选择适用于当前系统的命令
!python3 -m unittest discover -s tests -v

Windows:

!py -m unittest
# 二选一,选择适用于当前系统的命令
!py -m unittest discover -s tests -v

然后让 Codex 在临时目录中实跑下列场景:

场景 期望结果
三行合法数据 成功导入 3 条,退出码为 0
缺少 title 列 提示缺少必需列,退出码非 0,旧数据不变
某行标题为空 指出错误行或有用的定位信息,整次不写入
completed 为 yes 按当前规则拒绝,不悄悄猜测
数据写入前校验失败 现有任务数量和内容完全不变
重复导入同一文件 行为与 README 中约定一致

输入:

请在临时目录中验证上述六个场景。每个场景列出输入文件的关键内容、运行命令、退出码、关键输出,以及导入前后的任务数量。不要读写真实 data/tasks.json。

正常导入的输出可能类似:

已导入 3 条任务。

非法布尔值则可能类似:

错误:第 4 行 completed 必须是 true 或 false。

文字不必与示例相同,重点是用户能找到问题,失败后数据仍然完整。

用 Diff 检查代码范围和数据风险

输入:

/diff

这次不只看“功能能不能跑”,还要看:

  • 是否引入了本来不需要的第三方库;
  • 是否写死了某台电脑的绝对路径;
  • 是否一边读 CSV 一边直接写正式数据,导致中途失败时留下半成品;
  • 错误信息是否泄露了不必要的完整文件内容;
  • 测试是否使用临时目录;
  • 是否把真实 CSV 或运行后的 tasks.json 加入了 Git。

再做一次只读审查:

请只从权限与数据完整性角度审查当前 Diff,不要修改:
- 文件读取范围是否过大;
- 输入是否在写入前完整校验;
- 失败是否可能留下部分写入;
- 日志或错误信息是否泄露文件内容;
- 新增权限是否都与功能直接相关。

每个发现给出文件位置和触发条件。

确认后再通过 git 提交实际变更的文件。

把这一阶段提交到 Git

测试、手工验证和 Diff 都通过后,打开另一个终端,进入 TaskFlow 项目根目录。先查看实际改动:

git status --short

确认列表中只有本篇产生的代码、测试、文档和样例文件,再明确暂存它们:

git add taskflow.py tests README.md samples/tasks.csv

如果 Codex 实际还修改了其他必要文件,不要直接使用 git add .。先确认它确实属于 CSV 导入功能,再把准确路径补到 git add 命令中。

提交前检查暂存区:

git diff --cached --check
git diff --cached

前一条正常情况下没有输出;后一条应只包含已经审查过的 CSV 导入改动。确认无误后提交:

git commit -m "feat: add CSV import"
git status --short

提交成功时会看到提交摘要;最后一条命令应当没有输出。若仍列出文件,先判断它们是遗漏的本篇改动,还是不应提交的运行数据。data/tasks.json 等真实数据不应被顺手加入版本库。

为什么“一直批准”和“什么都拒绝”都不理想

如果每次看到审批都直接允许,审批就失去了意义。反过来,如果任何写入和测试都拒绝,Codex 又无法完成开发任务。

更实用的方法是:事先界定工作区和允许的操作,边界内的常规工作让 Codex 连续执行,越界时再检查具体原因。沙箱的价值之一,就是减少无意义的反复确认,同时保留清楚的信任边界。

一份可复用的权限任务模板

请完成:<任务目标>

允许的范围:
- 可读取:<必要的目录或文件>
- 可写入:<必要的目录或文件>
- 可运行:<测试、构建或检查命令>

本任务不需要:
- <网络、安装依赖、工作区外文件等>

安全要求:
- 先读取和验证,再写入;
- 失败时不能留下部分结果;
- 删除、覆盖、发布和外部发送前先停下来说明;
- 需要扩大权限时,说明具体操作、目标和不可替代性。

完成后报告实际读写范围、运行命令、验证结果和未执行的高风险操作。

本篇小结

沙箱决定 Codex 在什么边界内能自主行动,审批策略决定它越过边界时怎样停下来。判断一次授权时,不要只看“Codex 说需要”,要看操作、对象、范围和必要性。

本篇完成的 CSV 导入只需要工作区内的读写和本地测试。权限越贴合任务,执行过程越容易检查。

下一篇,我们会把标准库、临时目录、数据保护和完整测试等约束写进 AGENTS.md,让新会话也能自动了解项目的工作方式。


10 用AGENTS与配置文件教会Codex理解项目

预计阅读时间:45 分钟
本篇目标:把 TaskFlow 的结构、测试方式和安全约束固化下来,并通过一次新会话验证它们是否真的生效。

前面几篇里,我们反复告诉 Codex:

  • TaskFlow 只使用 Python 标准库;
  • 测试必须使用临时目录;
  • 不能读写真实 data/tasks.json;
  • 修改后要先跑局部测试,再跑完整测试;
  • CLI 行为变化时要同步 README。

如果这些要求每次都由你重写,时间久了总会漏掉一两条。AGENTS.md 的作用,就是把“这个仓库中应该长期遵守的工作方式”放进项目,让 Codex 在开始任务前自动读取。

配置文件解决的是另一类问题:Codex 用什么沙箱模式、什么审批策略、哪些功能开启。两者一个管“在项目里怎样做事”,一个管“Codex 以什么运行方式开始工作”。

README、AGENTS.md 和 config.toml 分别管什么

文件 主要读者 适合放的内容 不适合放的内容
README.md 项目使用者 安装、功能、命令示例、数据格式 Agent 的内部工作约定
AGENTS.md Codex 等开发 Agent 项目结构、验证命令、持续约束、完成标准 API Key、短期临时任务、大段用户手册
config.toml Codex 运行时 模型、推理强度、沙箱、审批、功能开关等 项目业务规则和敏感凭据

一个实用的判断方法是:

  • 用户需要知道的,写进 README;
  • Codex 每次开工都应遵守的,写进 AGENTS.md;
  • Codex 应该以什么权限和功能运行,写进 config.toml;
  • 只对当前一次任务有效的,直接写在本次提示词里。

官方建议也是保持 AGENTS.md 简短、准确,从重要规则开始,再根据反复出现的问题逐步增加。参考:Codex best practices。

用 /init 建立初稿,但不直接照单全收

在 TaskFlow 根目录启动 Codex,然后输入:

/init

/init 会根据当前目录快速生成一份初始 AGENTS.md。它是一个起点,不是项目规则的最终答案。

生成后先不要急着提交,让 Codex 说明它是从哪些文件推断出项目命令和结构的。它能看见当前仓库里有什么,却不一定知道我们前面特别在意的数据安全和验收顺序。

可以继续输入:

请审查刚生成的 AGENTS.md,暂时不修改。

请核对:
1. 项目结构是否与当前仓库一致;
2. 测试命令是否已经实际运行验证;
3. 是否写明测试使用临时目录;
4. 是否保护真实 data/tasks.json;
5. 是否保留 Python 标准库约束;
6. 是否写清了修改后的验收方式;
7. 是否有空泛、重复或无法执行的句子。

对每个问题给出证据和修订建议。

为 TaskFlow 写一份足够用、但不臃肿的 AGENTS.md

可以把下面的版本作为核对基准,再按你的实际文件名调整:

# TaskFlow 项目协作指南

## 项目概况

TaskFlow 是一个使用 Python 3.11+ 标准库开发的命令行任务管理器,不依赖第三方库。

保持实现简单,并确保现有 JSON 数据仍然兼容。

## 重要文件和目录

- `taskflow.py`:CLI 入口和核心功能
- `tests/`:unittest 测试
- `samples/`:不含敏感信息的示例输入
- `README.md`:面向用户的命令和使用说明

## 验证方式

- macOS、Linux、WSL2:`python3 -m unittest discover -s tests -v`
- Windows:`py -m unittest discover -s tests -v`
- 修改后先运行相关测试,再运行完整测试。
- 修改 CLI 行为后,使用临时数据运行受影响的命令,并记录退出码。
- 不要只根据 Codex 的完成报告判断结果,必须检查实际输出和 Diff。

## 项目约束

- 除非任务明确改变这一约定,否则只使用 Python 标准库。
- 自动测试必须使用临时目录。
- 测试和调试不得读取或覆盖真实的 `data/tasks.json`。
- 日常开发任务不得访问网络或安装依赖。
- 除非已经制定并测试迁移方案,否则必须兼容旧任务数据。
- 不得提交密钥、个人绝对路径、运行数据或缓存文件。
- 不要进行与当前任务无关的重构。

## 完成标准

- 请求的功能已经实现,重要错误场景有测试覆盖。
- 相关测试和完整测试全部通过。
- 用户可见的 CLI 行为发生变化时,已经同步更新 `README.md`。
- 最终报告列出修改的文件、运行的命令、实际结果和仍然存在的限制。

这份文件里没有“写出优雅代码”“遵循最佳实践”这类句子,因为它们无法直接验收。“测试使用临时目录”和“CLI 变化同步 README”则是可以观察的行为。

把它交给 Codex 时,不要让它不加判断地整段覆盖:

请用下面的内容作为核对基准,修订仓库根目录的 AGENTS.md。

先根据当前项目确认文件名、命令和目录是否真实存在。保留初稿中已经准确的项目信息,删除重复或空泛内容。不要把示例中与当前仓库不符的路径照抄进去。

<粘贴上面的基准内容>

修订后说明删除、保留和新增了什么,以及依据是什么。

理解 AGENTS.md 的发现顺序

Codex 可以同时加载多层项目指令。官方文档描述的核心顺序是:

  1. 先读取 Codex 主目录中的全局指导,默认位于 ~/.codex;
  2. 再从项目根目录向当前工作目录逐层查找;
  3. 同一目录中优先检查 AGENTS.override.md,然后是 AGENTS.md;
  4. 越靠近当前工作目录的指导越具体,会出现在合并后的更后面。

官方详细说明:Custom instructions with AGENTS.md。

对 TaskFlow 来说,刚开始只需要根目录的一份 AGENTS.md:

taskflow/
├── AGENTS.md
├── taskflow.py
├── README.md
├── samples/
└── tests/

不要因为支持分层,就立即在每个目录放一份。只有当子目录确实存在不同的构建或审查规则时,再增加更具体的指导。否则重复规则很容易日后不一致。

AGENTS.override.md 更适合明确的临时覆盖或特殊目录约束,不要把它当成“更高级的默认文件”到处使用。

不要假设它生效了,开新会话验证

AGENTS.md 的意义是影响新的工作过程。因此,修改完成后退出当前 Codex,在 TaskFlow 根目录重新启动。

先让它总结当前指令:

请只读取当前会话已加载的项目指导,不要修改文件。

请列出:
1. 你发现的指令文件及所在层级;
2. TaskFlow 的完整测试命令;
3. 对真实数据的保护规则;
4. 修改 CLI 后的文档要求;
5. 当前任务的完成标准。

还可以从终端做一次只读验证:

codex --ask-for-approval never "Summarize the current project instructions and their sources. Do not modify files."

官方文档也使用这类方式检查指令是否被加载。注意,--ask-for-approval never 只是说不弹出审批,不是赋予 Full Access;命令仍然受当前沙箱和配置约束。

如果它没有说出 TaskFlow 的临时目录和数据保护规则,检查:

  • 文件名是否真的是 AGENTS.md;
  • 文件是否位于仓库根目录到当前目录的路径上;
  • 是否存在更近的 AGENTS.override.md;
  • 启动 Codex 时是否位于你以为的项目目录;
  • 修改后是否新开了会话。

用一个小任务测试行为,不只是复述规则

能复述 AGENTS.md 不等于工作时一定会遵守。继续给它一个边界清楚的小任务:

为 import-csv 增加一个“CSV 只有表头、没有数据行”的测试。

请自行根据项目指导决定使用什么测试目录、需要运行哪些验证,以及是否需要更新 README。不要读写真实任务数据。

观察它是否会:

  • 使用临时目录;
  • 不安装新依赖;
  • 先运行相关测试,再运行完整测试;
  • 在结尾报告实际运行的命令和结果;
  • 根据用户可见行为是否改变,判断 README 是否需要修改,而不是机械地每次都改。

如果它遗漏了某一条,先判断是指令写得不清楚,还是本次执行偏离。只有当一个要求对后续任务都有价值时,才应该补进 AGENTS.md。

什么时候应该修订 AGENTS.md

适合加入的内容:

  • Codex 已经重复犯过的错误;
  • 评审中反复出现的同一条要求;
  • 真实可运行的构建、测试和 lint 命令;
  • 仓库特有的数据、兼容性或安全约束;
  • 可以明确检查的完成标准。

不适合加入的内容:

  • 只用一次的具体功能需求;
  • 一大段代码实现细节;
  • 与当前仓库无关的个人偏好;
  • “保证高质量”“仔细思考”之类无法验收的口号;
  • 密钥、令牌、账号密码和敏感内部地址;
  • 已经过时的目录或命令。

规则越多不代表效果越好。如果一份 AGENTS.md 已经让新成员都很难找到测试命令,Codex 同样会被无关信息干扰。

加入最小项目配置

Codex 的个人默认配置通常放在:

~/.codex/config.toml

仓库特定配置可放在:

.codex/config.toml

官方参考:Sample configuration。

对 TaskFlow 的日常开发,一份小配置就足够:

sandbox_mode = "workspace-write"
approval_policy = "on-request"

它表示:Codex 可以在工作区内完成日常开发,需要超出边界时再请求审批。

配置文件不需要追求“把所有可用字段都写上”。字段越多,未来过时或互相冲突的可能性越高。在增加当前版本的其他配置项之前,先查阅官方配置参考或使用 codex --help。

还要注意两个边界:

  • 不要把 API Key 或其他秘密写进会提交到 Git 的 .codex/config.toml;
  • 不要因为项目里放了一份高权限配置,就对一个陌生仓库不加检查地使用。

用“文件发现”和“实际行为”做双重验收

最终验收不应该只问“你看到 AGENTS.md 了吗”,而应该包含两层。

第一层:它加载了哪些规则

让新会话列出指令来源和关键规则。如果来源不对,先解决目录和文件发现问题。

第二层:它真的按规则工作了吗

用一个小任务检查临时目录、测试顺序、README 判断和最终报告。如果行为与文字不一致,规则就还不算真正落地。

完成后输入:

/diff

确认没有密钥、个人绝对路径和与仓库不符的命令,再按实际变更提交:

git add AGENTS.md .codex/config.toml
git commit -m "add Codex project guidance"

如果验证小任务还改了测试或 README,先在 Diff 中确认这些改动,再把实际需要的文件加入提交。

一份可复用的项目指导检查清单

新建或审查 AGENTS.md 时,可以问:

  • 文件中的目录和命令是否真实存在?
  • 测试命令是否已经实际运行过?
  • 哪些是项目长期约束,哪些只是当前任务?
  • 规则是否可以被观察和验收?
  • 是否正在重复 README、CI 或其他文档的大段内容?
  • 是否有过时命令、本机路径或敏感信息?
  • 更具体的子目录规则是否真有必要?
  • 是否可以通过一个小任务验证它确实生效?

本篇小结

AGENTS.md 不是越长越好。它应该记录真实、持续、可执行的项目规则;config.toml 则负责 Codex 的运行默认值。新会话能复述规则,只是第一步;它能在真实任务中正确使用临时目录、运行测试并保护数据,才说明项目指导真正发挥了作用。

下一篇,我们会把 TaskFlow 升级到 2.0,并学会怎样用计划、目标、恢复和上下文整理管理一项更长的工作。


11 管理长任务-把TaskFlow升级到2.0

预计学习时间:55—70 分钟
本篇目标:把一次跨多个阶段的升级做成可规划、可验证、可中断、也可恢复的长任务。

前面几篇里,我们做的任务大多能在一个会话内完成。到了真实项目,需求常常不是“改一个函数”,而是连续经历规划、实现、测试、修正和文档更新。时间一长,最容易出问题的不是 Codex 不会写代码,而是任务逐渐失去边界:已经做到哪里、哪些决定已经确认、下一步该验证什么,全都只剩在聊天记录里。

这一篇,我们把 TaskFlow 升级到 2.0,加入三个相互关联的能力:

  1. list 可以按完成状态筛选任务;
  2. 新增 stats,显示任务总数、完成数和完成率;
  3. 新增 report,把当前全部任务导出为 Markdown 报告。

这三个功能并不难,难点在于把它们作为一个长任务稳稳落地。我们会同时使用四层保障:

  • 用 Plan 模式先确认路线;
  • 用 Goal 固定最终完成条件;
  • 用仓库里的计划和状态文件保存事实;
  • 用测试、Git Diff 和实际命令证明每个阶段真的完成。

Plan 和 Goal 不是一回事。Plan 回答“准备怎么做”,Goal 回答“什么结果出现以后才算结束”。仓库里的状态文件则负责回答“即使换了会话,别人怎样知道现在做到哪里”。

开始前先建立可回退的基线

进入 TaskFlow 项目目录。macOS、Linux 或 WSL 可以执行:

cd /你的路径/taskflow
git status --short
python3 -m unittest 
# 二选一,选择适用于当前系统的命令
python3 -m unittest discover -s tests -v

Windows PowerShell 使用:

cd C:\你的路径\taskflow
git status --short
py -m unittest 
# 二选一,选择适用于当前系统的命令
py -m unittest discover -s tests -v

这里要确认两件事:

  • git status --short 没有出现你不认识的改动;
  • 升级开始前,原有测试可以通过。

如果测试本来就有失败,不要带着它进入升级。先保存失败命令和报错,把它作为单独问题处理。否则后面出现红灯时,你无法判断是新代码造成的,还是旧问题一直存在。

基线正常后,在同一个项目目录启动 Codex:

codex

本文以支持 Goals 的 Codex CLI 为准。Goals 从 Codex 0.128.0 起提供。如果输入 /goal 后没有对应命令,先退出并运行 codex update,再用 codex --version 检查版本。不同版本可用的斜杠命令可能有差异,最可靠的办法是在输入框键入 / 查看当前命令面板。

先规划,不要让第一个回答直接改代码

在 Codex 输入框中输入:

/plan

然后提交需求:

请规划 TaskFlow 2.0,暂时不要修改文件。

目标:
1. list 支持 --status all|open|done,默认 all;
2. 新增 stats 命令,显示总数、已完成、未完成和完成率;
3. 新增 report --output <path>,导出 Markdown 任务报告;
4. 保持现有 JSON 数据兼容;
5. 继续只使用 Python 标准库;
6. 更新测试和 README。

请先检查当前代码和测试,再把工作拆成“筛选、统计、报告、总体验收”四个阶段。每个阶段写明:
- 修改范围;
- 需要先确认的歧义;
- 验证命令;
- 完成标准;
- 主要风险。

Plan 模式的可见结果应该是一份实施路线,而不是一批已经修改的文件。收到计划后,重点检查下面几个问题:

  • 是否保留了 list 原来的默认行为;
  • 是否明确空任务列表的完成率;
  • 是否说明报告输出目录不存在时怎么办;
  • 是否把业务计算与终端输出分开,以便直接测试;
  • 是否把旧 JSON 数据兼容纳入了最终验收。

如果这些问题没有说清楚,先在规划阶段追问。例如:

补充计划,但仍不要改代码:
1. 空任务列表的完成率统一显示为 0%;
2. report 的父目录不存在时返回清晰错误,不自动创建;
3. 报告结构固定为标题、生成时间、统计摘要、未完成任务和已完成任务;
4. 不增加模板系统。

请据此更新阶段边界和验收标准。

规划阶段多花几分钟,通常比实现后再推倒重来便宜。官方的长任务实践也强调:里程碑应足够小,而且每个里程碑都要带验收条件和验证命令。参见 Run long horizon tasks with Codex。

把计划和进度写进仓库

首次落盘前退出 Plan 模式(选择实施计划或按当前界面的模式切换提示),确认工作区可写;没有可写项时退出后用 codex --sandbox workspace-write --ask-for-approval on-request 重新进入并提供计划。此时只允许写 PLAN.md 和 STATUS.md,随后才授权代码阶段。

聊天记录可以恢复,却不应该成为项目唯一的状态来源。计划确认后,让 Codex 在仓库根目录创建两个短文件:

按照刚才确认的计划,创建 PLAN.md 和 STATUS.md,暂时不要实现功能。

PLAN.md 需要记录:目标、非目标、四个里程碑、每个里程碑的验收条件和验证命令。
STATUS.md 需要记录:当前阶段、已完成项、下一步、最近一次验证及结果、已知问题。

内容保持简短,不要复制整段对话。完成后展示文件摘要和 Git Diff。

随后输入 /diff 查看变化,也可以在另一个终端执行:

git diff -- PLAN.md STATUS.md

你需要看到的是清晰的项目状态,而不是泛泛的待办清单。PLAN.md 至少要能回答“每一步怎样验收”,STATUS.md 至少要能回答“现在做到哪一步、下一步是什么”。

如果项目不希望长期保留这两个文件,也可以把它们放进 docs/development/,或在任务结束后归档。关键不在文件名,而在于把长任务的核心状态放到可检查、可版本化的位置。

选择推进节奏,避免 Goal 越过验收点

本章采用逐阶段人工验收:先按第五节完成状态筛选,汇报后再授权下一阶段。不要同时设置覆盖整个 2.0 的活跃 Goal,否则持续推进的目标会与阶段暂停点冲突。

Goals 作为选修另做:在独立副本完成一次范围明确的小目标,例如只修一个已经复现的测试失败,并禁止进入下一功能。目标要包含结果、独立验证和约束。已设置目标后才用 /goal 查看、/goal pause 暂停、/goal resume 恢复;这些命令不是本章主线的必需步骤。

参考:官方 Goals 说明。

阶段一:完成状态筛选

现在开始第一个里程碑。输入:

执行 PLAN.md 的阶段一:为 list 增加 --status all|open|done。

要求:
- 默认行为与 1.0 保持一致;
- 非法状态值给出清楚提示和非零退出码;
- 测试覆盖 all、open、done、默认值和非法输入;
- 测试必须使用临时数据;
- 先运行相关测试,再运行完整测试;
- 验证通过后更新 STATUS.md,然后停下来汇报,不进入阶段二。

最终汇报请列出修改文件、运行过的命令、观察到的结果和仍然存在的风险。

Codex 停下后,不要只看“已完成”三个字。依次检查:

  1. /diff 中是否只有与筛选有关的修改;
  2. 是否真的运行了局部测试和完整测试;
  3. STATUS.md 是否写入了测试结果和下一阶段;
  4. 非法参数是否产生非零退出码。

最后一项可以亲自验证。在另一个终端使用临时数据文件;沿用已固定的全局 --data 参数;下列临时路径由你先创建,不依赖未定义的环境变量:

python3 taskflow.py --data "<临时文件绝对路径>" list --status invalid
echo $?

Windows PowerShell 对应执行:

py taskflow.py list --status invalid
$LASTEXITCODE

你应该看到可理解的错误提示,并得到非零退出码。如果命令只是打印错误但仍返回 0,自动化脚本会把失败误判成成功,这一阶段就还没有通过验收。

阶段二:统计功能先定规则,再写输出

继续输入:

执行 PLAN.md 的阶段二:新增 stats 命令。

输出总数、已完成数、未完成数和完成率。空任务列表的完成率显示为 0%。请把统计计算放在可直接测试的函数中,不要让测试依赖解析整段终端文本。

补齐正常数据和空数据测试,运行相关测试与完整测试。验证通过后更新 STATUS.md,并停下来汇报证据。

这里真正要学的不是如何算百分比,而是如何把“规则”变成可验证行为。完成后,用三组数据检查结果:

  • 空列表:总数 0,完成率 0%;
  • 全部完成:完成率 100%;
  • 完成一半:完成率 50%。

如果 Codex 为了测试方便,把统计逻辑抽成一个小函数,这是合理结构调整;如果它顺手重写了存储层或 CLI 框架,就已经超出阶段范围。长任务依靠小而清楚的 Diff 保持可审查,而不是靠一次性生成大量代码提高“完成感”。

阶段三:只实现已经确认的报告范围

本课 report 导出当前数据文件的全部任务快照,不按周筛选,因此统一称“任务报告”。若以后需要周报,先新增时间字段、时区、周起止和归属规则,再增加跨周测试。

报告功能最容易膨胀。模板、主题、配置文件、HTML 导出都很有诱惑力,但不属于本次 2.0。输入:

执行 PLAN.md 的阶段三:实现 report --output <path>。

报告采用已经确认的固定结构:标题、生成时间、统计摘要、未完成任务、已完成任务。

要求:
- 父目录不存在时给出清晰错误并返回非零退出码;
- 不增加模板系统;
- 测试核对文件被创建、关键标题存在、统计数字正确、任务分组正确;
- 使用临时目录,不向仓库留下测试报告;
- 更新 README 中的命令示例;
- 运行相关测试和完整测试,更新 STATUS.md 后停下来汇报。

完成后,除了看测试,还要实际打开一次产物。先准备一份临时数据,再让 report 写入临时目录。由于不同操作系统的临时路径和 TaskFlow 数据路径参数可能不同,可以直接让 Codex 给出适合当前项目的命令:

请根据当前 TaskFlow 的真实参数,给我一组不会读写 data/tasks.json 的手工冒烟命令:创建临时数据,加入一条已完成和一条未完成任务,生成 Markdown 报告,再打印报告内容。暂时不要执行。

检查命令没有指向真实数据后再执行。报告中应该同时出现:

  • 正确的总数、完成数和完成率;
  • 一条未完成任务;
  • 一条已完成任务;
  • 合法的 Markdown 标题。

“文件成功生成”只能证明写入发生了,不能证明内容正确。打开产物,是这一阶段不可省略的验证。

中断后怎样可靠恢复

如果今天做到一半需要离开,先让 Codex 更新状态:

准备暂停本次任务。请根据 Git 状态和实际验证结果更新 STATUS.md,写清已经完成、尚未完成、最近一次验证、下一步和已知阻塞。不要开始新阶段。

如果另做选修并有活跃 Goal,先暂停它;主线未设 Goal 则直接退出:

/goal pause

退出 Codex。下次回到同一个项目目录时,在终端执行:

codex resume

该命令会打开会话选择器。如果就是继续最近一次会话,可以执行:

codex resume --last

恢复后,不要直接说“继续”。先让 Codex 重新核对事实:

先不要修改文件。请读取 PLAN.md、STATUS.md、AGENTS.md,并检查 git status、git diff 和最近可运行的测试。

请列出:
1. 已完成且有证据的阶段;
2. 声称完成但仍缺少证据的项目;
3. 当前未提交改动;
4. 下一步最小动作;
5. 进入下一阶段前需要确认的风险。

确认状态无误后,主线直接授权下一阶段;只有选修中已暂停的 Goal 才使用:

/goal resume

这里的顺序很重要:会话记忆帮助你找回上下文,Git、项目文件和测试帮助你恢复事实。两者发生冲突时,以当前仓库和重新运行的验证为准。

上下文变长时,压缩还是分叉

长任务经过多轮讨论后,可以先输入:

/status

它用于查看当前会话和上下文状态。如果目标没变,只是聊天记录太长,可以输入:

/compact

压缩后立刻做一次核对:

请根据压缩后的上下文以及 PLAN.md、STATUS.md,列出当前 Goal、已完成阶段、未完成阶段、关键约束和最近一次验证结果。只报告,不修改。

如果摘要漏掉重要决定,把决定补到项目文件里。真正重要的信息不应只依赖上下文压缩是否完整。

如果目标已经发生分歧,就不要继续往同一个会话里塞内容。例如,你想比较“固定报告格式”和“可配置模板系统”,可以退出当前交互界面,在终端执行:

codex fork --last

它会基于最近会话的历史创建一个新会话。新分支适合调查另一条真正不同的方向;原会话继续负责已经确认的 2.0 范围。注意,分叉的是会话,不会自动隔离同一工作目录里的文件改动。若两个方向都要实际修改代码,应使用不同 Git 分支或 worktree,避免互相覆盖。

一个简单判断是:

  • 目标相同、上下文太长:用 /compact;
  • 目标不同、但需要继承历史:用 codex fork;
  • 只是临时问一个问题:在当前 Codex CLI 中使用 /side;它会临时分出一条对话,不会打断主聊天。

/side 和 codex fork 的区别在于:Side Chat 适合快速核对一个问题,结束后回到原聊天;Fork 会创建一个拥有新 ID 的持久分支,适合继续探索另一套方案。/side 不能在另一个 Side Chat 或 Review 模式里使用。若本机没有该命令,先输入 / 核对当前命令面板,再用 codex --version 与 codex update 检查版本。

总体验收:不要在最后一轮继续加功能

三个功能完成后,最后一个阶段只做整体验收和必要修复:

执行 PLAN.md 的总体验收阶段,不增加新功能。

请完成:
1. 运行完整测试;
2. 用临时数据实际执行 add、list --status all|open|done、stats 和 report;
3. 打开生成的 Markdown 报告,核对统计与任务分组;
4. 用一份 1.0 格式的 JSON 数据验证向后兼容;
5. 对照 README 逐条核查示例;
6. 审查完整 Git Diff,只修复阻塞 2.0 发布的问题;
7. 更新 STATUS.md,汇总修改文件、验证命令、实际结果和已知限制。

只有证据满足当前 Goal 时,才可以把任务标记为完成。若有失败,先报告失败证据和最小修复方案。

你最终至少应该拿到下面这些证据:

验收项 合格证据
状态筛选 三种筛选结果正确,默认行为兼容,非法值返回非零退出码
统计 空、全完成、部分完成三组数据结果正确
报告 临时目录中生成文件,内容和任务分组与输入一致
数据兼容 1.0 JSON 可以直接读取,不要求手工迁移
回归 完整测试通过,并记录实际命令和结果
文档 README 示例与当前参数一致,可以照着执行
改动范围 Git Diff 中没有真实任务数据、缓存、临时报告或无关重构

验收通过后,先在终端检查:

git status --short
git diff --check
git diff --stat

git diff --check 没有输出,通常表示没有空白错误;它不等于功能测试通过。确认文件范围无误后,再按项目习惯提交。不要因为教程给了示例就机械执行 git add .,更稳妥的做法是明确添加本次确认过的文件。

把六种工具放回正确位置

工具 它解决的问题 不应该替代什么
/plan 实现前拆路线、找歧义和风险 不能证明功能已经完成
/goal 跨多轮保留可验证的完成条件 不能替代具体实施计划
PLAN.md 把阶段和验收方式放进项目 不能替代当前进度记录
STATUS.md 保存已完成、下一步和最近证据 不能只靠 Codex 自述更新
codex resume 回到已有会话继续工作 不能替代恢复后的事实核查
/compact / /side / codex fork 分别处理“同目标但过长”“临时岔开一问”和“方向已分开” 不能替代 Git 分支或 worktree 的文件隔离

如果只记住一个原则,可以记住这句:聊天负责协作,仓库保存状态,验证决定是否完成。

本篇小结

管理长任务,不是把一个巨大提示词扔给 Codex 后等待更久,而是把工作拆成可以单独验收的阶段,并让目标、状态和证据都能在中断后找回来。

在这次 TaskFlow 2.0 升级里,Plan 模式让我们先确认路径,Goal 固定最终完成条件,PLAN.md 和 STATUS.md 把状态放进仓库,codex resume 负责恢复会话,/compact、/side 和 codex fork 则分别处理上下文过长、临时问题与方向分歧。每完成一段工作,我们都用测试、实际产物和 Git Diff 重新建立事实。

下一篇,我们会把视野从一个项目扩展到 Codex 的能力扩展体系,分清 Skills、Plugins、MCP 和 Apps 各自解决什么问题,并为 TaskFlow 做一个真正可复用的发布检查能力。


12 技能、插件、MCP与应用

预计学习时间:55—70 分钟
本篇目标:分清 Codex 扩展体系的几个层次,为 TaskFlow 创建并验证一个项目 Skill,再连接一个只读 MCP 服务完成最小练习。

TaskFlow 2.0 已经完成。发布前,我们每次都要做同一组事情:看 Git 状态、跑完整测试、核对 README、检查是否混入运行数据,最后整理一份发布检查报告。

当然可以把这些要求每次复制给 Codex,但更合适的做法是把它保存成 Skill。Skill 负责告诉 Codex“这套工作应该怎样重复执行”;如果以后还想把它连同外部工具一起分发给其他人,再把它包装成 Plugin;如果流程需要访问仓库之外的实时数据或执行外部动作,就通过 MCP 提供工具。

这一篇不做扩展机制的百科全书,只完成两个能亲手验证的练习:

  1. 为 TaskFlow 创建一个仓库级发布检查 Skill;
  2. 给 Codex CLI 添加 OpenAI 官方的只读文档 MCP,并验证它确实能检索资料。

先把几个层次摆正

下面这张表不是按“高级程度”排序,而是按它们解决的问题区分:

机制 解决的问题 TaskFlow 中的例子
当前提示词 只约束这一次任务 “检查今天这次 Diff,不要改代码”
AGENTS.md 规定这个项目长期遵守的工作方式 测试必须用临时目录,不碰真实任务数据
Skill 保存一套可以反复触发的工作流程 每次发布前执行同一套验收并生成报告
MCP server 向 Codex 暴露外部数据和可调用工具 查询文档、读取工单、操作获准的第三方服务
Plugin 把 Skills、MCP 连接等能力包装成可发现、可安装的产品 给团队分发统一的发布检查与仓库工具
App / connector 用户实际连接和使用的外部应用或交互能力 Gmail、Google Drive、Slack,或 MCP 返回的可视化界面

这里有两个特别容易混淆的地方。

第一,Skill 不是一个外部工具。它本质上是一组可复用的说明、参考资料、模板和可选脚本。Codex 先根据 Skill 的名称与描述判断是否适用,需要时再读取完整的 SKILL.md。官方说明见 Build skills。

第二,Plugin 是安装和分发单位,不是和 Skill、MCP 并列的另一种执行协议。一个 Plugin 可以只有 Skills,也可以包含 MCP server,或者把二者组合起来。当前官方架构可参考 Plugin architecture。

“App”通常指你实际连接和使用的外部服务,也常被称为 connector。当前 Codex CLI 中,/plugins 用来发现和管理插件,/apps 用来浏览当前可用的 Apps,并把 $app-slug 插入提示词,/mcp 则用来查看已经接入的 MCP server 与工具。三者是不同入口,不要把“安装插件”“选择 App”和“检查底层工具连接”混成一件事。

一个实用判断顺序是:

  1. 这条要求只用一次吗?直接写进提示词。
  2. 它是当前仓库每次都要遵守的规则吗?写进 AGENTS.md。
  3. 它是一套会被反复执行、有明确输入和输出的流程吗?做成 Skill。
  4. 它需要实时访问外部系统吗?接 MCP。
  5. 它要让别人方便安装,或把流程与连接一起交付吗?打包成 Plugin。

为 TaskFlow 选择最小够用的方案

这次“发布前检查”只需要读取仓库、运行现有命令并生成本地 Markdown 报告,不需要访问外部账户,也不需要自建服务。因此,仓库级 Skill 就够了。

我们要创建的 Skill 叫 taskflow-release,它应当做到:

  1. 阅读 AGENTS.md、README.md 和当前 Git 状态;
  2. 检查本次 Diff 的范围;
  3. 运行完整测试;
  4. 核对 README 中的 CLI 用法;
  5. 检查运行数据、缓存、密钥和个人绝对路径;
  6. 生成 RELEASE_CHECK.md,把结果分成“通过、阻塞、提醒”;
  7. 记录真正执行过的命令和观察到的证据。

它明确不做这些事:

  • 不执行 git commit、git tag 或 git push;
  • 不发布版本;
  • 不修改业务代码来“顺手修复”检查结果;
  • 不删除文件;
  • 不读取项目目录之外的内容。

边界写得越清楚,Skill 就越适合反复调用。否则“发布检查”很容易在某次运行中悄悄变成“修改、提交并发布”。

确认 Skill 应该放在哪里

在 TaskFlow 根目录启动 Codex。仓库级 Skill 的路径是:

.agents/skills/taskflow-release/SKILL.md

Codex 会从当前工作目录一路向仓库根目录查找 .agents/skills。因此,把 Skill 放在仓库根目录,团队成员克隆项目后也能获得同一套工作流;把它放进个人目录,则更适合跨项目使用的个人习惯。

开始前,先在终端确认你位于项目根目录:

git rev-parse --show-toplevel
git status --short

Windows PowerShell 中这两条 Git 命令相同。

第一条应该输出 TaskFlow 仓库根路径。第二条可以出现上一课创建的 PLAN.md、STATUS.md 或 TaskFlow 2.0 改动,但不应该出现来源不明的文件。若工作区状态与你预期不一致,先弄清它们属于谁,再创建 Skill。

用内置 Skill Creator 创建初稿

在 TaskFlow 根目录运行 codex,然后输入:

$skill-creator

如果界面允许在同一条消息里带上要求,可以直接输入:

$skill-creator 为当前 TaskFlow 仓库创建 taskflow-release Skill。

保存到 .agents/skills/taskflow-release/SKILL.md。

触发场景:用户要求对 TaskFlow 做发布检查、release check、发布前验收或发布就绪评估。

流程:
1. 阅读 AGENTS.md、README.md、PLAN.md、STATUS.md;
2. 检查 git status 和未提交 Diff;
3. 运行项目规定的完整测试;
4. 核对 README 的命令、参数与当前 CLI;
5. 检查密钥、个人绝对路径、真实运行数据和缓存;
6. 生成 RELEASE_CHECK.md,包含“通过、阻塞、提醒、验证证据”四部分;
7. 最终列出实际执行的命令、退出结果和未能验证的项目。

边界:不修改业务代码,不删除文件,不提交、不打标签、不推送、不发布,不读取工作区之外的内容。发现问题只记录并给出最小建议。

请保持 instruction-only,不添加脚本。先展示准备创建的结构和关键内容,再写入文件。

这里选择 instruction-only,是因为现有 Git 和 Python 命令已经足以完成检查。只有当某项计算必须保证完全确定、或者需要复用一段稳定程序时,才值得增加 scripts/。不要为了让 Skill 看起来“更完整”而塞入没有必要的脚本。

Skill Creator 可能追问触发条件、输出格式或存放范围。按照上面的边界回答即可。写入完成后,你应该看到类似结构:

.agents/
└── skills/
    └── taskflow-release/
        └── SKILL.md

若当前版本没有 $skill-creator,也可以让 Codex 按同一路径手动创建。最小 SKILL.md 必须包含 frontmatter:

---
name: taskflow-release
description: Run a TaskFlow release check and create RELEASE_CHECK.md when the user asks for release readiness, release check, or 发布前验收. Do not publish or modify business code.
---

# TaskFlow release check

Follow the repository instructions, inspect the current changes, run verification, and create an evidence-based release report.

name 是调用名称;description 同时负责告诉 Codex“什么时候应该考虑使用它”。描述不能只写“TaskFlow 工具”,而要包含触发场景和重要边界。

先审查 Skill 本身,再运行它

Skill 是会影响 Agent 行为的指令文件。即使它由内置创建器生成,也应该像审查代码一样打开查看。

在 Codex 中输入:

请只审查 .agents/skills/taskflow-release/SKILL.md,不要执行这个 Skill,也不要修改文件。

检查:
1. name 与 description 是否能准确触发;
2. 输入、步骤和输出是否明确;
3. 是否引用了真实存在的项目文件与测试命令;
4. 是否明确禁止提交、推送、发布和业务代码修改;
5. 是否有“全面检查”“确保高质量”这类无法验收的空话。

请给出逐项结论和证据位置。

也可以在另一个终端查看实际内容:

git diff -- .agents/skills/taskflow-release/SKILL.md

如果这是一个全新未跟踪文件,git diff 默认可能不显示内容。此时先用下面的命令确认文件存在,再直接打开它:

git status --short

macOS、Linux 或 WSL 可用:

sed -n '1,240p' .agents/skills/taskflow-release/SKILL.md

Windows PowerShell 可用:

Get-Content .agents\skills\taskflow-release\SKILL.md

合格的 Skill 应该让你能回答三个问题:什么请求会触发、按什么顺序执行、什么证据才算完成。

显式调用一次,验证完整闭环

Codex 通常会自动发现 Skill 的变化;如果 /skills 中没有出现,退出后从 TaskFlow 根目录重新启动 Codex。

先输入:

/skills

在列表中找到 taskflow-release,确认路径指向当前仓库的 .agents/skills/taskflow-release/SKILL.md。然后显式调用:

$taskflow-release 请对当前 TaskFlow 2.0 做一次发布检查。只生成 RELEASE_CHECK.md,不修改业务代码,不提交、不打标签、不推送、不发布。

执行过程中,留意 Codex 是否:

  • 先读取项目指导和当前 Diff;
  • 使用 TaskFlow 真实的测试命令;
  • 对高风险命令仍遵守现有审批与沙箱设置;
  • 只生成报告,没有为了消除阻塞而修改业务代码;
  • 把无法验证的事项标成未知,而不是默认通过。

完成后不要只接受“发布检查通过”的总结。打开报告,并在终端检查文件变化:

git status --short
git diff --stat

再打开 RELEASE_CHECK.md。macOS、Linux 或 WSL:

sed -n '1,260p' RELEASE_CHECK.md

Windows PowerShell:

Get-Content .\RELEASE_CHECK.md

报告至少应包含:

  • 检查时的 Git 状态与修改范围;
  • 完整测试命令和观察到的结果;
  • README 与当前命令的一致性结论;
  • 对敏感信息、真实数据、缓存和本机路径的检查;
  • 明确的阻塞项与提醒项;
  • 没有自动提交或发布的说明。

最后独立验证 Skill 有没有越界:

git status --short --untracked-files=all
git diff --name-only
git diff --cached --name-only

正常情况下,新出现的文件应该主要是 Skill 本身和 RELEASE_CHECK.md。如果业务代码也发生变化,先查看 Diff;除非你明确授权,否则这次运行就没有遵守边界。

再测一次“该触发”和“不该触发”

显式调用成功,只能证明 Skill 可以运行,还不能证明它会在合适的时候运行。

开一个新会话,先用不带 $ 的自然语言请求:

请对 TaskFlow 做一次发布前验收,生成检查报告,但不要发布或修改业务代码。

Codex 应该能根据 description 匹配到这个 Skill。然后再测试一个不应触发的请求:

请解释 stats 命令的完成率怎样计算。只解释,不修改文件。

第二个请求不需要完整发布检查。如果 Codex 仍加载并执行了 taskflow-release,通常说明 description 写得过宽;如果第一个请求没有触发,则可能是描述缺少“发布检查、发布前验收、release readiness”等明确触发词。

修改 Skill 后不必不断增加规则。优先修复三类问题:

  • 触发错了:改 description;
  • 执行顺序或边界错了:改正文指令;
  • 输出难以核对:改报告结构和完成证据。

Plugin 是把能力交付给别人

当前 taskflow-release 跟仓库一起使用,直接放在 .agents/skills 最简单。如果以后你有多个项目都需要同一套发布流程,或者还要把团队的 MCP 工具一起安装,就可以考虑打包成 Plugin。

当前 Codex CLI 可以在交互界面中输入:

/plugins

插件浏览器会显示可用市场、已安装状态和插件详情。也可以退出交互界面,在终端查看当前 CLI 支持的管理命令:

codex plugin --help
codex plugin list

本教程不要求你为了完成练习而安装任意第三方插件。你可以打开一个插件详情页,练习检查下面这些信息:

  1. 发布者和来源是谁;
  2. 它包含 Skills、MCP 工具、browser extension 还是 hooks;
  3. 是否需要登录外部服务;
  4. 请求读取和写入什么数据;
  5. 是否有比安装完整插件更小的实现方式。

如果决定安装,完成安装或连接后应新开一个会话,让新能力进入会话的工具和 Skill 列表。插件中的 MCP 工具仍受外部服务授权、Codex 沙箱和审批策略约束;“安装成功”不等于它拥有所有权限。当前产品说明见 Plugins。

用一个只读 MCP 理解“工具连接”

Skill 解决的是“怎样做”,MCP 解决的是“能调用什么”。为了避免一上来就授权邮箱或云盘,我们连接 OpenAI 官方的文档 MCP。它只能搜索和读取官方开发者文档,不会替你调用 OpenAI API。

先退出正在运行的 Codex。在系统终端执行:

codex mcp add openaiDeveloperDocs --url https://developers.openai.com/mcp

然后验证配置:

codex mcp list

列表中应该出现名为 openaiDeveloperDocs 的服务及其 URL。它的配置会写入 Codex 配置;Codex CLI、桌面端和 IDE 扩展在同一台 Codex host 上会共享这份 MCP 配置。官方示例见 Docs MCP。

重新进入 TaskFlow 目录并启动 Codex:

codex

输入:

/mcp

你应该能看到已经连接的服务器及可用工具。接着提交一个与项目相关、但不会修改文件的请求:

请使用 openaiDeveloperDocs MCP,查找 Codex 官方关于仓库级 Skills 加载位置的说明。

回答三个问题:
1. 仓库根目录的 Skill 放在哪里;
2. Codex 怎样决定是否加载完整 SKILL.md;
3. Skill 修改后没有出现时应该先做什么。

请附上官方文档链接。不要修改项目文件。

完成后检查两个层面:

  • 回答是否包含与你刚才实践一致的路径和触发机制;
  • 引用是否指向 OpenAI 官方文档,而不是模型凭记忆给出的泛泛结论。

这就是 MCP 的最小闭环:添加连接 → 列出服务 → 在新会话中看到工具 → 明确要求使用 → 检查返回证据。

如果 /mcp 中看不到它,按顺序检查:

  1. codex mcp list 是否真的列出该服务;
  2. 添加后是否重新启动了 Codex;
  3. 当前是否在同一台 Codex host 上;
  4. 网络是否能访问该 HTTPS 地址;
  5. codex mcp --help 和 codex --version 是否与教程命令一致。

这次 MCP 不需要 OAuth。连接其他服务时,可能还要执行 codex mcp login <server-name> 或在插件安装流程中完成授权。不要把令牌直接写进教程、提示词或 Git 仓库;需要令牌时,优先使用环境变量或官方授权流程。MCP 的配置方式和审批选项见 Model Context Protocol。

如果只是练习、后续不想保留这个连接,可以退出 Codex 后执行:

codex mcp remove openaiDeveloperDocs
codex mcp list

第二条命令中不再出现它,才说明清理完成。删除 MCP 配置不会删除我们刚才创建的项目 Skill,因为它们属于不同层次。

怎样理解 Apps 与连接权限

当你在插件目录里安装 Gmail、Google Drive、Slack 之类的能力时,用户感知上是在“连接一个 App”;在底层,它通常由插件提供可复用工作流,并通过 MCP 等机制暴露数据和动作。

在 Codex CLI 中输入:

/apps

选择一个可用 App 后,Codex 会把类似 $app-slug 的引用插入输入框,你可以接着说明要查询什么或执行什么动作。如果列表中没有目标服务,先用 /plugins 检查对应插件是否已安装并启用,再检查账号方案、地区和组织策略;不要因为 /mcp 能看到某个 server,就推断 App 一定会出现在列表里。

你不必为了使用而掌握全部实现细节,但必须分清三种授权:

授权层次 它控制什么 使用前要看什么
第三方账户授权 外部服务允许读取或写入哪些内容 OAuth 权限范围、账号、组织策略
Codex 工具审批 某次工具调用是否需要你确认 是只读查询还是写入、发送、删除
本机沙箱与文件权限 Codex host 可以访问哪些本地目录和命令 当前 sandbox、工作目录和额外授权

一个插件已经连接账号,不代表每个动作都应该自动放行。尤其是发送消息、修改云文档、创建工单和删除内容,要保留清楚的最终确认。把只读查询和有外部副作用的动作分开,是使用 Apps 和 MCP 时最重要的习惯。

最后用一张决策表收口

你的需求 优先选择 原因
这一次按指定格式检查 TaskFlow 提示词 没有复用价值
TaskFlow 每次测试都不能碰真实数据 AGENTS.md 属于项目长期规则
每次发布都执行同一套检查并生成报告 Skill 是可重复工作流
查询实时工单、文档或服务状态 MCP 需要外部数据或动作
把发布流程和团队工具交给多人安装 Plugin 需要打包、发现和分发
在 Gmail、Drive、Slack 等服务里工作 App connection 需要选择 App,并授权对应外部账户

如果只记住一句话,可以这样记:Skill 规定流程,MCP 提供工具,Plugin 负责交付;App 是你实际连接和使用的外部服务或交互体验。

本篇小结

这一篇,我们没有把所有扩展机制都做一遍,而是沿着 TaskFlow 的真实需要选择了最小方案:把发布检查做成仓库级 taskflow-release Skill,并通过显式调用、自然触发、反例和实际文件 Diff 验证它;随后连接一个只读 Docs MCP,观察外部工具怎样进入 Codex。

现在 TaskFlow 不仅有项目规则,还有一套可以重复执行的发布检查流程。下一篇,我们会调用这套 Skill 做发布前审查,并学习如何把相互独立的代码、测试和文档调查交给多个 Agent,同时避免它们争抢同一份文件。


13 多智能体协作升级项目

权限名称可能随版本和配置变化。本课按能力选择:调查用 read-only,实施用 workspace-write。若 /permissions 没有只读选项,退出后运行 codex --sandbox read-only --ask-for-approval on-request;实施前用 workspace-write 重新启动并明确提供计划,不凭 Read Only/Auto 等标签猜权限。

预计学习时间:50—65 分钟
本篇目标:把 TaskFlow 的发布前审查拆给三个只读子 Agent,并由主 Agent 统一核验证据、决定修复和完成最终验收。

TaskFlow 2.0 已经具备筛选、统计和 Markdown 报告功能,我们还在上一篇创建了 taskflow-release Skill。现在要做发布前审查,需要同时回答三个问题:

  • 核心功能和数据处理有没有隐藏缺陷;
  • 测试是否遗漏了关键边界和跨平台行为;
  • README 是否仍然与真实 CLI 一致。

让一个 Agent 依次检查当然可以,但这三个方向以阅读和调查为主,彼此依赖很少,很适合并行。多 Agent 的价值不在于“多叫几个人显得更认真”,而在于把相互独立、会产生大量中间信息的工作移出主会话,再由主 Agent 收集精简结论。

这一篇采用一个稳妥的协作模式:

主 Agent 定义范围
    ├── 子 Agent A:代码与数据风险,只读
    ├── 子 Agent B:测试与跨平台,只读
    └── 子 Agent C:文档与 CLI 一致性,只读
                  ↓
主 Agent 去重、复现、判断
                  ↓
主 Agent 统一修改和验收

前半段允许并行,真正写代码时重新收口。这样既能获得并行调查的速度,又不会让几个 Agent 同时争抢 taskflow.py。

先判断这项工作是否值得并行

适合交给子 Agent 的任务通常有三个特征:

  1. 子问题之间基本独立;
  2. 每个子任务有清楚的输入、边界和交付格式;
  3. 主要产出是调查结论、证据或互不重叠的文件。

典型例子包括:

  • 分别梳理代码、测试和文档;
  • 分别调查几种互不相关的故障假设;
  • 一个 Agent 复现问题,另一个查影响范围;
  • 分别阅读多份材料,最后由主 Agent 汇总。

下面这些情况不适合为了并行而并行:

  • 只需要改一两行的小任务;
  • 后一个步骤必须等待前一个步骤的输出;
  • 任务范围还没有讲清楚;
  • 几个 Agent 必须同时修改同一个核心文件;
  • 协调和去重的成本已经超过工作本身。

子 Agent 会独立使用模型、上下文和工具,因此通常比单 Agent 消耗更多额度。官方也建议先从代码探索、测试、问题分类和总结这类“读多写少”的工作开始,谨慎对待并行写入。参见 Subagents。

确认起点,避免把旧问题算到本次审查里

进入 TaskFlow 仓库根目录。macOS、Linux 或 WSL 执行:

git status --short
python3 -m unittest discover -s tests -v

Windows PowerShell 执行:

git status --short
py -m unittest discover -s tests -v

同时确认上一篇创建的 Skill 存在:

test -f .agents/skills/taskflow-release/SKILL.md && echo "skill found"

PowerShell 对应命令:

Test-Path .agents\skills\taskflow-release\SKILL.md

预期结果是:

  • 你知道当前有哪些未提交改动;
  • 完整测试在审查前处于已知状态;
  • Skill 文件存在,稍后可以用于最终验收。

如果你跳过了上一篇,没有这个 Skill,也可以继续完成多 Agent 练习。最终验收时把 $taskflow-release 换成文中提供的普通提示词即可。

测试基线有失败时,先记录失败名称和输出。不要让三个子 Agent 都把同一个已知失败当成新发现。

调查阶段先切到只读权限

在 TaskFlow 根目录启动 Codex:

codex

进入交互界面后输入:

/permissions

选择只读模式,然后输入:

/status

检查输出中的工作目录和权限状态。你要确认 Codex 位于 TaskFlow 仓库,并且当前回合不应写文件。

子 Agent 会继承父回合的沙箱和审批策略。先把主会话设为只读,比在三个子任务里分别写一句“不要修改”更可靠;提示词边界仍然要保留,用来说明任务意图。当前官方权限说明和继承行为见 Subagents。

如果你的版本里没有 /permissions,退出 Codex,在终端以只读沙箱重新启动:

codex --sandbox read-only

由主 Agent 先画出共同边界

不要一进入会话就立刻派出三个子 Agent。先让主 Agent 建立共同事实:

我要对 TaskFlow 2.0 做发布前审查。现在先不要创建子 Agent,也不要修改文件。

请读取 AGENTS.md、README.md、PLAN.md、STATUS.md、RELEASE_CHECK.md(如果存在),并检查当前 Git 状态与项目结构。

请输出:
1. 本次审查范围;
2. 已知测试基线;
3. 核心命令和数据文件;
4. 三个适合独立调查的方向;
5. 所有子 Agent 必须遵守的只读边界和统一报告格式。

共同目标:只寻找会影响正确性、数据安全、跨平台使用或文档可信度的问题,忽略纯粹的个人风格偏好。

理想结果应该把审查范围限制在 TaskFlow 2.0 的真实能力上,而不是泛泛地说“检查整个项目质量”。如果它提出重做架构、加入依赖扫描、部署流水线等新目标,先删掉这些超出范围的内容。

一次创建三个边界互不重叠的子 Agent

确认共同边界后,提交下面的任务:

请创建三个子 Agent 并行调查。三个子 Agent 全部只读,不修改文件、不创建报告、不执行安装、提交、推送或网络操作。

子 Agent A:代码与数据风险
- 检查 add、done、import-csv、list --status、stats、report;
- 关注损坏 JSON、部分写入、重复 ID、空数据、非法参数和报告路径错误;
- 每个发现给出文件与行号、触发条件、实际行为、预期行为、严重程度;
- 最多返回 5 个高价值发现。

子 Agent B:测试与跨平台
- 检查测试是否覆盖正常、错误、旧数据兼容和退出码;
- 检查 macOS、Linux、Windows 的路径、Python 命令和编码差异;
- 找出“测试通过但真实 CLI 仍可能失败”的缺口;
- 每个发现给出缺少的验证方式,最多 5 个。

子 Agent C:文档与 CLI 一致性
- 逐项核对 README 中的命令、参数、默认值、错误行为和输出示例;
- 对照当前实现确认示例是否能在干净环境中运行;
- 只报告有文件或命令证据的不一致,最多 5 个。

统一输出字段:
- 标题;
- 状态:已证实 / 需要主 Agent 复现 / 非阻塞建议;
- 证据位置;
- 复现或核对步骤;
- 影响;
- 建议的最小验证。

请并行执行,等待三个子 Agent 都结束后再汇总。主 Agent 此时只收集结果,不修改文件,也不要把“需要验证”自动升级为缺陷。

这个提示词做了四件重要的事:

  • 按不同证据面拆任务,减少重复;
  • 明确只读,避免写入冲突;
  • 限制每个 Agent 的输出数量,防止低价值问题淹没主线;
  • 统一报告字段,便于主 Agent 去重和比较。

当前 Codex 通常会在你明确要求后创建子 Agent。它们会各自在独立的 agent thread 中工作,主 Agent 最后收集结果。不是所有模型和配置都会主动帮你拆任务,因此在教学练习中直接写“创建三个子 Agent”最可靠。

用 /agent 观察,而不是反复追问进度

子 Agent 运行时,在 Codex CLI 中输入:

/agent

也可以使用:

/subagents

界面会显示正在运行和已经完成的 agent thread。选择某个线程后,可以查看它正在调查什么以及最终返回了什么;回到主线程后,主 Agent 仍负责总汇报。当前命令说明见 Developer commands。

观察时重点看三件事:

  1. 三个线程是否拿到了不同任务;
  2. 它们是否仍处于只读范围;
  3. 是否有线程卡在权限请求或错误命令上。

在 CLI 中,即使你正在查看主线程,后台子 Agent 的审批请求也可能弹出。审批界面会标出来源线程;先看清是哪一个任务和哪条命令,再决定是否允许。只读审查阶段如果出现写文件、安装依赖或访问无关目录的请求,通常应该拒绝并让该 Agent 改用只读证据。

不要每隔几十秒向主 Agent 发送“好了吗”。主 Agent 会等待请求中的三个结果;频繁插入新要求反而容易改变边界。

子 Agent 的结论不能直接变成修复清单

三个线程结束后,先让主 Agent 做一次证据整理:

现在只汇总,不修改文件。

请把三个子 Agent 的结果合并成候选问题表:
1. 去掉重复项;
2. 保留每项原始证据位置;
3. 区分“已证实缺陷、需要主 Agent 复现、测试缺口、文档不一致、非阻塞建议”;
4. 标出彼此矛盾的结论;
5. 给出主 Agent 接下来需要亲自执行的最小验证。

不要根据出现次数投票,也不要因为多个 Agent 说法一致就跳过验证。

多个 Agent 的一致意见仍然可能来自同一个错误假设。最终分类必须回到代码、需求、测试和实际命令。

一项可以进入修复阶段的问题,至少要包含:

  • 具体文件与位置;
  • 可重复的触发条件;
  • 实际结果;
  • 有依据的预期结果;
  • 对用户或数据的影响;
  • 修复后可以运行的验证。

“这里可以更优雅”“建议重构”“也许在 Windows 上有问题”都还不是已证实缺陷。

由主 Agent 逐项复现

继续保持只读权限,让主 Agent 验证候选项:

请由主 Agent 亲自复现候选问题,仍然不要修改文件。

规则:
- 优先使用临时目录和临时数据;
- 不读取或覆盖真实 data/tasks.json;
- 每次只验证一个问题;
- 记录命令、退出码、关键输出和对应文件位置;
- 不能复现的项目降级为“未证实”,说明缺少什么条件;
- 最后给出按严重程度排序的已证实问题清单。

如果子 Agent 彼此冲突,例如一个认为 report 会自动创建父目录,另一个认为应该报错,主 Agent 要以既定需求和真实执行结果为准,而不是凭多数票。

复现完成后,在另一个终端执行:

git status --short

它应该与调查前一致。若多出源代码、报告或测试文件,说明所谓只读调查发生了写入。先检查这些改动,不要直接进入修复阶段。

如果三个方向都没有发现已证实缺陷,这是正常结果。不要为了让多 Agent 看起来“有产出”而要求它们继续找茬;保留审查范围和验证证据,直接进入最终验收即可。

修改阶段切回单一责任主体

只有当已证实问题确实需要修复时,才从只读模式切回你愿意使用的工作权限。输入:

/permissions

选择允许在工作区修改、但仍保留合适审批的模式,再用 /status 核对。接着提交:

请由主 Agent 修复刚才已经复现的发布阻塞问题。不要创建新的子 Agent,也不要让已有子 Agent 修改文件。

按严重程度逐项进行:
1. 先补充或确认能够失败的复现测试;
2. 做最小修改;
3. 运行相关测试;
4. 展示该项 Diff 与验证结果;
5. 一项通过后再进入下一项。

测试缺口和文档不一致可以一并处理;非阻塞重构建议记录到 RELEASE_CHECK.md,本轮不实施。全部完成后运行完整测试并停下来汇报,不提交、不打标签、不推送。

为什么不继续让多个 Agent 写代码?因为 TaskFlow 规模不大,许多命令共享同一个入口和存储逻辑。并行修改同一工作树会增加覆盖、冲突和重复修复的风险。

如果以后遇到多个真正独立的模块,并且确实需要并行写入,应先把它们放到不同 Git 分支或 worktree 中,再明确集成责任人。会话线程的隔离不等于文件系统隔离。关于工作树的使用边界,可以参考 Worktrees。

用上一课的 Skill 做最终验收

修改完成后,显式调用发布检查 Skill:

$taskflow-release 请对当前 TaskFlow 2.0 执行最终发布检查。请把本次多 Agent 审查中已证实的问题、主 Agent 的修复以及实际验证证据写入 RELEASE_CHECK.md。不要提交、不打标签、不推送、不发布。

如果你没有创建这个 Skill,使用普通提示词:

请完成 TaskFlow 2.0 最终发布检查:运行完整测试,核对 README 与 CLI,检查旧 JSON 兼容性,检查真实运行数据、缓存、密钥和个人路径是否进入 Diff,并生成 RELEASE_CHECK.md。报告每条已证实问题的修复与验证证据。不要提交或发布。

然后在终端独立检查:

git status --short
git diff --check
git diff --stat

macOS、Linux 或 WSL 再运行:

python3 -m unittest discover -s tests -v

Windows PowerShell:

py -m unittest discover -s tests -v

最后在 Codex 中输入:

/diff

把三个层次对起来:

层次 你要核对什么
子 Agent 调查 每个候选问题有没有位置、触发条件和证据
主 Agent 修复 Diff 是否只处理已证实问题,测试是否先失败后通过
最终发布检查 完整测试、README、数据兼容和安全检查是否都有实际结果

只有这三层能互相对应,才说明多 Agent 提升了审查效率,而不是只制造了三份更长的意见。

最常见的四个卡点

1. Codex 没有创建子 Agent

先确认你是直接要求“创建三个子 Agent 并行调查”,而不是含糊地说“可以并行看看”。然后检查:

/agent

若列表始终没有子线程,查看 codex --version 并更新 Codex。当前版本默认启用多 Agent;如果你修改过配置,还可以用 /debug-config 检查 agents.enabled 是否被关闭。

2. 三个 Agent 返回了几乎相同的内容

通常是任务边界按“角色名称”写了,却没有按证据面拆开。重新指定不同文件范围、问题类型和交付字段,不要简单复制同一任务给三个人。

3. 某个子 Agent 返回一段泛泛建议

要求它补充文件位置、触发条件、实际与预期结果、最小验证。仍然没有证据的内容只能保留为建议,不能进入修复清单。

4. 子 Agent 请求修改或额外权限

先看请求来自哪个线程。调查阶段默认拒绝写入,让它改为输出证据。若任务确实无法只读完成,也应回到主 Agent 重新划分阶段,而不是临时给某个后台线程扩大权限。

什么时候值得定义自定义 Agent

这次练习直接用临时子任务就够了。只有当同一种分工会反复出现,例如每次发布都需要固定的安全审查者、测试审查者和文档审查者,才值得把它们定义成项目级 custom agents。

当前 Codex 还提供 default、worker 和 explorer 等内置 Agent,并允许在 .codex/agents/ 中定义项目 Agent。自定义 Agent 可以指定更窄的职责、模型、推理强度和只读沙箱,但这会引入新的配置维护成本。先把一次任务拆对,再考虑固化角色;不要在第一次使用多 Agent 时同时引入一整套配置。

本篇小结

多 Agent 最适合并行展开相互独立的调查,而不是让多个 Agent 同时修改同一份代码。我们先在只读权限下,由三个子 Agent 分别检查代码、测试和文档;再由主 Agent 去重、复现和判断;真正的修改重新集中到主 Agent;最后用 taskflow-release Skill 和独立测试完成验收。

完成这一篇以后,你应该掌握的不只是“怎样创建三个 Agent”,而是一套可复用的协作纪律:并行调查、统一证据、单点写入、集中验收。

下一篇,我们会把已经稳定的检查任务搬出交互式会话,使用 codex exec 生成可供脚本和 CI 消费的结果。


14 用codex-exec实现自动化

预计学习时间:55—70 分钟
本篇目标:用 codex exec 为 TaskFlow 生成可验证的健康报告,理解普通输出、JSONL 事件、结构化结果、退出状态和自动化权限边界。

前面几篇一直在 Codex 的交互界面里工作。交互模式适合需求还在变化、需要随时追问和纠偏的任务;当一套检查已经稳定,并且你希望从脚本、定时任务或 CI 中反复运行时,才轮到 codex exec。

codex exec 是 Codex CLI 的非交互模式。它接收一次任务说明,执行后退出,不需要你守在 TUI 里继续对话。它适合做下面这些工作:

  • 重复执行仓库健康检查;
  • 把测试日志整理成固定格式;
  • 为后续脚本输出 JSON;
  • 在 CI 中生成供人审查的报告或补丁。

“非交互”不等于“可以放心给最高权限”。恰恰因为运行期间没人临时纠偏,工作目录、沙箱、输入、输出和完成条件更需要提前写清楚。

这一篇继续使用 TaskFlow。我们会先跑一个只读命令,再逐步把它升级成既给人看、也能被脚本消费的健康检查。

先确认自动化的运行环境

进入 TaskFlow 仓库根目录。先执行:

codex --version
codex login status
git rev-parse --show-toplevel
git status --short

这些命令在 PowerShell 中相同。

你需要确认:

  • Codex CLI 能正常运行;
  • 当前已经登录;
  • Git 输出的根目录正是 TaskFlow;
  • 你知道自动化开始前有哪些未提交改动。

codex exec 默认要求在 Git 仓库中运行。这个限制能减少在错误目录里执行任务的风险。--skip-git-repo-check 适合你完全了解的临时目录,不应该成为项目脚本里的默认选项。

再查看本机版本真正支持的参数:

codex exec --help

教程里的命令以当前稳定参数为准;如果帮助中没有某个选项,先更新 Codex,而不是直接照抄执行。

第一次运行:明确使用只读沙箱

在 TaskFlow 根目录执行:

codex exec --sandbox read-only "检查当前 TaskFlow 仓库,概括项目结构、完整测试命令和三个最值得关注的发布风险。只读取和分析,不修改文件。每个结论给出文件或命令证据。"

PowerShell 中可以使用同一条命令。

运行过程中,进度信息会写到 stderr,最终回复写到 stdout。因此终端里可能先看到工具调用和进度,最后才出现一段完整结论。这是正常现象。

命令结束后,先检查退出码。

macOS、Linux 或 WSL:

echo $?

Windows PowerShell:

$LASTEXITCODE

退出码为 0 说明这次 codex exec 运行完成,不代表 TaskFlow 一定健康。项目是否通过,仍要看测试证据和报告里的状态。这是自动化中非常重要的区别:进程成功结束与业务检查通过不是一回事。

再执行:

git status --short

结果应该与运行前一致。这个检查独立证明只读任务没有悄悄改动项目。

官方对输出流、沙箱和非交互模式的说明见 Non-interactive mode。

把最终回复单独保存,而不是重定向所有日志

先创建输出目录。

macOS、Linux 或 WSL:

mkdir -p reports

Windows PowerShell:

New-Item -ItemType Directory -Force reports | Out-Null

然后运行:

codex exec --sandbox read-only \
  --output-last-message reports/taskflow-health.md \
  "只读检查 TaskFlow 的测试、README 与实际 CLI 是否一致,并生成一份简洁的 Markdown 健康报告。列出实际证据、阻塞项和未能验证的内容。不要修改项目文件。"

PowerShell 可以写成一行:

codex exec --sandbox read-only --output-last-message reports\taskflow-health.md "只读检查 TaskFlow 的测试、README 与实际 CLI 是否一致,并生成一份简洁的 Markdown 健康报告。列出实际证据、阻塞项和未能验证的内容。不要修改项目文件。"

-o 是 --output-last-message 的短写。它只把 Agent 最终回复写入指定文件,进度仍然显示在终端。打开文件验证内容:

macOS、Linux 或 WSL:

sed -n '1,240p' reports/taskflow-health.md

Windows PowerShell:

Get-Content reports\taskflow-health.md

一份合格的报告至少要说明:

  • 它检查了哪些文件和命令;
  • 完整测试是否真的运行;
  • README 与当前参数是否一致;
  • 哪些结论有证据,哪些仍未验证;
  • 是否存在发布阻塞项。

如果文件只有“项目结构良好,可以发布”这一类结论,说明任务描述还不够可审计。

不希望保留会话记录时,可以加:

codex exec --ephemeral --sandbox read-only "只读总结当前项目"

--ephemeral 不保存这次运行的 session 文件,适合一次性检查;需要稍后 resume 的多阶段任务不要使用它。

不要让管道掩盖原始测试是否失败

你可以把命令输出通过标准输入交给 codex exec:

python3 -m unittest discover -s tests -v 2>&1 \
  | codex exec --sandbox read-only "分析输入的测试日志,归纳失败测试、共同根因和建议的排查顺序。只分析,不修改文件。"

但这条简短写法有一个陷阱:管道最后显示的退出码通常来自 codex exec,不一定是前面的测试命令。测试明明失败,日志分析却成功完成,整个管道仍可能得到 0。

更稳妥的做法是先保留测试日志和测试退出码,再交给 Codex 分析。

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v > reports/tests.log 2>&1
test_exit=$?
codex exec --sandbox read-only \
  "读取 reports/tests.log,归纳失败测试、共同根因和下一步。报告中必须注明原始测试退出码为 ${test_exit}。只分析,不修改文件。"
codex_exit=$?
echo "tests=$test_exit codex=$codex_exit"

PowerShell:

py -m unittest discover -s tests -v *> reports\tests.log
$testExit = $LASTEXITCODE
codex exec --sandbox read-only "读取 reports/tests.log,归纳失败测试、共同根因和下一步。报告中必须注明原始测试退出码为 $testExit。只分析,不修改文件。"
$codexExit = $LASTEXITCODE
"tests=$testExit codex=$codexExit"

最终你会得到两个独立状态:

  • tests:TaskFlow 测试本身是否通过;
  • codex:Codex 是否完成日志分析。

自动化脚本不应该把它们混成一个结果。日志中如果含有令牌、客户数据、本机敏感路径或生产内容,要先脱敏,再交给模型处理。

JSONL 记录的是过程事件,不是一份普通 JSON 报告

当下游系统需要观察运行过程时,可以使用 --json:

codex exec --json --sandbox read-only \
  "只读核对 README 中的命令是否与当前 TaskFlow CLI 一致。" \
  > reports/codex-events.jsonl

PowerShell:

codex exec --json --sandbox read-only "只读核对 README 中的命令是否与当前 TaskFlow CLI 一致。" > reports\codex-events.jsonl

此时 stdout 不再只是最终回复,而是 JSON Lines:每一行都是一个独立 JSON 对象。常见事件包括 thread 开始、turn 开始或结束、命令执行、文件变化、Agent 消息和错误。

先查看前几行。

macOS、Linux 或 WSL:

sed -n '1,12p' reports/codex-events.jsonl

Windows PowerShell:

Get-Content reports\codex-events.jsonl -TotalCount 12

你应该看到多行各自完整的 JSON,而不是一个最外层数组。不能直接把整份 .jsonl 当成普通 .json 交给只接受单个 JSON 文档的解析器。集成时应逐行读取,并对未知事件类型保持兼容。

如果你只关心最终结论,用 -o;如果你需要工具调用、进度、用量或失败事件,用 --json。二者可以同时使用。

用 JSON Schema 固定最终结果

人读 Markdown 很舒服,程序更需要稳定字段。现在为 TaskFlow 健康检查准备一个 Schema。

创建 schemas/taskflow-health.schema.json:

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": ["pass", "warn", "fail"]
    },
    "summary": { "type": "string" },
    "checks": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "status": {
            "type": "string",
            "enum": ["pass", "warn", "fail", "unknown"]
          },
          "evidence": { "type": "string" }
        },
        "required": ["name", "status", "evidence"],
        "additionalProperties": false
      }
    },
    "blockers": {
      "type": "array",
      "items": { "type": "string" }
    }
  },
  "required": ["status", "summary", "checks", "blockers"],
  "additionalProperties": false
}

如果你正在 Codex 交互界面中,可以让它按上面内容创建文件;创建后要亲自打开核对。Schema 只规定报告长什么样,并不决定什么证据算通过。

再创建 prompts/taskflow-health.md:

对当前 TaskFlow 仓库执行只读健康检查。

检查范围:
1. 运行 AGENTS.md 规定的完整测试;
2. 核对 README 的命令、参数和默认行为;
3. 检查当前 Git Diff 是否包含真实运行数据、缓存、明显密钥或个人绝对路径;
4. 检查 TaskFlow 1.0 JSON 数据是否仍可读取。

要求:
- 不修改任何项目文件;
- 只把实际执行或读取到的内容写为证据;
- 无法验证的检查标为 unknown;
- 任一发布阻塞项存在时,顶层 status 为 fail;
- 没有阻塞但存在提醒时为 warn;
- 全部有证据通过时才为 pass。

把提示词放进文件有两个好处:版本控制可以审查它,shell 也不必处理一大段引号和 $ 等特殊字符。

macOS、Linux 或 WSL 执行:

codex exec --json --sandbox read-only \
  --output-schema schemas/taskflow-health.schema.json \
  --output-last-message reports/taskflow-health.json \
  - < prompts/taskflow-health.md \
  > reports/taskflow-health.events.jsonl

Windows PowerShell:

Get-Content prompts\taskflow-health.md -Raw | codex exec --json --sandbox read-only --output-schema schemas\taskflow-health.schema.json --output-last-message reports\taskflow-health.json - > reports\taskflow-health.events.jsonl

这里同时产生两个文件:

  • reports/taskflow-health.json:符合 Schema 的最终结果;
  • reports/taskflow-health.events.jsonl:完整事件流。

--output-schema 约束最终回复的结构,不能证明里面的判断一定正确。打开并验证 JSON 语法:

macOS、Linux 或 WSL:

python3 -m json.tool reports/taskflow-health.json

Windows PowerShell:

py -m json.tool reports\taskflow-health.json

然后再对照完整测试、README 和 Git Diff 检查 evidence。只有结构正确而证据空泛,仍然不是一份可靠报告。

让脚本同时判断“运行成功”和“检查通过”

假设 codex exec 返回 0,但报告中的 status 是 fail,自动化仍应失败。可以用 Python 标准库读取最终结果。

macOS、Linux 或 WSL:

python3 -c 'import json,sys; d=json.load(open("reports/taskflow-health.json", encoding="utf-8")); print(d["status"], d["summary"]); sys.exit(1 if d["status"] == "fail" else 0)'
echo $?

Windows PowerShell:

py -c "import json,sys; d=json.load(open('reports/taskflow-health.json', encoding='utf-8')); print(d['status'], d['summary']); sys.exit(1 if d['status'] == 'fail' else 0)"
$LASTEXITCODE

这一步把“模型运行是否完成”和“项目健康检查是否通过”分开:

  1. 先检查 codex exec 的退出码;
  2. 再检查结构化报告里的业务状态;
  3. 两者任意一个失败,流水线都不应该宣告成功。

对于 warn 是否阻塞,可以按团队规则调整。入门阶段先让 fail 返回非零即可。

什么时候允许 codex exec 修改工作区

默认只读很适合报告、分类和审查。如果任务确实需要修改代码,必须显式开放:

codex exec --sandbox workspace-write \
  "根据 AGENTS.md 修复当前唯一一个已经复现的失败测试。只做最小修改,先运行局部测试,再运行完整测试,最后汇报 Diff。"

非交互任务无法像你坐在 TUI 前那样随时解释需求。第一次执行新的写入流程时,最好先在可丢弃分支或 worktree 中试跑,并保留人工 Diff 审查。

不要为了减少阻塞而默认使用:

--dangerously-bypass-approvals-and-sandbox

它会绕过审批和沙箱,只适合外层已经有严格隔离的专用环境。日常仓库脚本应使用最小沙箱;需要额外目录时,优先精确使用 --add-dir,不要直接扩大到整个系统。

恢复一次非交互任务

如果自动化确实分两个阶段,而且第一阶段保留了 session,可以在同一仓库中运行:

codex exec resume --last "继续上一次检查。先核对当前 Git 状态,只完成尚未执行的验证,然后输出最终结论。"

--last 默认选择当前工作目录最近的非交互会话。更稳妥的自动化可以从 JSONL 的 thread.started 事件中保存 thread ID,后续用明确 ID 恢复:

以下为参数模板,执行前先将尖括号占位符替换为实际值:

codex exec resume <SESSION_ID> "继续第二阶段验证"

不要用 --last 跨多个并发任务猜会话,也不要对 --ephemeral 运行安排后续恢复。

接入 CI 前先守住凭据边界

本地练习会复用你已经保存的 Codex 登录。到了 CI,凭据、仓库代码和自动执行会同时出现,风险更高。

一个稳妥的流水线通常是:

运行项目测试
    ↓
保留退出码并脱敏日志
    ↓
Codex 在只读仓库中生成结构化报告或补丁
    ↓
把结果保存为构建产物
    ↓
人工决定是否修复、合并或发布

GitHub Actions 场景优先使用官方 openai/codex-action。不要把 API Key 设置成整个 Job 都能读取的环境变量,因为仓库里的构建脚本、测试和依赖生命周期脚本也可能读到它。官方建议让密钥只在运行 Codex 的受控步骤中可用,并把生成补丁与拥有仓库写权限的步骤分开。完整示例和安全说明见 Non-interactive mode。

这套入门教程不要求你立即搭建 CI。先把本地只读流程跑通、把输出字段稳定下来、明确什么状态会阻塞,再搬进流水线,排错成本会低很多。

常见问题先看这五项

1. 提示“不是 Git 仓库”

先运行 git rev-parse --show-toplevel,确认工作目录。正式项目应回到仓库根目录;只有可丢弃的临时目录才考虑 --skip-git-repo-check。

2. 没有生成 -o 指定的文件

检查父目录是否已经创建、codex exec 退出码是否为零、Schema 文件是否有效。-o 不会替你建立缺失的复杂目录结构。

3. JSONL 无法被普通 JSON 解析器打开

这是预期行为。它是“一行一个 JSON 对象”,不是一个数组。逐行解析,或者只使用 -o 保存最终 JSON。

4. 命令完成了,但报告说 fail

两者不矛盾。退出码说明 Agent 运行状态,报告字段说明 TaskFlow 健康状态。脚本要同时判断。

5. 非交互任务卡在权限或外部工具上

减少任务范围,显式设置沙箱,移除不必要的网络或 MCP 依赖。无人值守任务如果需要新的人工批准,应该失败并报告,而不是偷偷放宽权限。

本篇小结

codex exec 的价值不是把交互式提示词原样塞进脚本,而是把一套已经验证的流程变成输入、权限、输出和判定规则都明确的命令。

我们为 TaskFlow 完成了一个只读健康检查:普通模式给人看,-o 保存最终回复,--json 记录 JSONL 事件,--output-schema 固定机器可读结果,再由独立脚本同时判断 Codex 退出码和报告状态。整个过程中,Git 状态、真实测试和 Diff 仍然是最终证据。

到这里,TaskFlow 主线已经覆盖了从规划、开发、调试到扩展与自动化的完整流程。接下来的三篇将进入综合实战:先接手陌生仓库修复缺陷,再完成跨文件功能,最后做代码审查、重构和发布准备。


15 实战一-接手陌生项目并修复缺陷

本课按能力区分调查 read-only 与实施 workspace-write。若 /permissions 未显示只读,退出后用 codex --sandbox read-only --ask-for-approval on-request 启动;写入前明确切换 workspace-write 并提供计划。以实际权限摘要为准。

预计学习时间:60—75 分钟
本篇目标:在不知道答案的新会话中,用 Codex 建立项目地图、复现退款计算缺陷、实施最小修复,并用测试、真实命令和 Git Diff 完成交付验收。

前面的练习都发生在熟悉的 TaskFlow 里。真实维护任务往往只有一句话:“退款金额算错了,帮忙修一下。”你不知道入口在哪,也不知道现有测试是否可靠。

这一篇会临时创建一个独立仓库 legacy-expenses。我们先让一个会话搭好带缺陷的练习环境,再关闭它;随后开启全新会话,把仓库当成第一次见到的项目来处理。这样练到的不是“让 Codex 根据自己刚写的代码回答”,而是接手陌生代码时真正需要的调查顺序。

最终验收标准很明确:

  • 修改前,一笔 100 元支出和一笔 20 元退款会错误得到 120.00;
  • 修改后,同一输入得到 80.00;
  • 与退款有关的失败测试由红转绿,完整测试全部通过;
  • Diff 只包含必要逻辑、回归测试和确有需要的说明更新。

创建一份可重复的陌生仓库

这个练习会产生故意失败的测试,请不要在 TaskFlow 仓库里执行。先建立单独目录。

macOS、Linux 或 WSL:

mkdir -p ~/codex-course/legacy-expenses
cd ~/codex-course/legacy-expenses
git init
codex --sandbox workspace-write --ask-for-approval on-request

Windows PowerShell:

New-Item -ItemType Directory -Force "$HOME\codex-course\legacy-expenses" | Out-Null
Set-Location "$HOME\codex-course\legacy-expenses"
git init
codex --sandbox workspace-write --ask-for-approval on-request

在 Codex 中提交下面的任务:

请创建一个名为 Legacy Expenses 的最小 Python 3.11 命令行练习项目,用于汇总 CSV 报销记录。

请严格使用下面的结构:
- legacy_expenses/__init__.py
- legacy_expenses/core.py
- legacy_expenses/cli.py
- tests/test_core.py
- tests/test_cli.py
- samples/mixed.csv
- README.md
- AGENTS.md
- .gitignore

业务约定:
- CSV 列固定为 description,amount,type;
- type 只能是 expense 或 refund;
- expense 增加总额,refund 应减少总额;
- samples/mixed.csv 只放一笔 100 元 expense 和一笔 20 元 refund;
- 正确结果应为 80.00,CLI 输出格式固定为 Total: 80.00。

练习要求:
- 只使用 Python 标准库;
- 故意在 core.py 留下一个缺陷:refund 被当成正数累加;
- 测试名 test_refund_reduces_total 必须暴露这个缺陷;
- 除这一个测试外,其余测试必须通过;
- README 只描述正确规则和运行方法,不提示缺陷在哪一行;
- AGENTS.md 写明完整测试命令、只做最小修改、不得增加第三方依赖;
- .gitignore 忽略 __pycache__、*.pyc 和常见虚拟环境目录;
- 不要修复故意保留的缺陷。

创建后请运行完整测试和样例命令。最后列出文件,并证明当前恰好只有 test_refund_reduces_total 失败,样例输出为 Total: 120.00。

这里把目录、失败测试名称和 CLI 输出都固定下来,是为了让后面的调查步骤可以复现。等 Codex 完成后,不要只看它的总结,自己验证一次。

macOS、Linux 或 WSL:

git ls-files --others --exclude-standard
python3 -m unittest discover -s tests -v
python3 -m legacy_expenses.cli samples/mixed.csv

Windows PowerShell:

git ls-files --others --exclude-standard
py -m unittest discover -s tests -v
py -m legacy_expenses.cli samples\mixed.csv

此时应该看到:

  • 项目文件都还是未跟踪文件;
  • 完整测试只有 test_refund_reduces_total 失败;
  • CLI 打印 Total: 120.00;
  • 测试进程返回非零退出码,这是故意留下的基线状态。

如果测试全部通过,说明缺陷没有被保留下来;如果有多个测试失败,说明练习环境还不稳定。先让当前会话修正“练习仓库本身”,直到满足上面四项,再继续。

建立基线提交:

git add .
git commit -m "add legacy expenses exercise"
git status --short
git switch -c fix/refund-total

git status --short 应该没有输出。若 Git 提示没有配置用户名或邮箱,按照提示设置你自己的 Git 身份,再重新提交;不要在教程或公开仓库中照抄别人的邮箱。

最后在 Codex 中输入 /exit。这个会话参与了项目创建,已经知道缺陷位置,不适合继续扮演接手者。

以只读方式建立项目地图

确认终端仍位于 legacy-expenses 根目录,然后开启一个新会话:

codex --sandbox read-only --ask-for-approval on-request

Codex CLI 会在开始工作前读取适用范围内的 AGENTS.md。但“自动读取”不代表你可以跳过核对:陌生仓库里的说明也可能过期。先提交调查任务:

我刚接手这个仓库。先只读调查,不要修改文件,也不要提出修复补丁。

请给我一张简洁的项目地图:
1. 项目解决什么问题;
2. AGENTS.md 规定了哪些约束和验证命令;
3. 程序入口、CSV 解析、金额汇总和输出分别在哪;
4. 一条记录从输入到最终金额经过哪些函数;
5. 哪些测试覆盖退款规则;
6. 当前分支和 Git 状态;
7. 对“退款让总额变大”这个报告,目前已知什么、还缺什么证据。

每项结论都引用文件路径、函数名或实际命令结果。信息不足时明确写“尚未验证”。

一份合格的项目地图应把“入口—解析—汇总—输出—测试”连成一条短路径,而不是逐文件复述代码。你可以在另一个终端做两项交叉检查:

git status --short
git ls-files

前一条应为空,后一条应包含准备阶段约定的文件。还可以在 Codex 中输入 /status,确认当前目录正确、权限仍是只读。若 Codex 在调查阶段尝试修改文件,先停止任务并用 /permissions 选择 Read Only,不要用提示词代替权限边界。

官方文档说明,Codex 会从项目根目录到当前目录逐层加载适用的 AGENTS.md;离当前目录更近的说明拥有更高优先级。详情见 AGENTS.md 配置说明。

先把用户报告变成最小复现

现在我们只有一句现象描述,还没有可交付证据。继续输入:

请继续保持只读,复现“退款会让总额变大”。

要求:
- 使用 samples/mixed.csv,不修改样例和测试;
- 运行真实 CLI,记录命令、退出码、预期值和实际值;
- 运行完整测试,列出失败测试和通过测试数量;
- 从 CLI 入口追踪到计算函数,解释实际值为何变成 120.00;
- 区分“实际运行证据”和“根据代码作出的解释”;
- 暂时不要给补丁。

这里要拿到两类证据:

  1. 行为证据:100 元支出减去 20 元退款,本应是 80 元,程序实际输出 120 元;
  2. 代码证据:退款分支经过哪条调用路径,哪个表达式把它加进总额。

只有第二类证据,可能只是“发现了可疑代码”;只有第一类证据,又不能说明改哪里风险最小。两者合在一起,才构成可复核的根因判断。

你再亲自运行一次,避免把 Agent 的转述当成事实。

macOS、Linux 或 WSL:

python3 -m legacy_expenses.cli samples/mixed.csv
python3 -m unittest tests.test_core.LegacyExpensesTest.test_refund_reduces_total -v

Windows PowerShell:

py -m legacy_expenses.cli samples\mixed.csv
py -m unittest tests.test_core.LegacyExpensesTest.test_refund_reduces_total -v

生成器可能给测试类用了不同名称。如果第二条命令提示找不到测试,打开 tests/test_core.py,把示例里的类名 LegacyExpensesTest 换成实际类名;测试方法名应仍是我们固定的 test_refund_reduces_total。完整测试命令始终可以作为兜底:

python3 -m unittest discover -s tests -v

Windows 把 python3 换成 py。到这一步,工作区仍应保持干净:

git status --short

先定修复边界,再开放写权限

让 Codex先给方案:

基于刚才的复现和调用路径,请给出最小修复方案,暂时不要实施。

请说明:
- 必须修改的文件和函数;
- 现有失败测试能证明什么,不能证明什么;
- 至少还需要哪些回归用例;
- 普通支出、混合记录、只有退款、非法 type 是否会受影响;
- 局部验证、完整验证和手工验证分别运行什么;
- 明确列出本次不做的重构。

这个案例通常只需要修正退款的符号处理,并补一两个能防止回归的测试。重写 CSV 解析器、引入财务库、顺手更换 CLI 框架,都不属于当前缺陷的最小范围。

确认方案合理后,在 Codex 中输入:

/permissions

在出现的权限选择器中选 Auto。当前官方定义下,Auto 允许 Codex 在工作区内读写和运行命令;越过工作区或访问受限网络仍可能触发审批。权限边界详见 Agent approvals & security。

然后提交实施任务:

请按刚才确认的方案实施最小修复。

要求:
1. 修改前先再次运行目标失败测试,保留“先失败”的证据;
2. 只修改退款计算和必要的回归测试;
3. 不增加依赖,不重构无关代码;
4. 先运行退款相关测试,再运行完整测试;
5. 用 samples/mixed.csv 运行真实 CLI;
6. 最后汇报实际命令、退出码、关键输出和修改文件,不要提交 Git。

如果 Codex 请求安装包或访问网络,先拒绝并检查原因:这个练习明确只用标准库,不需要下载任何依赖。

不要让“测试通过”成为唯一验收

Agent 完成后,在你自己的终端里独立验证。以下命令都在 legacy-expenses 根目录执行。

macOS、Linux 或 WSL:

python3 -m unittest tests.test_core.LegacyExpensesTest.test_refund_reduces_total -v
python3 -m unittest discover -s tests -v
python3 -m legacy_expenses.cli samples/mixed.csv
git diff --check
git status --short
git diff --stat

Windows PowerShell:

py -m unittest tests.test_core.LegacyExpensesTest.test_refund_reduces_total -v
py -m unittest discover -s tests -v
py -m legacy_expenses.cli samples\mixed.csv
git diff --check
git status --short
git diff --stat

仍需按实际测试类名替换 LegacyExpensesTest。理想结果是:

  • 目标测试显示 ok;
  • 完整测试显示全部通过,退出码为 0;
  • 样例打印 Total: 80.00;
  • git diff --check 没有输出;
  • git status --short 只列出预期修改;
  • Diff 规模与“一处计算修复加必要测试”相符。

这几项验证覆盖了不同风险:局部测试证明缺陷被锁住,完整测试观察回归,真实 CLI 证明用户路径恢复,Git 检查证明交付内容没有跑偏。

回到 Codex,输入:

/diff

/diff 会显示已暂存、未暂存和未跟踪的变化。逐项检查:

  • 是否修的是退款规则,而不是对 samples/mixed.csv 中的数字硬编码;
  • 是否保留了原有非法类型处理;
  • 回归测试是否断言具体金额;
  • 是否混入缓存、真实报销数据或无关格式化;
  • README 若没有行为变化,是否被无故改写。

还可以输入 /review,选择 Review uncommitted changes,让专用 Reviewer 只读检查当前工作树。官方说明中,Reviewer 会报告按优先级排列的问题,不会自行修改文件;若随后要求它应用修复,才重新受当前沙箱和审批设置约束。这里只需要关注正确性、遗漏测试和范围扩大,深入的审查流程会在第 16 篇完成。

形成别人可以复核的交付记录

验证通过后,让 Codex 生成简短的交付说明:

根据已经执行的命令,为代码审查者写一份修复说明,包含:
- 用户可见影响;
- 最小复现与修改前结果;
- 根因和修改范围;
- 修改后结果;
- 局部测试、完整测试和真实 CLI 的命令与结果;
- 尚未验证的内容或残余风险。

不要使用“应该”“大概”“看起来没问题”这类没有证据的表述。

然后再次确认工作树,提交修复:

git status --short
git add legacy_expenses tests README.md
git diff --cached --check
git diff --cached --stat
git commit -m "fix refund total calculation"
git status --short

如果 README 实际没有修改,就从 git add 中去掉它;只暂存你已经审查过的文件。提交后最后一条命令应无输出。你还可以运行:

git show --stat --oneline HEAD

确认最新提交就是本次修复,而不是把其他文件一起带了进去。

卡住时先按现象定位

测试在修改前就全部通过

练习基线不成立。回到创建仓库的会话,确认退款分支确实保留缺陷,且目标测试断言正确结果 80.00。不要为了继续教程而把“先失败”的证据省掉。

提示找不到模块或测试

先运行 git rev-parse --show-toplevel,确认当前目录是仓库根目录;再用 git ls-files 核对包和测试文件。目标测试命令中的类名需与 tests/test_core.py 一致。

只读阶段无法修改文件

这是预期行为。调查完成并确认方案后,用 /permissions 选择 Auto。不要重启成危险的全访问模式,也不要为了一个标准库项目开放网络。

Codex 修改了很多无关文件

先不要提交。用 /diff 和 git diff --stat 列出超出范围的文件,让 Codex 说明每一项与根因的关系,并恢复无法证明必要的改动。恢复后重新运行全部验证,不能只看缩小后的 Diff。

修复后测试通过,CLI 仍输出 120.00

这通常说明测试没有走真实 CLI 路径,或 CLI 调用了另一套计算逻辑。让 Codex 重新画出入口到汇总函数的调用路径,并比较测试导入的函数与 CLI 实际调用的函数。

把流程带回真实项目

接手陌生仓库时,可以稳定地按下面的顺序工作:

核对仓库说明与权限
  → 建立入口、数据流和测试地图
  → 检查干净基线
  → 用最小输入复现
  → 把行为证据与代码证据对应起来
  → 明确最小修复边界
  → 目标测试先红后绿
  → 完整测试与真实入口验证
  → 审查 Diff
  → 只提交已验证文件

这套顺序的核心不是让 Codex“少做事”,而是让每一步都留下下一步可以依赖的证据。陌生项目越复杂,越不应该一上来要求“检查整个仓库并顺手修好所有问题”。

本篇小结

我们用两个隔离的会话完成了一次真正的陌生项目维护:第一个会话只负责准备练习仓库,第二个会话先以只读权限建立项目地图和最小复现,再开放工作区写权限实施修复。最终结论同时由目标测试、完整测试、真实 CLI、Git Diff 和独立 Review 支撑。

下一篇回到 TaskFlow,为它加入优先级和截止日期。那次任务不再是一处缺陷,而是同时跨越数据模型、CLI、排序、统计、报告、兼容性、测试和文档的功能开发。


16 实战二-完成跨文件功能开发

预计学习时间:75—90 分钟
本篇目标:为 TaskFlow 增加优先级和截止日期,让数据、CLI、排序、统计、报告、旧数据兼容、测试与 README 遵守同一套规则。

修复一个缺陷时,改动通常可以围绕一条因果链收紧。跨文件功能更容易出现另一类问题:每一处单看都能运行,合在一起却不一致。CLI 默认是 normal,存储层可能写成空值;stats 说任务逾期,报告却没有标记;新数据运行正常,老用户的 JSON 一打开就报错。

这篇回到 TaskFlow 主线,把已经完成的 2.0 升级到 3.0。我们不再练“怎样让 Codex 多写几个文件”,而是练怎样先冻结业务契约,再按阶段让所有受影响位置对齐。

最终结果应满足:

  • add 接受 --priority low|normal|high 与可选的 --due YYYY-MM-DD;
  • list 展示新字段并稳定排序;
  • stats 和 Markdown report 使用相同的逾期规则;
  • 1.0/2.0 JSON 不迁移也能读取;
  • 纯读取旧数据不会偷偷改写文件;
  • 完整测试和一次真实升级演练都通过。

回到 TaskFlow 2.0 的干净基线

上一篇使用的是独立练习仓库。现在请切回 TaskFlow 根目录。开始前应已完成第 10 篇的 2.0 功能:list --status、stats 和 report --output 可以使用,PLAN.md、STATUS.md 与仓库级 taskflow-release Skill 也已经存在。

macOS、Linux 或 WSL:

cd /你的路径/taskflow
git status --short
python3 -m unittest discover -s tests -v
python3 taskflow.py --help

Windows PowerShell:

Set-Location C:\你的路径\taskflow
git status --short
py -m unittest discover -s tests -v
py taskflow.py --help

只有下面三项同时成立,才进入 3.0:

  • git status --short 没有不认识的改动;
  • 2.0 完整测试通过;
  • 帮助中能看到 add、list、done、stats 和 report 等现有命令。

如果你跳过了第 10 篇,先补齐 2.0;这篇不会重新创建项目。若测试基线失败,也应先把失败作为单独问题处理,否则后面无法判断是哪次改动引入了回归。

建立功能分支并记录基线提交:

git switch -c feature/taskflow-3-priority-due
git rev-parse --short HEAD

如果同名分支已经存在,不要覆盖它;先确认它是否属于之前未完成的练习,再换一个新分支名或回到原任务继续。

规划的重点是找到“同一条规则出现了几次”

在 TaskFlow 根目录启动 Codex:

codex --sandbox workspace-write --ask-for-approval on-request

进入 Plan 模式:

/plan

当前官方说明中,/plan 会让 Codex 先调查并提出实施路线;Plan 模式不会因为名字叫“计划”就自动替你消除需求歧义,关键规则仍需由你确认。命令入口和适用场景可参考 Developer commands 与 Prompting。

提交第一版需求:

请规划 TaskFlow 3.0,先检查当前实现、测试、AGENTS.md、PLAN.md、STATUS.md 和 README,但不要修改文件。

目标:
1. add 支持 --priority low|normal|high,默认 normal;
2. add 支持可选的 --due YYYY-MM-DD;
3. list 展示 priority 和 due;
4. list 默认按“未完成优先、优先级从高到低、截止日期从近到远”排序;
5. stats 增加逾期未完成任务数;
6. Markdown report 展示 priority、due 和 overdue 标记;
7. TaskFlow 1.0/2.0 的旧 JSON 仍可读取;
8. 继续只用 Python 标准库,并更新测试与 README。

请先输出:
- 当前数据从 CLI 输入到 JSON、list、stats、report 的调用路径;
- 受影响文件和函数;
- 需求中尚未定义的边界;
- 三个可单独验收的实施阶段;
- 每个阶段的局部测试、完整测试、停止点和回滚点。

此时不要写代码,也不要替我决定业务歧义。

理想的计划会指出,同一个字段至少涉及六类契约:输入校验、内存表示、JSON 兼容、展示与排序、统计/报告、文档示例。若计划只写“修改 taskflow.py 和测试”,说明它还没有把跨文件影响展开。

先冻结 TaskFlow 3.0 的业务契约

这套教程采用下面的规则:

主题 3.0 规则
优先级 只接受 low、normal、high,默认 normal
截止日期 可省略;提供时必须是有效的 YYYY-MM-DD 日历日期
默认排序 未完成在前;再按 high → normal → low;同优先级时有截止日期的在前,日期早的在前;仍相同时按任务 ID 升序
逾期 仅当任务未完成且 due < 今天;截止当天不逾期
已完成任务 永远不标记逾期,但仍展示原截止日期
旧字段缺失 缺少 priority 按 normal 读取;缺少 due 按无日期读取
旧数据改写 list、stats、report 等纯读取命令不得改写 JSON;后续用户主动执行写命令时允许按当前格式保存,但任务语义不能变化
非法旧数据 已存在但值非法的 priority 或 due 必须给出明确错误,不静默替换成默认值

把规则发给 Codex:

请用以上规则修订计划和测试矩阵,仍不要实现。

额外要求:
- 日期相关测试固定参考日,不读取测试运行当天;
- stats 与 report 必须复用同一份逾期判断;
- 排序必须有任务 ID 兜底,避免结果在不同运行间漂移;
- 读取旧 JSON 的兼容测试还要证明纯读取不会改变文件字节;
- 列出非目标:不增加提醒通知、不增加时区、不引入迁移命令、不更换 CLI 框架。

先退出 Plan 模式并确认 workspace-write 权限;只授权以下文档落盘,再进入实现阶段。把确认后的 3.0 计划写入现有 PLAN.md,把 STATUS.md 更新为“阶段一待开始”,然后停下。除了这两个状态文件,不修改业务代码。

收到结果后输入 /diff,只应看到 PLAN.md 和 STATUS.md 的计划性变化。计划里至少要有下面三段:

  1. 数据模型与旧数据兼容;
  2. add、list 与排序;
  3. stats、report 与真实升级演练。

如果 Codex 已经改了业务代码,先让它恢复这些提前发生的修改,再进入阶段一。跨文件任务最容易失控的时刻,就是计划和实现混在同一轮里。

阶段一:先让新模型读得懂旧数据

提交阶段一任务:

执行 PLAN.md 的阶段一:扩展任务数据模型并保持 1.0/2.0 JSON 兼容。只做这一阶段,完成后停止。

验收要求:
- 新任务在内存中有 priority 和 due;
- 缺少 priority 的旧任务按 normal 读取,缺少 due 按空值读取;
- 已存在但非法的 priority 或 due 返回明确错误;
- 纯读取旧数据不会改写文件;
- 测试覆盖旧记录、新记录、缺字段、非法值和读取前后字节一致;
- 不修改 add/list/stats/report 的用户界面;
- 运行相关测试和完整测试;
- 更新 STATUS.md,列出修改文件、实际命令、结果与下一步。

完成后先看可见结果:业务代码、兼容测试和 STATUS.md 可以变化,CLI 展示与 README 不应提前进入 3.0。然后在另一个终端独立运行:

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v
git diff --check
git diff --stat

Windows PowerShell:

py -m unittest discover -s tests -v
git diff --check
git diff --stat

完整测试通过只说明现有测试认可实现,还要打开新兼容测试确认它真的验证了三件事:旧字段缺失得到默认语义、非法字段被拒绝、只读命令执行前后文件内容完全一致。只创建一个“旧 JSON 能解析”的测试还不够。

阶段二:把输入、展示和排序当成一个契约

继续提交:

执行 PLAN.md 的阶段二:扩展 add 与 list。不要进入 stats 和 report。

要求:
1. add 接受 --priority low|normal|high,默认 normal;
2. add 接受可选 --due YYYY-MM-DD,并拒绝不存在的日期;
3. 保留原有 add 用法;
4. list 展示 priority 和 due,无日期时使用 README 中定义的统一表示;
5. 严格按已确认的“状态、优先级、日期、任务 ID”顺序排序;
6. 测试覆盖默认值、三个优先级、无日期、非法枚举、非法日期和所有排序层级;
7. 更新 README 对应命令和示例;
8. 运行相关测试与完整测试,更新 STATUS.md 后停止。

这里最容易漏掉的是“最后一个排序键”。如果两条任务的状态、优先级和日期都相同,却没有 ID 兜底,结果可能依赖输入顺序或内部实现,测试也会偶发变化。

测试通过后,让 Codex 根据当前项目真实的数据文件参数或环境变量准备冒烟命令,不要凭教程猜参数:

请先只输出、不要执行一组 TaskFlow 3.0 add/list 冒烟命令。

命令必须使用当前项目真实支持的数据路径机制,并指向一个可删除的临时 JSON,绝不能读写 data/tasks.json。请创建下面六条任务:
- 未完成 high,due=2999-01-01;
- 未完成 high,无 due;
- 未完成 normal,due=2999-01-01;
- 未完成 low,due=2000-01-01;
- 未完成 normal,无 due;
- 已完成 high,due=2000-01-01。

最后运行 list,标明预期 ID 顺序,并给出清理临时文件的命令。所有占位路径都替换成真实路径。

先检查命令中的数据路径。只要仍指向 data/tasks.json,就不要执行,让 Codex 改成临时文件。确认后再让它运行,或者复制到另一个终端执行。

预期排序逻辑是:所有未完成任务先出现;未完成内部先 high,再 normal,最后 low;同一优先级下有日期的在无日期之前;最后才出现已完成任务。注意,优先级比截止日期更靠前,所以一条已经逾期的 low 任务不会越过未来截止的 normal 任务。这不是唯一合理规则,但它是本教程已经冻结的规则。

再次检查:

git status --short
git diff --check

临时 JSON、缓存和冒烟输出不应进入待提交文件。

阶段三:让统计和报告共享同一个“今天”

提交最后一个实现阶段:

执行 PLAN.md 的阶段三:扩展 stats 和 Markdown report,然后完成真实升级演练。不要增加计划外功能。

要求:
- stats 增加逾期未完成任务数;
- report 的每条任务展示 priority 和 due,并只给逾期未完成任务加 overdue 标记;
- stats 与 report 复用同一份逾期判断;
- 业务函数可以注入参考日期,自动化测试固定 today=2026-06-15;
- due=2026-06-14 的未完成任务逾期;
- due=2026-06-15 的未完成任务不逾期;
- due=2026-06-14 的已完成任务不逾期;
- 报告摘要与明细中的逾期数量一致;
- 更新 README,运行相关测试与完整测试;
- 更新 STATUS.md 后停止。

不要用修改电脑系统日期来测试。可注入的 today 或集中封装的日期函数,能让测试在明天、下个月和 CI 中得到同样结果。你要检查的是 stats 与 report 是否调用同一份规则,而不是分别复制一段看起来相同的条件判断。

完成后独立运行完整测试:

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v

Windows PowerShell:

py -m unittest discover -s tests -v

然后让 Codex 输出一份临时报告,并明确回显:临时数据路径、生成文件路径、stats 的逾期数、报告摘要的逾期数,以及哪些任务带有 overdue 标记。三处数字必须能互相对上。

用一份真实旧文件演练升级,而不是只测新用户

普通功能测试容易从空数据开始,遗漏老用户路径。现在单独做一次升级演练:

请在系统临时目录中完成 TaskFlow 2.0 → 3.0 升级演练,不要修改仓库内的 data/tasks.json。

步骤:
1. 创建一份旧格式 JSON,至少包含一条未完成和一条已完成任务,二者都没有 priority 和 due;
2. 记录文件路径和运行前 SHA-256;
3. 用 3.0 依次运行 list、stats 和 report;
4. 再次计算 SHA-256,证明三条纯读取命令没有改写旧文件;
5. 对同一临时文件执行一次 add,创建带 high 和 due 的新任务;
6. 再运行 list、stats、done 和 report;
7. 打开最终 JSON 与 Markdown 报告,核对旧任务语义、新任务字段、完成状态和逾期数字;
8. 记录每条命令的退出码和关键输出,最后清理临时文件。

如果当前 CLI 的数据路径参数与这里表述不同,以实际 --help 和 README 为准。不要为了演练修改真实用户数据。

合格证据应同时说明:

  • 旧文件不经过手工迁移即可读取;
  • 三条纯读取命令前后 SHA-256 相同;
  • 主动写入后,新任务保存新字段;
  • 旧任务仍有正确的默认语义;
  • done、stats 与报告在升级后的同一文件上仍然一致。

如果只证明“单元测试通过”,还不能说明真实命令链路正确;如果只跑真实命令却不保留旧文件哈希,也不能证明读取没有副作用。

做一次跨文件契约审查

实现完成后,让当前会话先只读审查,不要立即修:

请对 TaskFlow 3.0 做跨文件契约审查,暂时不要修改。

逐项核对并给出文件、测试或命令证据:
- CLI 默认 priority 与旧数据默认 priority 是否一致;
- add 写出的 due 与读取、展示的格式是否一致;
- list 排序与 README 描述是否完全一致;
- stats、report 明细和 report 摘要是否共用逾期定义;
- 纯读取旧文件是否保持字节不变;
- 无效 priority/date 的错误信息与退出码是否一致;
- README 示例是否可以直接运行且不会碰真实数据。

把发现分为“阻塞 3.0”“非阻塞建议”“已验证无问题”。每个阻塞项先给最小复现,不要直接扩大重构范围。

跨文件审查关注的是同一个概念在不同层之间有没有漂移。某个函数写得是否优雅,可以留到下一篇;契约不一致则必须在本篇收口。若发现阻塞问题,按“补回归测试—最小修复—局部验证—完整测试—重跑升级演练”的顺序处理。

完成最终验收并提交

先运行仓库级发布检查 Skill,作为功能完成后的初步检查:

$taskflow-release 请对当前 TaskFlow 3.0 功能分支做一次发布前检查。重点核对完整测试、旧数据兼容、README 和未跟踪文件;只生成或更新 RELEASE_CHECK.md,不提交、不打标签、不推送、不发布。

这个报告只是证据索引,不能替代你亲自执行验证。最后在终端运行:

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v
git diff --check
git status --short
git diff --stat
git diff --name-only

Windows PowerShell:

py -m unittest discover -s tests -v
git diff --check
git status --short
git diff --stat
git diff --name-only

最终应看到:

  • 完整测试全部通过;
  • 没有空白错误;
  • 变化集中在业务代码、测试、README、计划/状态和发布检查报告;
  • 没有 data/tasks.json、临时 JSON、临时报告、缓存或真实任务数据;
  • STATUS.md 记录的命令与刚才实际执行的结果一致。

在 Codex 中输入 /diff,逐个文件检查后再明确暂存:

git add taskflow.py tests README.md PLAN.md STATUS.md RELEASE_CHECK.md
git diff --cached --check
git diff --cached --stat
git commit -m "add priority and due dates"
git status --short

如果实际项目拆成了多个模块,或某个列出的文件并未存在,就按照 git diff --name-only 的结果逐个添加;不要用 git add . 把临时数据一起收入提交。提交后 git status --short 应为空。

遇到问题时先看契约落在哪一层

新任务正常,旧 JSON 报错

检查读取路径是否在字段访问前补默认值,以及兼容测试是否真的使用了不含新字段的原始 JSON。只在 add 中设置默认值,无法帮助历史记录。

测试今天通过,明天失败

日期逻辑仍直接读取系统当天。把参考日作为参数传入业务函数,或集中到可替换的日期函数;测试固定参考日,CLI 默认才使用真实当天。

stats 与报告逾期数量不同

寻找两套独立条件判断。应让二者调用同一业务函数,并用同一组任务和同一参考日做一致性测试。

list 顺序偶尔变化

检查排序键是否包含所有层级,尤其是最后的任务 ID;还要确认优先级使用显式映射,而不是按 high、low、normal 的字母顺序排序。

冒烟测试改动了真实 data/tasks.json

立即停止后续命令,先保存 git status 和 Diff 证据。若该文件受 Git 管理,确认改动只来自本次误操作后再恢复;若它包含真实未提交数据,不要直接覆盖,先备份并人工比较。下一次演练必须在执行前检查临时路径。

本篇小结

TaskFlow 3.0 的难点不是两个新字段,而是让这两个字段在输入、存储、兼容、排序、统计、报告、测试和文档中保持同一含义。我们先用 Plan 模式找出跨层影响,再冻结业务契约,按三个阶段实施,每阶段都停下来验证,最后用旧文件哈希和真实命令链路证明升级可用。

下一篇不再增加功能。我们会把这个已提交的 3.0 分支当成发布候选版本,使用专门的 Review、复现证据和有限重构完成发布前收口。


17 实战三-代码审查重构与发布准备

权限名称可能随版本和配置变化。本课按能力选择:调查用 read-only,实施用 workspace-write。若 /permissions 没有只读选项,退出后运行 codex --sandbox read-only --ask-for-approval on-request;实施前用 workspace-write 重新启动并明确提供计划,不凭 Read Only/Auto 等标签猜权限。

预计学习时间:70—85 分钟
本篇目标:审查第 15 篇提交的 TaskFlow 3.0,验证而不是照单全收 Review 发现,只处理已证实的发布阻塞项,在行为证据保护下决定是否重构,并生成可核对的发布材料。

功能完成后最危险的两个动作,一是看到 Review 结论就立刻全改,二是趁发布前“顺手把代码整理漂亮”。前者会把误报变成真实改动,后者会让功能变化和结构变化混在一起。

这一篇不增加任何新功能。最终要留下五类证据:

  • 审查目标确实是 TaskFlow 3.0 的那次提交;
  • 每个接受的发现都有复现或测试证据;
  • 修复与重构前后,用户可见行为保持在已确认范围内;
  • README、CHANGELOG、发布说明和实际功能一致;
  • 最终测试、升级演练、Git 状态与发布检查全部通过。

先确认你审查的是哪一份代码

上一篇最后创建了 add priority and due dates 提交,并留下干净工作树。进入 TaskFlow 根目录后运行:

git branch --show-current
git status --short
git log --oneline --decorate -5
git show --stat --oneline HEAD

你需要看到:

  • 当前位于 3.0 功能分支;
  • git status --short 没有输出;
  • HEAD 正是第 15 篇的 3.0 提交;
  • git show --stat HEAD 的文件范围与优先级、截止日期、测试和文档有关。

如果 HEAD 不是 3.0 提交,先不要运行 Review。审查工具会忠实检查你指定的范围,范围选错后,结论再具体也没有意义。

再建立发布候选基线。

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v
git status --short

Windows PowerShell:

py -m unittest discover -s tests -v
git status --short

完整测试应通过,工作树仍应干净。若这里已经失败,先把它作为“3.0 功能未完成”返回上一篇处理,不要让 Review 替代基本测试。

先用独立 Reviewer 审查那个提交

Codex CLI 提供两种常用入口:

  • 在交互界面输入 /review,从预设中选择基准分支、未提交改动或某个提交;
  • 在普通终端运行 codex review,完成一次非交互审查后退出。

本篇先用第二种,因为上一篇把整个 3.0 功能放进了最新提交。退出当前 Codex 交互界面或打开另一个终端,在 TaskFlow 根目录执行:

codex review --commit HEAD > ../taskflow-review-1.txt 2>&1

保存第一轮输出后立即检查退出码:bash 为 $?,PowerShell 为 $LASTEXITCODE;非零先解决错误。文件放项目外,所以后续工作区检查仍应干净。PowerShell 7+ 读取时使用 UTF-8。当前本机帮助中,--commit、--base、--uncommitted 和自定义 PROMPT 是互斥审查目标,不能在同一条命令中叠加多个范围。执行前可用下面的命令核对你安装版本的实际参数:

codex review --help

可见结果应该是一份按优先级组织、带文件位置和影响说明的审查,而不是一批文件修改。官方文档明确说明,专用 Reviewer 读取选定 Diff 并报告发现,不会自行修改工作树;只有你随后要求 Codex 应用修复时,才重新受当前沙箱和审批设置约束。审查范围和行为见 Code review 与 Developer commands。

Review 结束后立即验证这一点:

git status --short

结果应仍为空。如果出现文件变化,先确认是否是你同时运行的其他任务产生的,不要默认它来自 Reviewer。

第二轮 Review 要带着业务契约,而不是只说“再仔细看看”

默认 Review 适合发现广泛问题,但 TaskFlow 3.0 还有一套在第 15 篇冻结的业务规则。现在启动 Codex 交互界面:

codex --sandbox read-only --ask-for-approval on-request

输入 /review,选择 Custom review instructions,提交下面的范围:

请审查最新的 TaskFlow 3.0 提交,只报告会影响正确性、数据、兼容性或可验证发布的发现,不修改文件。

重点核对:
1. 旧记录缺少 priority/due 时能读取,非法现有值不会被静默吞掉;
2. list、stats、report 等纯读取命令不会改写旧 JSON;
3. 排序严格按状态、优先级、日期、任务 ID;
4. stats、report 摘要与明细共用同一逾期定义;
5. 截止当天不逾期,已完成任务不逾期;
6. 测试不会依赖运行当天;
7. README 示例、默认值和真实 --help 一致;
8. 仓库中没有临时数据、缓存、密钥或个人绝对路径。

每个发现必须给出:优先级、文件与位置、触发输入、用户影响、现有证据、最小复现。无法证实的内容标为“待验证”,不要当作缺陷。

这次审查与上一轮的区别,不是模型“更认真”,而是检查标准更贴近产品契约。Review 最有价值的输入通常是准确范围、不能破坏的行为和可复现条件,而不是泛泛要求“全面审查”。

先验证发现,再决定接不接受

把两轮结果交给当前会话整理:

先读取我提供的 ../taskflow-review-1.txt,并记录两轮审查对应的提交号;若无法读取请停止合并。再合并该文件中的第一轮与本会话第二轮 Review 的发现,去除重复项,暂时不要修改。

按下面四类输出:
- 已有命令或测试能够复现的发布阻塞缺陷;
- 需要补一个最小测试才能判断的风险;
- 有证据但不阻塞 3.0 的改进建议;
- 缺乏触发路径或与当前需求不符的疑似误报。

每项写明验证命令、预期结果、实际结果和你为何归入该类。不要仅根据 Reviewer 给出的优先级下结论。

然后逐项执行前两类的最小复现。判断一个发现是否成立,至少要回答:

  1. 这个输入在当前产品规则中是否允许出现?
  2. 它是否真的经过 Review 指出的代码路径?
  3. 实际结果是否违反第 15 篇确认的契约?
  4. 有没有自动化测试或可重复命令证明?

如果 Review 说“可能有问题”,但无法给出合法输入和错误结果,就先保留为待验证风险。不要为了让报告里“零发现”而修改稳定代码。

只修已证实的发布阻塞项

若确有阻塞项,先用 /permissions 把当前会话从 Read Only 切换到 Auto,再逐项修复:

只处理已经复现的发布阻塞项,一次处理一项。

每项遵循:
1. 先增加最小回归测试,并证明修改业务代码前该测试失败;
2. 做最小修复,不顺带重构;
3. 运行目标测试;
4. 运行完整测试;
5. 重跑原始复现命令;
6. 展示本项 Git Diff 与剩余风险。

某项无法稳定复现时停止,不要猜着修。不要提交、打标签、推送或发布。

如果两轮 Review 都没有发现可复现阻塞项,不需要故意制造修改。记录“没有接受的阻塞发现”也是有效结果,前提是基线测试、升级演练和发布检查仍会重新执行。

修复后在终端独立验证:

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v
git diff --check
git diff --stat

Windows PowerShell:

py -m unittest discover -s tests -v
git diff --check
git diff --stat

预期结果是完整测试通过、没有空白错误,而且变化只覆盖回归测试、根因修复和必要说明。Review 本身不是成功证据;它只是帮你找到值得验证的问题。

重构必须通过一道“现在值得做吗”的门

TaskFlow 从 1.0 升到 3.0 后,代码中可能出现重复解析、过长函数或职责混合。它们不一定都值得在发布前处理。先让 Codex 只评估:

请评估当前 TaskFlow 3.0 是否存在会明显提高下一次修改风险的结构问题,暂时不要改代码。

最多提出 3 个候选。每个候选必须说明:
- 已有证据,而不是只说文件太长;
- 如果现在不改,下一次最可能在哪类需求中出错;
- 需要保持不变的 CLI、JSON、排序、统计和报告行为;
- 现有测试是否足以保护;
- 修改规模、失败时回退方法和是否值得阻塞 3.0 发布。

最后给出“现在做一个”“全部延期”二选一建议。

只有同时满足下面三点,才选一个候选实施:

  • 风险具体,例如同一校验或排序键存在多份实现;
  • 用户可见行为已经有测试和冒烟证据保护;
  • Diff 能保持小而独立,不夹带新功能。

若满足条件,先锁定行为:

只实施刚才选中的一个有限重构,不增加功能。

实施前:
- 运行完整测试;
- 用临时数据记录 add、list、stats、report 的关键输出;
- 记录临时 JSON 和 Markdown 报告的内容或哈希。

实施后:
- 重跑同一组命令;
- 比较输出、JSON 语义和报告内容;
- 运行完整测试;
- 展示只属于这次重构的 Diff。

如果行为证据发生计划外变化,恢复这次重构并报告,不要修改验收标准。

“全部延期”不是失败。发布前重构的目标是降低已知风险;如果收益模糊或测试保护不足,保留稳定实现通常更负责。把延期项写入发布说明的已知限制或后续计划即可。

根据仓库事实生成发布材料

现在让 Codex 根据 Git、测试和 README 起草材料,而不是根据聊天记忆编写:

请根据 TaskFlow 2.0 到当前 3.0 的实际 Git 提交、README、测试和已验证命令,准备发布材料。

1. 在 CHANGELOG.md 增加 3.0 条目;
2. 创建 RELEASE_NOTES.md;
3. 更新 README 中已经过时的命令或排序说明;
4. 更新 STATUS.md,写明已接受的 Review 发现、已延期建议和最近验证。

发布材料必须包含:
- 新增 priority 与 due;
- 默认排序的用户可见变化;
- 旧 JSON 兼容和纯读取不改写的边界;
- 逾期定义;
- 实际验证过的操作系统与命令;
- 已知限制。

不要编造性能提升、支持平台、零缺陷或“完全兼容”等无法由证据支持的结论。不要提交、打标签、推送或发布。

打开两个发布文件逐条核对。一个简单方法是让 Codex 为每条重要声明附上证据来源:对应测试名、README 小节、Git 提交或手工验证命令。来源可以在起草阶段使用,最终面向用户的发布说明不必写成测试报告。

尤其要检查“兼容”这个词。当前证据支持的是:旧记录缺少新字段仍能读取,纯读取命令不改写旧 JSON,后续主动写入可以按当前格式保存且语义不变。它不自动等于所有历史版本、损坏文件和未来格式都兼容。

用发布检查 Skill 做最终证据索引

显式调用第 11 篇创建的 Skill:

$taskflow-release 请执行 TaskFlow 3.0 最终发布检查。

重点核对:
- 完整测试;
- 2.0 旧数据升级演练;
- add/list/stats/report 冒烟命令;
- README、CHANGELOG、RELEASE_NOTES 的事实一致性;
- Git Diff 与仓库清洁度;
- 是否含真实数据、密钥、缓存、临时文件或个人绝对路径。

只生成或更新 RELEASE_CHECK.md。把每个结论对应到实际命令和结果;无法验证的项目标为 unknown。不要修改业务代码,不要提交、打标签、推送或发布。

打开 RELEASE_CHECK.md,确认每一个 pass 都有证据。报告写“测试通过”,至少应能看到真实测试命令和结果;写“旧数据兼容”,应能对应上一篇的升级演练或本轮重跑结果。

如果 Skill 为了消除阻塞而修改业务代码,说明它越过了第 11 篇设定的边界。先停止,审查 Skill 和 Diff,再恢复到“只检查、只写报告”。

再审一次未提交变化

3.0 功能提交已经审过;这一轮又可能产生了修复、有限重构和发布文档。现在审查未提交工作树:

codex review --uncommitted

这一范围包括已暂存、未暂存和未跟踪文件。它与前面的 --commit HEAD 不是同一个问题:

命令 审查对象
codex review --commit HEAD 已提交的 3.0 功能提交
codex review --uncommitted 本轮尚未提交的修复、重构与发布材料

不要同时传 --commit 和 --uncommitted。如果未提交 Review 发现问题,仍先复现、确认范围,再做最小修改和完整验证。

人工完成最后一道发布门

在 TaskFlow 根目录亲自执行:

macOS、Linux 或 WSL:

python3 -m unittest discover -s tests -v
git diff --check
git status --short
git diff --stat
git diff --name-only

Windows PowerShell:

py -m unittest discover -s tests -v
git diff --check
git status --short
git diff --stat
git diff --name-only

还要人工确认:

  • 临时升级 JSON、真实 data/tasks.json、缓存和生成过程日志没有进入 Diff;
  • 没有 .env、API Key、个人绝对路径或敏感任务内容;
  • README 中复制命令与当前 --help 一致;
  • CHANGELOG 和 RELEASE_NOTES 没有夸大验证范围;
  • RELEASE_CHECK 的阻塞项为零,unknown 已经明确处理或写入限制;
  • 本轮没有执行 git push、创建远程 Release 或发布包。

输入 /diff 再看一遍实际内容,然后按 git diff --name-only 明确暂存。常见文件可以这样写:

git add taskflow.py tests README.md CHANGELOG.md RELEASE_NOTES.md STATUS.md RELEASE_CHECK.md
git diff --cached --check
git diff --cached --stat
git commit -m "prepare TaskFlow 3.0 release"
git status --short

如果本轮没有修改业务代码或测试,就不要为了照抄命令而添加它们;按实际文件列表逐个暂存。提交后工作树应干净。

最后创建本地标签前,先检查是否重名:

git tag --list taskflow-3.0

没有输出时再创建带说明的本地标签:

git tag -a taskflow-3.0 -m "TaskFlow 3.0"
git show --no-patch --decorate taskflow-3.0

git show 应指向刚才的发布准备提交。若标签已存在,先确认它指向哪里,不要强行覆盖。本教程到此只完成本地发布准备,不执行 git push、git push --tags 或任何真实发布;那些动作会影响远端和其他协作者,需要你单独确认目标仓库与发布权限。

卡住时先看 Review 范围与证据

Review 没发现问题,但完整测试失败

两者并不矛盾。Review 分析选定 Diff,测试执行实际代码路径。先修复可复现测试失败,不能用“无 Review 发现”覆盖红灯。

Review 报告的文件不属于 3.0

检查你选的是 --commit HEAD、--uncommitted 还是基准分支范围,再用 git show --name-only HEAD 或 git status --short 核对。范围不对时重新审查,不要解释错误目标上的发现。

修完发现后,Reviewer 又提出风格建议

回到发布门槛:是否有合法触发输入、用户影响和回归证据。纯命名、格式或个人偏好可以记录,但不必在发布前清零。

重构后测试通过,手工输出发生变化

测试保护不完整。把变化补成明确回归测试;若变化不是已批准需求,就撤回这次重构,而不是把发布说明改成“新行为”。

RELEASE_CHECK 写着通过,但工作树很脏

报告只是某一时刻的汇总。以当前 git status、测试和实际 Diff 为准,清理或解释新增文件后重新运行检查。

本篇小结

这次发布准备把“审查、修复、重构、文档、检查”拆成了五个不同判断。Review 负责提出值得验证的风险,复现和测试决定发现是否成立;重构只有在风险具体且行为被锁定时才进行;发布材料从仓库事实生成;最终仍由真实命令、Diff 和人工确认封口。

到这里,TaskFlow 的 CLI 主线完成了从规划、实现、调试、扩展、自动化到发布准备的完整闭环。下一篇转向 ChatGPT 桌面端与 Codex 工作模式,用文件整理、数据分析和方案比较三个非编程案例,把同样的“先限定范围、再执行、最后验收”迁移到办公任务。


18 Codex桌面客户端的三个办公实战

预计学习时间:60—75 分钟
本篇目标:在 ChatGPT 桌面应用中完成三个非编程任务,并学会在 Codex、ChatGPT Work、本地与云端之间做选择。

前面十几篇一直在终端和代码仓库里工作。这一篇换到桌面应用,但可靠完成任务的方法没有变:先限定资料范围,再让 Agent 提方案;执行后打开真实文件,用数量、公式和原始证据验收。

先澄清一个容易混淆的名称:你安装的是 ChatGPT 桌面应用,应用中可以选择 ChatGPT 或 Codex;选择 ChatGPT 后,还可能在输入框上方切换 Chat 与 Work。它们不是三个独立客户端。官方桌面应用说明给出的基本路径也是“选择 ChatGPT 或 Codex”,再在 ChatGPT 中选择 Chat 或 Work。

这篇会这样分工:

任务 本篇选择 原因
移动、重命名本机文件 Codex · Local 需要明确工作目录、文件操作和可检查的路径变化
分析 CSV、生成办公成品 ChatGPT · Work locally 目标是可打开、可复核的表格与报告
比较多份方案 ChatGPT · Work locally 需要跨文档提取证据并形成对比成品

ChatGPT Work 更强调“完成一个有明确产物的任务”,Codex 则会保留更多文件、命令和变更细节。官方也说明:非编程工作可以继续在 Codex 中完成;Work 是更偏日常工作的体验。若你的账号、地区或组织策略暂时没有 Work,后两个案例直接用 Codex · Local 也能练习,只是界面和产物预览方式可能不同。参见 Get started with ChatGPT Work 和 Use ChatGPT。

先准备一个不会误伤真实资料的练习区

新建下面的目录,不要把桌面、下载目录或整个个人主目录直接交给 Agent:

office-practice/
├── file-sort/
│   └── inbox/
├── sales/
└── vendors/

三个目录只放脱敏副本:

  • file-sort/inbox/:复制 8—15 个不同类型的样例文件;
  • sales/:稍后保存 sales.csv;
  • vendors/:放三份脱敏方案,PDF、Word 或 Markdown 均可。

如果前面已经安装 Codex CLI,可以在普通终端打开第一个目录。将路径替换为你电脑上的真实绝对路径:

codex app "/绝对路径/office-practice/file-sort"

这个命令会启动桌面应用;没有安装时会进入安装流程。macOS 会直接打开给定工作区,Windows 当前会打印需要打开的路径,你再到应用里选择该目录。你也可以直接打开应用,选择 Codex,再用“打开文件夹”一类的入口选择 file-sort。界面文字可能随版本变化,但目的只有一个:让当前 Local 任务的根目录是 file-sort,而不是更大的目录。

案例一:先预演,再整理一批杂乱文件

这个案例选择 Codex · Local。Local 会直接在所选目录中工作,因此第一次一定使用副本。开始前先在文件管理器中确认 inbox 的文件数量,记作 N。

也可以在应用的集成终端或系统终端中独立计数。

macOS、Linux 或 WSL:

find inbox -type f ! -name '.DS_Store' | wc -l

Windows PowerShell:

(Get-ChildItem .\inbox -File -Recurse | Where-Object Name -ne 'desktop.ini').Count

记住这个数字。它是整理后的第一条验收证据。

1. 只读盘点,不让它立即开工

新建 Codex 任务,输入:

请只读盘点 inbox 中的文件,不要创建、移动、重命名、覆盖或删除任何文件。

按表格列出:当前相对路径、文件类型、从文件名或可安全读取的内容中得到的主题、日期、建议类别、不确定项。

边界:
- 不访问 file-sort 之外的目录;
- 不打开明显包含密码、证件号或其他敏感信息的文件;
- 证据不足时写“待确认”,不要根据常识补全。

最后报告实际发现的文件总数。

预期先出现一份盘点表,文件数应与 N 一致,磁盘中的文件位置不变。若数字不同,先别继续:检查隐藏文件、子目录、无法读取的文件,或确认 Agent 是否遗漏了某种格式。

2. 把“怎么整理”变成可审查的计划

根据盘点结果设计一个最多两层的目录结构,但暂时不要执行。

请创建 ORGANIZE_PLAN.md,逐个记录:
- 原相对路径;
- 目标相对路径;
- 重命名理由;
- 判断置信度;
- 是否存在重名或覆盖风险。

规则:
- 已确认文件放到 organized/ 下;
- 无法可靠分类的文件放到 pending/;
- 文件名尽量使用“日期-主题-类型”,日期未知时保留原文件名信息;
- 不覆盖同名文件,不删除文件;
- 给出按清单回退到 inbox 的方法。

完成计划后停下来等我确认。

打开 ORGANIZE_PLAN.md,重点看三件事:分类是否细得过头,文件名是否丢失重要信息,多个源文件是否指向同一个目标。这里发现问题只需改计划,还没有碰真实文件。

3. 执行后用路径和数量验收

确认计划后输入:

按我确认后的 ORGANIZE_PLAN.md 执行。

同时创建 MANIFEST.csv,列为 source,target,status,note;每个源文件恰好一行。遇到目标重名、读取失败或判断不确定时不要猜,也不要覆盖,保留源文件并把状态写为 blocked。

完成后报告 moved、blocked、failed 的数量,不删除任何文件。

预期看到 organized/、可能存在的 pending/,以及计划和清单文件。现在不要只看 Agent 的“完成”消息,自己复核:

macOS、Linux 或 WSL:

find organized pending -type f 2>/dev/null | wc -l
find inbox -type f ! -name '.DS_Store' | wc -l

Windows PowerShell:

(Get-ChildItem .\organized,.\pending -File -Recurse -ErrorAction SilentlyContinue).Count
(Get-ChildItem .\inbox -File -Recurse | Where-Object Name -ne 'desktop.ini').Count

第一项加上 inbox 中未移动的文件数,应等于原来的 N。再随机抽查三行 MANIFEST.csv,确认源路径、目标路径与磁盘实际位置一致,并打开两三个文件检查它们仍能正常读取。

若整理结果不满意,不要让 Agent“凭记忆恢复”。要求它先读取 MANIFEST.csv,输出反向移动预览;你确认没有目标冲突后,再按 target → source 回退。清单的意义就在于让撤回也有证据。

案例二:分析 CSV,但先把口径说清楚

这个案例选择 ChatGPT · Work · Work locally。在桌面应用中切到 ChatGPT,再在输入框上方选择 Work;若输入框附近有 Work locally 与 Cloud 选项,保留 Work locally,因为源文件只在本机。官方说明中,Cloud 适合希望关机后继续运行或从网页、手机继续的任务;依赖本机文件或应用时应使用本地方式。

为了让你能核对结果,把下面内容保存为 office-practice/sales/sales.csv:

date,order_id,region,product,amount,status
2026-01-05,O001,华东,A,1200,paid
2026-01-18,O002,华南,B,800,paid
2026-02-04,O003,华东,A,1500,paid
2026-02-20,O004,华南,B,900,paid
2026-03-03,O005,华东,B,1100,paid
2026-03-16,O006,华南,A,1400,paid
2026-03-16,O006,华南,A,1400,paid
2026-03-28,O007,华北,A,-200,refunded

把 sales.csv 添加到任务,或将 sales 文件夹作为本地工作位置。先不要说“帮我分析一下”,而是先做数据体检:

请先检查 sales.csv,不修改原文件,也暂时不要生成业务结论。

报告列名、总行数、日期范围、空值、重复 order_id、完全重复行、异常金额和 status 取值。请区分:
1. 可以从数据直接确认的问题;
2. 必须由我确认的业务口径;
3. 你建议的处理规则及其影响。

正确盘点应识别出 8 行数据、O006 的重复记录,以及一笔状态为 refunded 的负数金额。负数不应直接被删掉,因为它可能是合法退款。

接着冻结口径:

采用以下口径完成分析:
- 按 order_id 去重;完全相同的重复行只保留一行;
- 净销售额包含 refunded 的负数金额;
- 订单数只统计 paid 状态的不同 order_id;
- 客单价 = 当月净销售额 / 当月 paid 订单数;
- 原始 CSV 保持不变。

请生成:
1. sales-analysis.xlsx,至少包含 Raw、Cleaned、Monthly Summary 三个工作表;
2. sales-brief.md,写给业务负责人,包含指标口径、月度表、三条观察和仍需确认的问题。

不要把月份变化写成因果关系。完成后说明每个文件保存在哪里。

如果当前界面不能生成 .xlsx,就让它改为输出 sales-cleaned.csv、sales-monthly-summary.csv 和 sales-brief.md;不要因为格式能力不同而放弃验收。

打开实际产物。正确去重和退款口径下,月度结果应为:

月份 净销售额 paid 订单数 客单价
2026-01 2000 2 1000
2026-02 2400 2 1200
2026-03 2300 2 1150

至少手工复算三月:1100 + 1400 - 200 = 2300,重复的 O006 不能再加一次。再检查 Raw 工作表是否保留 8 行、Cleaned 是否只有 7 行。这样验证的是源数据、清洗规则和公式,而不是报告写得是否顺眼。

真实工作中若退款应计入原订单月份,而不是退款发生月份,结果会不同。这不是 Agent 算错,而是业务口径不同;先确认口径再生成结论,正是这个练习要建立的习惯。

案例三:比较方案时,先建立证据链

把三份脱敏供应商方案放入 vendors/。仍使用 ChatGPT · Work locally;没有 Work 时用 Codex · Local,并明确输出文件名。开始时只提取事实:

请阅读 vendors 目录中的三份方案,暂时不要推荐供应商,也不要打分。

统一提取:总价与计价口径、交付范围、时间计划、服务水平、付款条件、违约责任、数据安全、实施依赖和退出机制。

请生成 vendor-evidence.xlsx:
- 每个事实必须带文件名,以及可定位的章节或页码;
- 原文未写的内容标为“未提供”;
- 口径不一致时保留原始口径,并单列“无法直接比较”;
- 扫描件或 OCR 无法确认的位置标为“引用待核对”,不要编造页码。

打开表格,任意选择三条重要信息,回到原文件对应页核对。至少覆盖一条价格、一条交付时间和一条退出或违约条款。若三条中有一条找不到来源,先修正证据表,不要进入评分。

然后让它列出决策缺口:

基于已核对的 vendor-evidence.xlsx,补充:
1. 三份方案的关键差异;
2. 互相冲突或无法直接比较的口径;
3. 每家“未提供”的重要信息;
4. 下一轮必须追问的 5 个问题。

再生成一页 vendor-summary.md,说明各方案更适合什么情况、主要成本与风险,以及现在为何能或不能做决定。没有我确认的权重,不要给出“最佳供应商”。

只有评价标准已经由决策者确认时,才加入评分。例如:价格 30%、能力 30%、交付 20%、风险 20%。要求同时保留每项原始证据、评分理由和总分公式;“未提供”不能悄悄按零分处理,应标记为信息缺口。最后把某一项权重上下调整 10%,看排序是否改变。排序轻易反转,说明结论对权重敏感,不适合写成确定推荐。

这个案例的独立验收不是再让 Agent 读一遍自己的摘要,而是:原文件中能找到关键事实、表格公式能复算、缺失信息没有被补写成事实。

本地、Cloud、Worktree 和 Remote 不要混为一谈

做完三个案例,再把几个运行位置放回正确心智模型:

  • Work locally:任务需要电脑上的文件、应用或浏览器时使用;关闭电脑后不能指望它继续依赖本机执行。
  • Cloud:资料已上传或来自已连接服务,并且希望任务在关闭应用后继续时使用。它不会自动获得本机目录中的文件。
  • Codex · Local:直接作用于所选项目目录,适合本篇的批量文件操作,也最需要谨慎选择工作区。
  • Codex · Worktree:为 Git 仓库创建隔离工作树,适合并行代码改动;普通办公目录没有必要使用。
  • Remote:从另一台设备控制已连接主机上的任务;它使用的是那台主机的文件和权限,并不等于把文件搬进 Cloud。

Codex 中 Local、Worktree 与 Cloud 的官方区别见 Environment modes。如果界面没有某个入口,先考虑账号方案、操作系统、地区或管理员策略差异,不要根据教程中的名称强行寻找。

两个高频阻塞点

Agent 看不到文件,或请求访问更大的目录

先检查当前任务打开的是哪个文件夹,以及文件是否真的位于该目录内。不要为了省一步就开放整个主目录;回到任务列表,新建一个以正确练习目录为根的 Local 任务更安全。

生成了文件,但打不开或内容不完整

先确认实际扩展名和保存路径,再打开每个工作表、页面或章节。若当前环境不支持目标格式,退回到 CSV、Markdown 等可检查格式。格式降级没有关系,不能降级的是原始数据保留、计算口径和证据来源。

本篇小结

桌面应用真正降低的,是同时处理文件、应用和成品的操作门槛,不是验收门槛。文件整理要用清单和数量证明没有丢失;数据分析要用固定口径和手算结果核对;方案比较要能从结论返回原始页码和条款。

你现在也有了一条简单的选择原则:要直接处理本机目录并查看操作细节,用 Codex · Local;要交付表格、报告等办公成品,优先 ChatGPT Work;任务是否放到 Cloud,则取决于资料在哪里、是否需要离开电脑后继续。下一篇会按错误现象整理安装、登录、Provider、权限、项目和桌面应用的排查路径。


19 常见问题与排查手册

本课按能力区分调查 read-only 与实施 workspace-write。若 /permissions 未显示只读,退出后用 codex --sandbox read-only --ask-for-approval on-request 启动;写入前明确切换 workspace-write 并提供计划。以实际权限摘要为准。

本篇用途:遇到问题时先确定故障发生在哪一层,再做最小修复。不要一上来重装、删除配置或切到 Full Access。

这套教程最后不再增加功能,而是把前面最容易卡住的环节串成一条排查路径。Codex 的问题通常落在五层:安装与版本、认证与 Provider、配置与权限、项目与工具、任务本身。顺序查清楚,比反复换提示词更有效。

命令和界面会更新。本篇以修订时的稳定 CLI 为准;你的第一依据仍应是本机 --help 和 OpenAI 官方 Developer commands。

先留住现场:四项基础检查

除非终端已经提示 codex: command not found,否则先在普通系统终端中运行:

codex --version
codex login status
codex doctor --summary
git status --short

PowerShell 中命令相同。最后一条需要在项目目录执行;若当前不是 Git 仓库,它会直接告诉你。

这四条分别回答:

  • 终端实际调用的是哪个版本;
  • 本机是否保存了可用的 OpenAI 登录凭据;
  • 安装、配置、认证、运行时、Git 和终端等基础检查是否有警告;
  • 故障发生前,项目里是否已经有未提交改动。

当前 CLI 的 codex doctor 会生成诊断报告;--summary 只显示分组结果。先记下失败项,不要看到一条警告就立刻改多个设置。修复一项后重复同一组命令,才能知道到底是哪一步起作用。

如果问题只在某个项目出现,再补两条:

macOS、Linux 或 WSL:

pwd
git rev-parse --show-toplevel

Windows PowerShell:

Get-Location
git rev-parse --show-toplevel

两个路径应该与你准备交给 Codex 的项目一致。很多“读不到文件”“规则没生效”,根因只是从错误目录启动。

终端找不到 codex,或运行的不是预期版本

症状:codex: command not found 或“无法将 codex 识别为命令”

先确认系统能否定位可执行文件。

macOS、Linux 或 WSL:

command -v codex
type -a codex

Windows PowerShell:

Get-Command codex -All -ErrorAction SilentlyContinue

没有输出,说明当前 shell 的 PATH 中没有 Codex;出现多个路径,则可能同时装过独立安装版、npm 或 Homebrew 版本。先回忆第二篇使用的安装方式,按照当前 Codex CLI 安装页为同一种方式修复或更新,不要同时叠加另一套安装器。

重新安装或修正 PATH 后,关闭并新开一个终端,再运行:

codex --version
codex --help

两条都能输出才算恢复。只看到安装包存在,不等于当前终端能调用它。

症状:教程里的参数不存在,或 CLI 与桌面应用表现不同

先比较版本,不要直接判断功能被删除:

codex --version
codex update
codex --version

codex update 只在当前发行版支持自更新时生效;若它提示使用安装器更新,就按原安装渠道更新。更新后用目标子命令的帮助核对,例如:

codex exec --help
codex review --help

桌面应用与单独安装的 CLI 可能捆绑不同 Codex 版本,功能到达时间也可能不同,这是官方排障页明确列出的情况。不要用系统 CLI 的版本号推断桌面应用一定拥有同一功能。参见 Troubleshooting。

Windows 特别检查:你到底在 PowerShell 还是 WSL

原生 Windows 与 WSL2 是两个运行环境,可以分别拥有不同的 Codex、配置和登录状态。在 PowerShell 中用 Windows 路径,在 WSL 中用 Linux 路径;不要把 C:\project、/mnt/c/project 和 /home/user/project 当成同一个工作目录。

在 WSL 中运行:

echo "$WSL_DISTRO_NAME"
which codex

如果第一个命令有发行版名称、第二个找不到 Codex,说明你可能只在 Windows 侧安装过。当前官方文档要求使用 WSL2;新版 Linux 沙箱不再支持 WSL1。代码仓库若主要在 WSL 中使用,优先放在 ~/code/...,避免大型项目长期跨 /mnt/c 读写。详见 WSL 指南。

Codex 启动失败:先查配置,不要先删配置

症状:出现 TOML 解析错误、未知配置项,或更新后无法启动

先运行:

codex doctor --summary

然后打开用户级配置,但不要把内容整份贴到聊天或工单中:

  • macOS、Linux、WSL:~/.codex/config.toml
  • Windows:%USERPROFILE%\.codex\config.toml

高频问题包括:同一个顶层键写了两次、字符串引号未闭合、顶层键误放进某个 [table]、复制了旧版本已移除的配置。当前版本已不再支持:

approval_policy = "untrusted"

如果配置中仍有这行,删除它或改用当前支持的审批策略;项目是否可信应通过用户配置中的项目 trust_level 表达,不能把旧的 approval_policy 原样保留。官方迁移说明见 Agent approvals & security。

修改前先备份配置。macOS、Linux 或 WSL:

cp ~/.codex/config.toml ~/.codex/config.toml.before-fix

Windows PowerShell:

Copy-Item "$HOME\.codex\config.toml" "$HOME\.codex\config.toml.before-fix"

一次只改一个可疑项,保存后重跑 codex doctor --summary。如果 Codex 可以进入交互界面,再输入:

/debug-config

它会显示配置层的加载顺序和策略来源,适合排查“文件里明明这样写,实际却不是这样”的问题。Provider、认证路由和模型服务商配置必须放在用户级配置中;项目级 .codex/config.toml 不允许覆盖这些机器级设置。参见 Configuration Reference。

登录正常不等于 Provider 正常

认证排障要先分清两条链路:

  • codex login 管理 ChatGPT OAuth、OpenAI API Key 或访问令牌;
  • 自定义 Provider 通常从它在 config.toml 中声明的 env_key 读取第三方密钥。

因此,codex login status 成功,只能证明本机有 OpenAI 登录凭据,不能证明第三方中转平台的密钥和接口可用。

症状:ChatGPT 登录失败,浏览器授权后没有返回

先检查状态:

codex login status

如果未登录,重新运行:

codex login

浏览器回调受公司网络、代理或浏览器插件影响时,可以使用设备码流程:

codex login --device-auth

按这一次终端显示的地址和代码操作,不要复用旧页面。完成后重新执行 codex login status;官方命令说明中,凭据存在时该命令会以退出码 0 结束。

不要为了“重新来一遍”随意运行 codex logout。它会移除已保存的 ChatGPT 与 API Key 认证;只有确认要清除本机凭据时才使用。

症状:从第三方 Provider 切回 ChatGPT 后仍走中转平台

只重新登录不够,因为 Provider 路由仍可能指向第三方。先备份用户级 config.toml,再核对这些位置:

  1. 将顶层 model_provider 恢复为 "openai";
  2. 如果 openai_base_url 曾被改为中转地址,删除该覆盖;
  3. 删除或改掉只属于第三方平台的顶层 model,之后在 /model 中选择账号可用模型;
  4. 启动命令不要再带第三方 --profile;
  5. 自定义 [model_providers.xxx] 表可以暂时保留,只要它不再被选中。

然后运行:

codex login
codex login status
codex

进入交互界面后输入 /status,核对有效 Provider、模型和权限。第三方密钥环境变量即使仍存在,也不会自动证明当前正在使用它;最终以有效配置和 /status 为准。

症状:401、403、模型不存在或第三方接口能聊天但不会用工具

按下面顺序查,不要同时改地址、密钥和模型名:

  1. 用平台文档核对 base_url,尤其是是否应包含 /v1;
  2. 核对 env_key 写的是环境变量名,不是密钥本身;
  3. 只检查变量是否存在,不打印值;
  4. 核对准确模型 ID 与账号权限;
  5. 确认平台支持 Codex 所需的 Responses API、流式事件和工具调用,而不只是普通文本对话。

macOS、Linux 或 WSL,假设配置中的变量名是 RELAY_API_KEY:

test -n "$RELAY_API_KEY" && echo set || echo missing

Windows PowerShell:

if ($env:RELAY_API_KEY) { "set" } else { "missing" }

若变量只在某个终端设置,必须从同一终端启动 Codex。最小验证顺序是:简单回答 → 列出当前目录 → 读取一个样例文件 → 在练习目录创建一个文件。前两步成功而文件工具失败,问题更可能在接口能力或工具调用兼容性,而不是提示词。

症状:429、用量或限流错误

429 可能来自账号用量、请求速率、并发数或第三方平台余额。先停止并行 Agent 和自动重试,稍后再执行一个最小请求;然后到实际 Provider 的控制台核对限额。ChatGPT 订阅额度与第三方 API 余额不是同一件事,先用 /status 确认当前到底走哪条链路。

能对话,但读不到文件或改不了文件

症状:Codex 看不到你说的项目

在交互界面输入:

/status

核对当前目录和 writable roots,再在终端执行本篇开头的 pwd/Get-Location 与 git rev-parse --show-toplevel。如果启动目录错了,退出后进入正确项目再运行 codex,或者显式使用:

codex --cd "/绝对路径/项目目录"

桌面应用中则取消当前错误任务,重新以正确文件夹创建 Local 任务。不要为了让文件“可见”,把整个个人主目录加成可写范围。

症状:Codex 一直请求批准

审批策略与沙箱不是一回事:沙箱决定技术上能访问哪里,审批策略决定何时停下来问你。输入 /permissions 和 /status,检查当前是否为 Read Only、任务是否越过工作区,以及是否需要网络。

日常仓库修改通常使用 Auto,即 workspace-write 加 on-request。下面这些动作仍可能触发审批:

  • 写工作区之外的路径;
  • 默认关闭时访问命令网络;
  • 安装依赖或启动外部应用;
  • 调用带副作用的 App 或 MCP 工具。

不要用 Full Access 消灭所有提示。先看请求中的命令、目标路径和原因;如果任务确实只需仓库内部,就让 Codex 改成不越界的方案。官方权限模型见 Agent approvals & security。

症状:已经是 Workspace Write,某些目录仍写不了

先看准确错误路径。当前默认策略会继续保护工作区中的 .git、.agents 和 .codex 等敏感目录;操作系统权限、文件锁定和组织策略也可能进一步收紧。不要把“工作区可写”理解成目录内每个位置都无条件可写。

如果需要创建 Skill、修改配置或执行 Git 内部操作,应让对应受控能力发起精确审批,而不是把整个会话升级到 Full Access。修复后用 git status --short 或实际文件列表验证变化范围。

症状:联网失败,但网页搜索还能用;或反过来

本地命令的网络访问与 Codex 的网页搜索是两条不同通道。workspace-write 默认不会让 shell 命令自由联网;网页搜索可能仍使用缓存索引。先判断失败的是 curl、包管理器等本地命令,还是 Web Search 工具,再检查对应设置,不能用其中一项成功证明另一项也已开放。

项目规则没生效,或结果越做越偏

症状:Codex 没有遵守 AGENTS.md

先确认文件名、目录与会话时机:

  • 根规则应为项目路径上的 AGENTS.md;
  • 更近目录中的 AGENTS.md 或 AGENTS.override.md 可能追加或覆盖规则;
  • 你必须从正确项目目录启动;
  • 新增或修改规则后,最好开一个新会话验证。

在交互界面运行 /debug-config,查看配置和项目层来源;再让新会话只读复述测试命令、数据边界和完成标准。能复述后,还要用一个小任务观察它是否真的按规则执行。

症状:Codex 一上来大范围重构

立即在当前回合输入转向指令:

暂停扩大修改范围。先列出当前已经变更的文件和原因,不再继续编辑。

请回到最小目标:先复现问题,给出根因证据和最小修改计划,等我确认后再改。不要提交、推送或重构无关代码。

随后输入 /diff,并在终端运行:

git status --short
git diff --stat

不要直接要求“全部恢复”,因为工作树里可能混有你原来的未提交内容。先分清哪些变化属于本轮,再决定逐项保留或撤回。

症状:Codex 说测试通过,但结果仍不可信

要求它给出真实命令、工作目录、退出码、测试数量与关键输出。然后自己在普通终端重跑同一条命令,并检查 git diff。至少区分四件事:

  • Codex 进程是否正常结束;
  • 目标测试是否真的运行;
  • 完整测试是否回归通过;
  • 实际 Diff 是否只包含预期修改。

“写了测试文件”不等于运行过,“退出码 0”也不等于测试覆盖了你关心的行为。

症状:会话很长,反复遗忘已确认决定

先把当前状态写入仓库中的 STATUS.md、任务计划或其他项目文件,再使用 /compact;或者新建会话,把目标、已完成项、测试结果、Git 状态和下一步一起交给它。不要只说“继续刚才的任务”,也不要让一个会话长期混合多个无关目标。

Skill、Plugin、MCP 或 App 看不见

先分清你在找哪一层:Skill 是本地流程说明,Plugin 是可安装能力包,MCP 是工具连接,App/connector 是用户连接的外部服务。把它们都叫“插件”,会让排查入口错位。

Skill 刚创建,但 /skills 中没有

仓库 Skill 应位于:

.agents/skills/<skill-name>/SKILL.md

检查 SKILL.md 的 YAML frontmatter 是否包含准确的 name 和能说明触发场景的 description,然后从项目根目录开启新会话,再输入 /skills。若仍没有,确认当前会话不是在另一个工作区,以及父目录或组织策略没有限制本地 Skill。

Plugin 已安装,但当前会话中不可用

先在普通终端查看安装状态:

codex plugin list

再在交互界面输入 /plugins,确认插件是否启用,以及当前安装包到底提供了哪些 Skills、MCP 工具或 Apps。安装状态不等于每项能力都适用于当前平台和账号;刚安装或切换启用状态后,新开会话再测一次。

MCP 显示已配置,但工具调用失败

从“配置存在”逐层验证到“工具可调用”:

以下为参数模板,执行前先将尖括号占位符替换为实际值:

codex mcp list
codex mcp get <服务器名称>

然后在交互界面输入:

/mcp verbose

依次检查:STDIO 启动命令是否存在、所需环境变量是否进入 Codex 进程、远程 URL 是否可达、OAuth 是否完成、服务器是否真的暴露了预期工具。远程服务器需要重新认证时,使用:

以下为参数模板,执行前先将尖括号占位符替换为实际值:

codex mcp login <服务器名称>

先调用一个最小只读工具,确认返回了真实数据,再测试写操作。不要用高权限写入调用来证明“连接成功”。官方 MCP 命令与配置见 Model Context Protocol。

找不到某个 App,或连接后没有权限

在交互界面输入 /apps,它用于浏览可用 App 并把 App 引用插入提示词。若列表中没有目标服务,可能是插件未安装、账号/地区不提供、组织管理员禁用,或当前 Surface 不支持;这不是靠重启 MCP 就一定能解决的问题。

连接成功后仍要区分读取权限和写入权限。先完成一次只读查询,再执行任何发消息、改记录或外部发布动作。

codex exec 与 CI 的问题

症状:codex exec 只分析,没有修改文件

先看本机帮助:

codex exec --help

需要写入且目录可信时,显式设置:

codex exec --sandbox workspace-write "<你的任务>"

再用 git status --short 和测试验证。不要因为无人值守就使用 --dangerously-bypass-approvals-and-sandbox;非交互任务更需要最小工作目录和明确边界。

症状:提示不是 Git 仓库,或处理了错误目录

先执行:

git rev-parse --show-toplevel

不在正确目录时,先进入仓库,或显式指定:

codex exec --cd "/绝对路径/仓库" --sandbox read-only "<只读任务>"

--skip-git-repo-check 只适合你明确了解的可信非仓库目录;它绕过的是检查,不会让目录自动变安全。

症状:--json 生成的文件无法按普通 JSON 解析

--json 输出的是 JSONL:每行一个独立事件,不是外层数组。逐行解析,或只需要最终回复时使用:

codex exec --output-last-message result.md --sandbox read-only "<任务>"

若需要稳定字段,再配合 --output-schema。无论哪种格式,CLI 退出码只说明 Codex 运行是否完成;测试、扫描或业务检查是否通过,必须保留它们自己的状态字段或退出码。

症状:本地成功,CI 中却未登录、读不到 Key 或表现不同

CI 是新的非交互环境,不会自动继承你电脑上的登录和 shell 配置。检查:

  • codex login status 在 CI 是否成功;
  • API Key 是否只注入运行 Codex 的步骤;
  • 工作目录和 checkout 是否正确;
  • 脚本是否依赖本机 profile、未提交文件或用户级 config.toml;
  • 外部贡献的代码是否可能读取 Secret。

不要把密钥写入命令参数、仓库、日志或构建产物。失败时先打印变量是否存在,绝不打印变量值。

桌面应用的问题

症状:打开了项目,但文件、分支或 Diff 不对

先确认任务目标是 Local、Worktree 还是 Cloud。Local 直接使用本机项目;Worktree 是另一个 Git 工作目录;Cloud 使用远端环境。选错目标时取消当前运行,回到正确项目重新建任务,不要在错误环境里补路径凑合。

Review 面板还可能显示项目中原本就存在的 Git 变化,而不只显示 Codex 本轮修改。想看本轮时切到 Last turn;想看真实工作树则用 git status --short 和 git diff 复核。

症状:桌面任务一直不动

按顺序看:

  1. 当前回合是否在等待审批或你的回答;
  2. 集成终端能否运行 pwd 或 git status;
  3. 当前任务是否仍在正确目录;
  4. 是否可以取消后用更小、更明确的提示新开任务。

终端面板卡住时,关闭后重新打开,再运行一个基础命令。等待其他活跃任务结束后重启应用,通常比强制终止所有任务更安全。官方恢复步骤见 Troubleshooting。

症状:ChatGPT 看不到或无法操作桌面应用

这属于 Computer Use 权限,不是 Codex 工作区权限。macOS 需要在“系统设置 → 隐私与安全性”中检查屏幕录制与辅助功能;Windows 要确保目标应用显示在当前活动桌面。ChatGPT 内部还会单独询问是否允许使用某个 App。

系统权限、App 允许列表、文件沙箱是三层不同边界:能看见窗口不等于能写项目文件,允许一个 App 也不等于获得全盘访问。参见 Computer Use。

Windows 桌面应用找不到 WSL 项目

添加项目时在文件选择器中输入 \\wsl$\,再进入对应发行版。如果希望 Agent 本身在 WSL2 中运行,到 Settings 切换 Agent environment,并重启应用;集成终端使用 PowerShell 还是 WSL 是另一项独立设置。具体路径与限制见 Windows desktop app。

仍未解决时,生成一份可复现的故障报告

先保存诊断信息:

codex doctor --json > codex-doctor.json

--json 会生成脱敏的机器可读报告,但分享前仍要亲自检查文件,删除个人路径、项目名、内部地址或其他不希望外传的内容。日志和会话记录也可能包含提示词、文件路径与工具输出,不能未经检查直接上传。

提交问题时使用下面的模板:

操作系统与版本:
运行环境:macOS / Windows 原生 / WSL2 / Linux
Codex 入口:CLI / ChatGPT 桌面应用 / IDE / codex exec
Codex 版本:
安装方式:独立安装器 / npm / Homebrew / 其他
当前目录与是否为 Git 仓库:
认证方式:ChatGPT / OpenAI API Key / 自定义 Provider(不要附密钥)
权限模式与沙箱:

最小复现步骤:
1.
2.
3.

预期结果:
实际结果:
完整错误文本(已脱敏):
codex doctor 中失败的检查:
已经尝试过的单项修复:

好的故障报告不需要堆满所有配置,而要让别人能在同一入口、同一目录和同一权限模式下复现。不要附 API Key、访问令牌、客户资料、完整环境变量或未经审查的会话记录。

本篇小结

排查 Codex 时,先确认“哪一层坏了”:命令能不能找到,版本是否一致,登录和 Provider 是否走对,配置是否被正确加载,工作区与权限是否覆盖目标,工具连接是否真的完成最小只读调用,最后才判断是不是提示词或模型表现问题。

到这里,这套教程的主线完成了:你不仅能用 Codex 完成从 TaskFlow 开发到发布准备的完整流程,也能把同样的方法迁移到桌面办公任务,并在出错时保留现场、缩小范围、独立验证修复结果。以后遇到新功能,先用本机帮助和官方文档确认当前行为,再把它放进一个可以验收的小任务里。


20 进阶学习

用Codex完成第一个项目之后 怎样进一步开发Agent应用

跟着 Codex 知识库完成 TaskFlow,你已经练习过需求拆解、代码修改、问题复现和验收,也开始用项目说明、权限设置与任务记录管理开发过程。

接下来,可以把注意力从一次功能实现扩展到应用本身:如果要让一个 Agent 长期帮助用户处理任务,它需要哪些工具、怎样保存进度,又如何证明结果可靠?

先让一次代码修改有清楚的依据

不妨给 TaskFlow 增加一个任务筛选功能。提交给 Codex 之前,先整理下面四项,让它的修改和你的验收围绕同一套约定展开。

原文图片

例如,约定只增加状态筛选,沿用现有页面样式;筛选后仍允许修改任务;没有匹配结果时显示空状态;刷新后按项目原有方式保存数据。随后检查正常输入、空列表和刷新场景,而不只看页面是否出现了一个按钮。

如果结果不符合预期,先复现问题,再提供操作步骤和实际结果。这些知识库中的练习,能帮助你更稳定地组织 AI 辅助开发,也让每次修改更容易检查和接手。

把开发经验用到Agent应用里

当你想做一个能读取代码库、运行测试并定位问题的助手,项目就会出现新的设计要求。可以先沿着下面四项拆解。

原文图片

读取文件的工具需要约定参数与返回值;长任务需要保存已完成的步骤;测试失败后要决定重试、调整计划还是请求帮助;完成后还要检查代码质量、工具调用记录和运行成本。

这里的难点,是把模型、工具和任务过程连接起来。可以从一个小任务开始:只允许助手读取指定目录,生成修改建议,由人审核后执行。待验证清楚,再逐步增加测试和修改能力。

Codex 可以继续帮助你实现这些模块。你也需要理解模块为什么这样设计,才能在发生超时、信息遗漏或重复执行时,找到问题所在。

从使用编码助手 到构建自己的Agent

《AI Agent 全栈工程师训练营》可以承接这一步学习。课程围绕工具调用、RAG、Agent Loop、上下文管理、评测和生产部署,安排多项工程实践。

其中,工具调用基础设施项目涉及参数校验、权限与风险分级、超时重试和调用追踪;Codebase Agent 项目练习规划、文件操作、测试与失败修复,以及人工确认和任务检查点。

后续的 Codebase RAG 与 Agent 实践,会加入代码检索、项目记忆和任务恢复;多 Agent 与评测项目,则练习协作、基准管理和版本比较。这些内容能让你把知识库中积累的项目经验,进一步用于 Agent 应用的开发与验证。

如果你希望从用 Codex 完成功能,走向独立组织一套 Agent 应用,可以带着自己的代码库或任务场景,对照课程项目判断学习重点。

选一个任务 作为下一步实践

先写清你希望 Agent 完成的一件事,再列出它需要读取什么、调用什么、交付什么,以及什么时候停止。一个范围明确的任务,更容易成为完整的实践项目。

想了解《AI Agent 全栈工程师训练营》的内容和学习要求,可以通过下方入口联系学习顾问,备注 「Codex 到 Agent 开发」,说明自己的基础和想做的项目。

原文图片


21 附录1-Codex_CLI常用命令速查表

具体参数以当前版本的 codex --help 和子命令帮助为准。

安装与版本

目的 命令
查看版本 codex --version
查看帮助 codex --help
升级 npm 安装版本 npm install -g @openai/codex@latest
启动交互式 CLI codex
带初始任务启动 codex "解释这个项目并告诉我如何运行测试"

目录、沙箱与审批

目的 命令
工作区可写 codex --sandbox workspace-write
按需审批 codex --ask-for-approval on-request
增加一个额外目录 codex --add-dir /specific/path
指定工作目录 codex -C /path/to/project

日常开发常用组合:

codex --sandbox workspace-write --ask-for-approval on-request

不要把 Full Access 设成习惯性默认值。

恢复会话

目的 命令
选择并恢复历史会话 codex resume
恢复最近会话 codex resume --last
从历史会话分支 codex fork

非交互模式

目的 命令
一次性执行 codex exec "<任务>"
临时会话 codex exec --ephemeral "<任务>"
允许写工作区 codex exec --sandbox workspace-write "<任务>"
JSONL 事件 codex exec --json "<任务>"
最终消息写入文件 codex exec -o result.md "<任务>"
用 Schema 约束结果 codex exec --output-schema schema.json -o result.json "<任务>"
继续最近一次执行 codex exec resume --last "<后续任务>"
非 Git 临时目录 codex exec --skip-git-repo-check "<任务>"

交互快捷操作

操作 作用
输入 @ 搜索并引用工作区文件
输入 !命令 在权限范围内运行本地 shell 命令
Enter 在运行过程中补充或转向当前任务
Tab 把消息排到当前工作之后
Ctrl+C 中止当前运行或退出,视当前状态而定

常见组合

只读理解陌生项目:

codex exec "只读分析项目入口、测试命令和主要风险,不修改文件。"

允许在仓库内完成一个修复:

codex --sandbox workspace-write --ask-for-approval on-request

输出结构化健康报告:

codex exec --output-schema schema.json -o health.json "检查项目健康状态,不修改文件。"

22 附录2-常用斜杠命令速查表

在 Codex CLI 输入 / 可查看当前版本真正支持的命令;界面与命令可能随版本更新。

会话与任务

命令 用途
/new 开始一个新任务
/rename 给当前任务改名
/resume 恢复历史任务
/fork 基于当前历史创建分支任务
/side 开启不打断主线的旁支讨论
/compact 压缩长上下文,保留继续工作所需信息
/status 查看目录、模型、权限和上下文状态
/ps 查看正在运行的进程或任务
/stop 停止当前会话启动的后台终端;不等于暂停 Goal 或取消当前模型回合
/exit 退出 CLI

规划与目标

命令 用途
/plan 进入规划模式,先设计再实施
/goal <目标> 创建或设置长期目标
/goal 查看目标状态
/goal edit 编辑当前目标
/goal pause 暂停目标
/goal resume 恢复目标
/goal clear 清除目标

项目与审查

命令 用途
/init 为当前项目生成或建议 Agent 说明
/mention <文件> 把文件加入当前上下文
/diff 查看本轮或工作区变化
/review 对 Git 变更做代码审查
/debug-config 检查配置来源与最终值
/permissions 查看或调整当前权限模式

扩展能力

命令 用途
/skills 查看和调用 Skills
/plugins 查看插件
/apps 查看或连接 Apps
/mcp 查看 MCP 连接和工具
/mcp verbose 查看更详细的 MCP 状态
/agent 查看或切换 Agent
/subagents 查看子 Agent(若当前版本提供)

三个容易混淆的命令

  • /new:从空白上下文开始另一件事;
  • /fork:带着共同历史探索另一条方案;
  • /side:临时调查旁支问题,之后回到主线。

如果只是补充当前任务的新要求,直接输入消息即可,不必新建会话。

需要暂停持续目标时用 /goal pause;中断当前回合按界面显示的取消快捷键操作,并检查任务状态。三者分别验收,不互相替代。


23 附录3-高质量任务描述模板

提示词不需要写得像合同,但至少要让 Codex知道目标、范围、约束和怎样算完成。

实现新功能

目标:<用户最终能做什么>

当前背景:
- <相关文件或现有行为>
- <为什么要做>

需求:
1. <行为一>
2. <行为二>

不在范围内:
- <本次不做的事情>

约束:
- <技术、依赖、兼容、安全要求>

验收:
- <可观察结果>
- <必须运行的测试>

请先检查现状并列出歧义,给出计划;确认后再实施。完成时报告修改文件、验证证据和剩余限制。

修复缺陷

现象:<用户看见什么>
复现步骤:<怎样触发>
预期结果:<正确行为>
影响范围:<已知用户或数据>

请先不要修改。先用最小输入复现,记录命令、实际结果和根因证据;补一个会失败的回归测试。确认后做最小修复,运行局部测试、完整测试并审查 Diff。

理解陌生项目

请只读调查当前仓库,不修改文件。

输出:
1. 项目目标和主要入口;
2. 关键目录与数据流;
3. 安装、启动和测试命令;
4. 配置、外部依赖和敏感边界;
5. 当前 Git 状态与主要风险;
6. 仍然无法确认的问题。

每个结论引用具体文件或实际命令结果。

代码审查

请审查 <当前 Diff / 分支 / 提交范围>,不要直接修改。

优先发现:正确性、数据安全、兼容性、并发、错误处理、测试失真和文档不一致。忽略纯格式偏好。

每个发现给出:严重程度、文件位置、触发条件、用户影响、证据和建议验证方式。没有发现时明确说明审查范围和仍未覆盖的风险。

重构

重构目标:<要降低的具体风险>
必须保持:<接口、输出、数据格式、性能边界>
允许修改:<文件或模块>
不允许修改:<范围外内容>

请先确认现有测试能保护行为;若不足先补特征测试。重构过程中不增加新功能。完成后运行完整测试,比较关键输入输出,并展示 Diff。

文件整理

请先只读盘点 <目录>,不要移动、重命名、覆盖或删除。

先输出文件清单、分类依据、不确定项、建议目录结构、移动预览、冲突处理和回滚方案。确认后再执行。执行前生成原路径到目标路径的清单,完成后核对文件总数和失败项。

数据分析

请先检查 <文件> 的字段、范围、空值、重复、异常值和口径,不要马上得出业务结论。

先说明清洗规则和指标公式,等我确认后再计算。最终结论必须附数据表或计算依据;区分事实、推断和待验证问题,不把相关性写成因果关系。

发布检查

请对 <版本> 做发布前检查,不提交、不打标签、不推送、不发布。

检查:Git 状态、完整测试、关键手动路径、兼容性、README、CHANGELOG、密钥和运行数据。报告分为通过、阻塞和提醒,并记录实际命令、退出码和证据。

中途纠偏

暂停当前修改。你已经偏离了 <原范围>。

请先说明已经改了哪些文件、哪些改动与目标无关、怎样在不影响我原有工作的前提下收缩范围。暂时不要继续写入。

24 附录4-配置文件示例

配置字段会随 Codex 版本更新。修改前先备份,修改后用 /debug-config 检查。密钥只放环境变量或安全凭据系统,不写入 TOML。

配置文件位置

  • macOS、Linux、WSL2:~/.codex/config.toml
  • Windows:%USERPROFILE%\.codex\config.toml
  • 项目级配置:<项目>/.codex/config.toml

项目配置只应放适合整个仓库共享的安全默认值。Provider 路由和认证应保留在用户级配置中。

默认使用 OpenAI

用户级配置:

model_provider = "openai"

登录方式和可用模型以当前账户与 CLI 提示为准。

只修改 OpenAI 网关地址

仅当网关继续使用 OpenAI 身份验证语义时:

model_provider = "openai"
openai_base_url = "https://gateway.example.com/v1"

如果网关发放自己的 Key,应定义自定义 Provider,不要混用认证方式。

自定义 Provider

先在终端设置环境变量。

macOS、Linux、WSL2:

export COMPANY_MODEL_API_KEY="<your-key>"

Windows PowerShell,仅当前窗口:

$env:COMPANY_MODEL_API_KEY = "<your-key>"

用户级配置:

model_provider = "company"
model = "provider-model-id"

[model_providers.company]
name = "Company Gateway"
base_url = "https://gateway.example.com/v1"
env_key = "COMPANY_MODEL_API_KEY"
wire_api = "responses"

平台若只兼容其他协议,wire_api 必须按其文档和 Codex 当前支持范围设置,不能仅凭 URL 猜测。

为第三方 Provider 创建独立 Profile

默认 ~/.codex/config.toml 保持:

model_provider = "openai"

[model_providers.relay]
name = "My Relay"
base_url = "https://relay.example.com/v1"
env_key = "RELAY_API_KEY"
wire_api = "responses"

另建 ~/.codex/relay.config.toml:

model_provider = "relay"
model = "provider-model-id"

使用:

codex --profile relay

退出后运行普通 codex,即可回到默认 OpenAI Provider。

本地模型

命令行:

codex --oss --local-provider ollama

或:

codex --oss --local-provider lmstudio

配置默认本地 Provider:

oss_provider = "ollama"

本地模型是否适合 Agent 任务,取决于上下文、工具调用和机器资源,不要只用聊天效果判断。

项目级安全默认值

<项目>/.codex/config.toml:

approval_policy = "on-request"
sandbox_mode = "workspace-write"

项目级配置只有在项目受信任时才会加载。不要在陌生仓库中盲目接受高权限设置。

最小 AGENTS.md

# Project guide

## Commands
- Test: `<完整测试命令>`
- Lint: `<检查命令>`

## Constraints
- Do not install dependencies unless the task requires it.
- Tests must not access production data.
- Preserve backward compatibility unless explicitly changed.
- Do not commit secrets, generated data, or personal paths.

## Definition of done
- Requested behavior is implemented.
- Focused and full tests pass.
- User-facing docs match actual behavior.
- Final response lists changes, validation, and limitations.

配置排错顺序

  1. codex --version;
  2. 检查 TOML 是否有重复键、引号或表名错误;
  3. 确认环境变量名与 env_key 完全一致;
  4. 运行 /debug-config;
  5. 用 /status 核对最终 Provider 和模型;
  6. 对 401、403、404、429 分别检查认证、权限、地址和限流。

25 附录5-安全与验收清单

开始任务前

  • 当前目录是正确项目,不是主目录或磁盘根目录
  • git status 已检查,知道哪些改动原本就存在
  • 重要文件已有版本控制或备份
  • 任务目标、范围外事项和完成标准清楚
  • 使用完成任务所需的最小权限
  • 不需要联网时,网络保持关闭
  • 密钥、客户数据和生产数据不进入提示词

批准命令前

  • 看清完整命令,不只看解释
  • 读写路径属于本次任务范围
  • 网络目标和用途明确
  • 没有递归删除、覆盖或大范围移动风险
  • 安装的依赖来源可信且确有必要
  • 不会把凭据写入日志或构建产物
  • 高风险动作有预览和回滚办法

代码实现验收

  • 修改范围与任务一致
  • 新行为有测试
  • 缺陷修复的回归测试曾在修复前失败
  • 错误输入和边界情况有覆盖
  • 先跑局部测试,再跑完整测试
  • 实际入口至少手动运行一次
  • 旧数据或旧接口兼容性已验证
  • README 与真实命令一致
  • /diff 中没有无关重构

数据与文件操作验收

  • 操作前有原文件清单
  • 没有直接处理唯一原件
  • 重名和覆盖策略明确
  • 无法判断的文件保留在待确认区
  • 执行前生成移动或修改预览
  • 执行后文件数量与完整性已核对
  • 记录了原路径、目标路径和失败项
  • 删除操作经过单独确认

数据分析验收

  • 字段、行数、日期范围已确认
  • 空值、重复和异常值处理口径明确
  • 指标公式与单位明确
  • 至少抽查一组原始数据和计算结果
  • 图表标题、单位、时间范围完整
  • 事实、推断和建议清楚区分
  • 没有把相关性表述成因果关系
  • 引用数字能追溯到数据范围

发布前

  • 工作区状态符合预期
  • 完整测试通过并记录命令与结果
  • 安装、升级和核心路径实际验证
  • 旧版本数据或配置可兼容
  • README、CHANGELOG 和实现一致
  • 没有 .env、API Key、令牌和客户数据
  • 没有运行数据、缓存、临时报告和个人绝对路径
  • 已知限制已记录
  • 提交、标签、推送和发布由人明确确认

Agent 最终汇报应包含

  • 修改了哪些文件
  • 为什么修改
  • 实际执行了哪些验证
  • 测试数量、结果或退出码
  • 哪些内容没有验证
  • 仍然存在什么风险或限制
  • 是否执行了外部写入、提交或发布

26 附录6-不同操作系统的环境差异

常用命令对照

目的 macOS / Linux / WSL2 Windows PowerShell
进入目录 cd ~/codex-course/taskflow Set-Location "$HOME\codex-course\taskflow"
创建目录 mkdir -p path New-Item -ItemType Directory -Force path
查看文件 ls -la Get-ChildItem -Force
Python python3 py 或 python
设置当前会话环境变量 export NAME="value" $env:NAME = "value"
删除当前会话环境变量 unset NAME Remove-Item Env:NAME
用户目录 $HOME 或 ~ $HOME / $env:USERPROFILE
路径分隔符 / \,PowerShell 多数场景也接受 /

Python 启动器

macOS 和多数 Linux 发行版使用:

python3 --version
python3 -m unittest discover -s tests -v

Windows 常见:

py --version
py -m unittest discover -s tests -v

如果 python、python3 和 py 指向不同版本,优先选择明确满足项目要求的那个,并把真实命令写进 AGENTS.md。

路径与引号

路径包含空格时始终加引号:

cd "/Users/you/My Projects/taskflow"
Set-Location "C:\Users\you\My Projects\taskflow"

教程中的 ~/... 不能原样复制到 CMD。PowerShell 可使用 $HOME,WSL2 使用 Linux 风格路径。

环境变量

只在当前终端设置密钥更适合练习,关闭窗口后自动失效。

macOS、Linux、WSL2:

export PROVIDER_API_KEY="<your-key>"

Windows PowerShell:

$env:PROVIDER_API_KEY = "<your-key>"

验证变量是否存在时不要把完整值打印出来。可以只检查是否为空。

换行符与 Git

Windows 常见 CRLF,macOS/Linux 常见 LF。团队应通过 .gitattributes 或 Git 配置统一策略,避免一次修改出现整文件换行变化。

审查时若 Diff 几乎每行都变化,先检查换行符,不要立即提交。

文件名大小写

Linux 通常区分大小写;默认的 Windows 和 macOS 文件系统往往不区分。README.md 与 readme.md 在不同系统上的行为可能不同。仓库中文件引用要保持精确大小写。

权限与锁定

Linux/macOS 可能遇到执行权限;Windows 可能遇到文件被编辑器、Excel 或杀毒软件锁定。先关闭占用程序,再重试,不要直接用管理员权限掩盖原因。

脚本需要可执行权限时:

chmod +x script.sh

但 Python 脚本通常可以直接通过 python3 script.py 运行,无需修改权限。

WSL2 的边界

  • WSL2 中使用 Linux 版 Node、Python、Git 和 Codex;
  • Windows 文件位于 /mnt/c/...;
  • 大量小文件项目优先放在 ~/...,性能通常更稳定;
  • 不要让 Windows Git 与 WSL Git 同时修改同一工作区;
  • 浏览器登录可能在 Windows 浏览器中打开,按终端提示完成回调。

命令不可用时的排查顺序

  1. 查看当前 shell;
  2. 查看程序版本;
  3. 用系统自己的命令查找程序路径;
  4. 重新打开终端;
  5. 核对安装目录是否进入 PATH;
  6. 避免把另一操作系统的命令直接照搬。

27 附录7-后续学习资源

教程帮助你跑通主线,下面这些官方资料适合在实际使用中按需查阅。

快速开始与桌面客户端

提示词与工作方法

项目配置

权限与安全

扩展能力

  • Build Skills:创建可复用 Skill
  • Plugins:插件的发现、安装与管理
  • MCP:连接外部工具和数据源
  • Subagents:多 Agent 的配置与使用

自动化

推荐学习顺序

学完教程后,不必从头通读所有文档。可以按自己的下一步选择:

  • 想稳定做项目:先看 AGENTS.md、Permissions、Best practices;
  • 想连接第三方模型:看 Basic/Advanced configuration;
  • 想沉淀工作流:看 Build Skills;
  • 想接内部系统:看 MCP 与 Plugins;
  • 想进入 CI:看 Non-interactive mode;
  • 想提高并行效率:看 Subagents。

产品更新较快。遇到教程与当前界面不一致时,以 codex --help、CLI 内命令列表和上述官方文档为准。