1. 为什么 Codex CLI 的 /goal 值得折腾:无人值守开发到底解决什么问题
Codex CLI 是 OpenAI 官方开源的命令行编码代理,跑在终端里,能读写你本地的代码文件、执行命令、跑测试。而/goal是它 0.128.0 版本引入的一个命令,做的事情很直接:你给它一个目标,它自己拆解、自己执行、自己验证,中途不需要你一句一句地喂指令。这就是所谓的无人值守开发——你下班前把目标写清楚,第二天回来看进度报告。
我第一次接触这个功能的时候,直觉是「这不就是把 prompt 写长一点吗」。实际跑下来发现差别很大。普通对话模式下,Codex 每完成一步都会停下来等你确认,你不在它就卡住了。而/goal模式会持续自主推进,直到满足你定义的完成条件,或者触发你设定的停止条件。它内部有一个目标审计机制,会把你的目标映射成可执行的清单,映射不了的虚词会被拒绝。
适合谁用?三类人最合适。第一类是手上有明确边界任务的人,比如「把某个数据文件扩充到指定条数并保证校验通过」这种,目标清晰、验证方式明确。第二类是做规格驱动开发的人,先写规格文档,再让代理按规格实现。第三类是想把重复性编码工作批量外包给代理的人,比如批量补单元测试、批量重构某个模块。
不适合谁?需求还在脑子里没想清楚的人。/goal不会帮你澄清需求,它只会忠实执行你写下的东西。你写得模糊,它跑出来的一定偏。所以这篇文章的重点,一半在配置,一半在怎么把目标写对。
整条链路要跑通,需要三样东西:Codex CLI 本体、一个稳定的模型入口、以及正确的配置文件。下面从环境准备开始,一步步来。
2. 前置准备:Codex CLI 安装与 TaoToken 统一 Key 接入配置
先说版本。/goal需要 Codex CLI ≥ 0.128.0,先确认:
codex --version如果版本不够,升级:
npm update -g @openai/codexNode.js 建议用 LTS 版本,装完重开终端,跑node -v和npm -v确认基础环境正常。
接下来是模型入口。Codex CLI 需要一个 OpenAI 兼容的接口来驱动。如果你已经有可用的 provider,这段可以跳过。如果你现在卡在「没有现成入口、想先把 Codex 跑起来」这一步,可以用 TaoToken 的统一 Key 通道先把环境搭起来。它的价值在于省事:一个 Key 走通,不用先折腾多家供应商的格式差异,后面再替换成你自己的正式方案也不影响。
TaoToken 的官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 根地址是 https://taotoken.net/api 。注意这两个地址的用法区别,后面配置里会体现。
操作流程是这样的:登录后台,新建一个 API Key,完整复制保存。然后打开 Codex 的配置文件。Codex CLI 的配置分两处,一处是~/.codex/config.toml,一处是~/.codex/auth.json。前者管 provider 和功能开关,后者管凭证。
先看~/.codex/config.toml里 provider 部分该怎么写:
model_provider = "taotoken" model = "gpt-5-codex" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api/v1" wire_api = "responses"这里有个容易踩的坑:OpenAI 兼容客户端一般填带/v1的地址,所以base_url写成https://taotoken.net/api/v1。但如果你用的是 Claude Code 那类客户端,填根地址https://taotoken.net/api,不要带/v1。两者不要混。
然后是凭证文件~/.codex/auth.json:
{ "OPENAI_API_KEY": "sk-你的TaoToken完整Key" }把后台复制的完整 Key 填进去。注意 Key 前后不要有空格,不要被编辑器自动换行截断。这两个文件改完,重启终端。
如果你用的是 Codex 的 auth.json 方式而不是 config.toml 里的 bearer token,那 Base URL、Key、Model ID 这三件套要对应上:Base URL 是https://taotoken.net/api/v1,Key 是后台那串,Model ID 填你实际要用的模型名。三件套缺一不可,任何一个对不上都会在启动时报错。
配置完成后,启动 codex,发一句「你好,只回复连接成功四个字」做连通性测试。能正常回复,说明入口通了。这一步别省,后面/goal跑长任务时如果入口不稳,中途断流很难排查。
3. 可复制配置:启用 /goal 与五段式目标模板
/goal默认是关闭的,需要手动开。编辑~/.codex/config.toml,加上功能开关:
[features] goals = true collaboration_modes = truegoals = true是启用/goal,collaboration_modes = true是启用/plan协作模式,两个一起开方便后面配合用。保存退出,关掉当前终端重新打开 Codex。
验证是否启用成功:输入/,在补全列表里能看到/goal就对了。或者直接输入/goal回车,显示「暂无目标」也是成功。
接下来是最关键的部分——写目标。/goal的质量几乎完全取决于目标写得好不好。推荐用五段式模板:
/goal <一句话描述目标> Scope: <作用范围,其他不要碰> Constraints: - <硬性约束 1> - <硬性约束 2> Done when: 1. <可验证的产物 1,引用具体文件或命令> 2. <可验证的产物 2> Stop if: - <停止条件 1> - <停止条件 2> Use a token budget of <N> tokens for this goal.五个段落各有作用。Scope划定边界,防止代理乱改文件。Constraints是硬性约束,比如不许新增依赖、schema 不能变。Done when是完成条件,每一条都要能跑一个命令验证。Stop if是停止条件,机械可识别,比如「需要修改范围外文件就停」。最后一行 token budget 是软停止,防止跑飞。
发之前过一遍检查清单:目标能不能被映射成清单?有没有「全部」「所有」「彻底」「improve」这种虚词?有就换成具体数字。Done when每一条都能跑命令验证吗?Stop if是机械可识别的吗?Token budget 设了吗?
一个具体例子:
/goal 把 src/data/words.json 里的词库扩展到 1000 个唯一词条。 Scope: 只改 src/data/words.json,其他文件不动。 Constraints: - 词条 schema 保持不变 - 不允许重复(以 word 字段去重) - 只用真实常见英语单词 Done when: 1. words.json 包含恰好 1000 个唯一词条 2. tools/validate.js 校验通过 3. 终端输出最终词条数和文件大小 Stop if: - 需要修改 words.json 以外的文件 - 需要新增 npm 依赖 - schema 校验失败超过 3 次 Use a token budget of 80000 tokens.这个目标里没有虚词,每条完成条件都能验证,停止条件机械可识别。粘贴完整目标,回车,Codex 开始自主推进。你可以去做别的事。
随时查看进度用不带参数的/goal,会显示目标内容、耗时、token 用量。生命周期控制:/goal pause暂停,/goal resume恢复,/goal clear中止。跨会话恢复用codex resume <session-id>。
4. 验证请求与成功结果:跑通一个完整 /goal 任务
配置和模板都齐了,现在跑一个完整任务验证链路。我用一个真实场景:给一个已有的工具函数文件补单元测试。
第一步,先随便发一句话建立会话,比如「看一下当前项目结构」。这一步很重要,因为如果第一条消息就发/goal,resume 列表里会找不到这个会话。
第二步,下目标:
/goal 给 src/utils/format.js 里的所有导出函数补单元测试。 Scope: 只新增 test/format.test.js,不改 src/utils/format.js。 Constraints: - 用项目现有的测试框架,不新增依赖 - 每个导出函数至少 3 个用例,覆盖正常输入和边界输入 - 测试文件风格与 test/ 下现有文件保持一致 Done when: 1. test/format.test.js 存在且包含所有导出函数的测试 2. npm test 退出码为 0 3. 终端输出测试通过数量和覆盖率摘要 Stop if: - 需要修改 src/utils/format.js - 需要 npm install 新依赖 - 测试连续失败超过 5 次 Use a token budget of 50000 tokens.回车。Codex 开始自主推进:它会先读src/utils/format.js,识别导出函数,然后读test/下现有文件学习风格,再生成测试文件,最后跑npm test验证。
中途你可以用/goal查看状态。实测下来,一个中等规模的文件补测试,大概几分钟到十几分钟,取决于函数数量和复杂度。
跑完后,Done when的三条会逐条被验证。如果npm test退出码是 0,终端会输出通过数量。这时候你去看test/format.test.js,文件应该已经生成好了。
如果第一轮输出对不上目标,立刻/goal pause,补充上下文,再/goal resume。不要让它带着错误方向继续跑。
长任务有个注意点:不要手动/compact。让自动压缩落在轮次边界,手动压缩容易打断代理的上下文连贯性。
如果你用的是聚合网关或中转站,第一轮先跑最小目标,确认模型可用、上下文不丢、长任务不会中途断流,再上整夜任务。这一步是保险,别跳过。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
跑/goal的过程中,最容易在入口层出问题。下面按真实报错对照排查。
401 Unauthorized。最常见的原因是 Key 复制不完整、前后有空格,或者被编辑器换行截断。先检查~/.codex/auth.json里的 Key 是不是完整的一串,前后有没有多余字符。如果 Key 没问题,检查config.toml里的base_url是不是https://taotoken.net/api/v1,带没带/v1。OpenAI 兼容客户端要带/v1,Claude Code 那类填根地址不带。两者混了就会 401。
local proxy failed。这个报错通常出现在你本地配了代理但代理没起来,或者代理地址写错。检查环境变量里有没有HTTP_PROXY、HTTPS_PROXY这类设置,如果有但代理服务没运行,就会报这个。清掉这些环境变量再试。
reading choices 相关报错。这个一般出现在响应格式不匹配的时候。Codex CLI 用的是 responses API,如果你在config.toml里wire_api写成了chat但实际入口只支持 responses,或者反过来,就会在解析响应时报错。确认wire_api = "responses"和你的入口能力匹配。
OAuth 相关报错。Codex CLI 支持 OAuth 登录方式,如果你用的是 API Key 方式,就不需要走 OAuth。如果启动时提示 OAuth 相关错误,检查是不是误触发了登录流程。用 API Key 的话,确保auth.json里的OPENAI_API_KEY存在且有效,Codex 会优先用这个。
余额不足或模型无权限。这类提示优先找服务方处理,不要在本地反复重装。本地重装解决不了账户层面的问题。
Plan 模式下 /goal 不推进。UI 显示 Goal active,但实际不动。这是因为 Plan 模式会拦截执行。必须先Shift+Tab退出 Plan 模式,再下/goal。
resume 列表找不到会话。原因是第一条消息就发了/goal。先随便发一句话建立会话,再用/goal。
目标里用虚词导致跑偏。比如「优化所有」「彻底清理」「improve performance」。审计机制映射不了这些,跑出来一定偏。换成具体数字和可验证状态。
不设 token 预算。跑飞了没有软停止。永远设 budget。
破坏性操作不加保护。/goal会自己往下推进。如果目标涉及删文件、改数据库,Constraints和Stop if里必须写明红线。
排查顺序建议:先确认入口通(发一句普通消息能不能回),再确认/goal启用(输入/能不能看到),再看目标本身(有没有虚词、完成条件能不能验证),最后看运行环境(代理、环境变量)。
6. 进阶玩法与长期编码方案:goal-prompt-builder、OpenSpec 与 Coding Plan
手写五段式写多了会累,可以用goal-prompt-builder自动生成。安装:
git clone https://github.com/win4r/goal-prompt-builder.git ln -s "$(pwd)/goal-prompt-builder/goal-prompt-builder" ~/.claude/skills/goal-prompt-builder重启后,跟 Codex 说「我想用 /goal 来做 XXX」,它会自动检测项目类型,问你几个问题,输出一段可以直接粘贴的五段式目标。内部有审计友好度打分,低于 70 分直接拒绝渲染,要求你补充信息。这个机制挺实用,相当于帮你把虚词挡在门外。
另一个进阶玩法是 OpenSpec +/goal的规格驱动开发。先装 OpenSpec:
npm install -g @fission-ai/openspec@latest cd your-project openspec init然后用/opsx:propose生成规格文档,Codex 会在openspec/changes/下生成 proposal、specs、design、tasks 四个文档。接着把规格交给/goal执行:
/goal 严格实现 openspec/changes/add-cohere-rerank/ 中的变更。 First action: 先读 proposal.md / specs/ / design.md / tasks.md, 报告每个文件的字数和关键章节标题,等我确认后再开始。 Scope: design.md 里的 MUST NOT 列表严格遵守。 Done when: 1. tasks.md 每项打勾,引用文件路径 2. npx tsc --noEmit 退出码 0 3. npm test 退出码 0 Stop if: - 需要修改 MUST NOT 列表中的文件 - 需要 npm install 新依赖 Use a token budget of 120000 tokens.注意First action那行。强制 Codex 先读完规格再动手,防止它假装「知道了」实际没读全。这个技巧在长任务里特别有用。
三种工作流按需选:工作流 A 直接用,70% 的任务用这个,边界清楚自己能写五段式。工作流 B 是 Plan + Goal,任务复杂需求模糊时,先用/plan讨论方案,Codex 会问你关键决策,讨论完Shift+Tab退出 Plan 模式再下/goal。工作流 C 是 OpenSpec + Goal,规格驱动,产物质量最稳。
如果你打算长期跑编码代理和无人值守任务,可以了解一下 Coding Plan 这类长期方案,入口在 https://taotoken.net/api 对应的后台里能找到。它适合把编码代理当日常工具用的人,比按次调用更划算。
第一次做的建议:先拿一个小任务练手,比如「给这个文件补 20 个单元测试」。Token budget 先设小一点(5 万),看跑出来的节奏对不对。第一轮输出对不上目标,立刻/goal pause,补上下文,再/goal resume。长任务不要手动/compact,让自动压缩落在轮次边界。如果你用的是聚合网关或中转站,第一轮先跑最小目标,确认模型可用、上下文不丢、长任务不会中途断流,再上整夜任务。
控制命令速查:创建目标/goal <objective>,查看进度/goal,暂停/goal pause,恢复/goal resume,清空/goal clear,退出 Plan 模式Shift+Tab,跨会话恢复codex resume <id>。
跑通之后你会发现,/goal真正的门槛不在配置,而在目标怎么写。配置是一次性的,目标写法是每次都要过的关。把五段式模板用熟,把虚词换成数字,把完成条件换成可验证的命令,无人值守开发才算真正落地。