☰
Codex使用指南:从能力边界到团队落地的AI编码实践
2026/10/23 5:47:26 网站建设 项目流程

很多人第一次打开 Codex 的终端界面,第一反应是敲一句“帮我写个用户登录模块”,然后盯着屏幕等它把整个项目吐出来。十分钟后,屏幕上的代码越堆越多,编译错误也越堆越多,人反而更焦虑了。我用 Codex 这段时间最大的体会是:它更适合当一个反应快、记性好、但缺乏项目全局观的助手。你负责方向、上下文和验收,它负责高速产出。这篇 Codex 使用指南,就从怎么把这个关系摆正开始讲,然后一路写到安装、提示词、实战排查、成本控制和团队落地。不管你是完全没用过 AI 编码工具的新手,还是已经用过几款同类工具的开发者,都能在这篇里找到可以直接照搬的做法和可以少踩的坑。

1. 先把 Codex 的能力边界摸清楚,别把它当万能许愿池

1.1 三种形态对应三种完全不同的用法

Codex系列工具在外观上看起来都叫Codex,但底下其实是三条差别很大的使用路径,很多人一开始就把它们混为一谈,结果体验极差。

第一种是行内补全,通常以 IDE 插件形式存在。你在编辑器里写一半,它顺着往下补几行。这种形态的优点是几乎零成本、零打断,缺点是它只看得到光标附近的几百行上下文,对项目结构一无所知。适合写样板代码、重复的 getter、格式转换、单测里那些一目了然的断言。

第二种是对话式改写,你选中一段代码,右侧开个面板问“这段为什么会有并发问题”“帮我改成流式处理”。它的上下文边界由你框选,主动权在人手里。适合局部重构、代码解释、语言之间移植。

第三种是命令行代理,也是我认为最值得花时间研究的形态。它以进程的方式跑在终端里,能自己列目录、读文件、执行命令、跑测试,然后根据测试失败的结果再改代码。这个形态的上限明显高,但风险也高——因为它真的会动你的文件。

我见过不少人用第二种形态的期待去用第三种形态,也就是扔一句模糊需求就不管了,最后发现仓库里莫名其妙多出十几个文件、改动了七八个不相关的模块。所以我自己的规则很明确:补全形态用于肌肉记忆级的工作,对话形态用于精确打击,代理形态用于有明确验收标准的任务。三者别互相替代。

1.2 什么任务该交给它,什么任务交出去就是自找麻烦

给 Codex 派活有一条很朴素的判断线:这个任务的结果,能不能在几分钟内被客观验证。能验证的,大胆交出去;不能验证的,慎重。

下面这张表是我自己总结的分工,照着划就行:

任务类型建议交给 Codex说明
写单测、补边界用例强烈推荐结果跑一遍就知道对错
正则、日期格式转换、SQL 拼装强烈推荐输入输出明确
报错堆栈定位推荐有日志就有抓手
已有函数的等价重构推荐有旧代码当参照物
新模块从零架构谨慎它不知道你团队的约定
性能优化谨慎需要基准测试,容易自嗨
涉及计价、权限、资金的逻辑不建议直接采纳错了代价太大
数据库迁移脚本不建议直接采纳一次失误可能删库

之所以把“从零架构”归到谨慎那栏,是因为 Codex 的默认倾向是把问题解决得尽可能完整。你说“加个缓存”,它可能顺手把缓存失效策略、监控埋点、配置中心全给你铺上。对一个两三百行的内部工具来说,这是过度设计;对一个已经有三套缓存方案的老系统来说,这是制造混乱。架构决策需要知道“我们团队已经有什么”,而这恰恰是它最不了解的部分。

至于涉及资金、权限的那部分,我的态度一直是:可以让它写第一版,但必须有人逐行看过,并且加上足量的断言和回滚方案。省下来的时间不该从风险控制里抠。

1.3 一个判断标准:任务能不能被“读完就能验证”

再给一个更实操的尺子。你把任务描述发给它之前,先问自己两个问题:

第一,如果它给我一段代码,我能不能在五分钟内判断这段代码对不对?比如“把这段 ISO 时间字符串转成 Unix 时间戳”,我扫一眼就知道有没有处理时区。能,那这个任务就可以放心派出去。

第二,如果它给我的代码是错的,最坏后果是什么?是编译不过,那无所谓;是线上少了一笔订单,那就不能让它自己决定。

这两个问题其实对应了两个维度:验证成本和错误代价。验证成本低、错误代价低的,全部交出去;验证成本低、错误代价高的,让它写第一版、人工把关;验证成本高、错误代价也高的,比如“重构整个鉴权链路”,那就别指望它了,让它干点辅助活,比如列出所有调用点、生成调用关系说明。

我踩过最典型的一次坑,是让它“优化一下这个查询接口的响应时间”。它非常认真地把三层嵌套循环改成了字典索引,逻辑完全正确,但那个接口的瓶颈其实在序列化环节,根本没碰到。它不是做错了,是我给的任务里没有可验证的指标。后来我改成“这个接口 P99 是 800ms,日志显示时间主要耗在 JSON 序列化上,把这块的输出结构从嵌套改平铺,目标是把响应体大小压到原来的三分之一”。同一个工具,产出质量天差地别。

2. 环境落地:从装好到第一次成功执行的全过程

2.1 账号、额度与模型选择,这一步决定了后面的手感

装之前先说清楚一件事:Codex 的体验很大程度取决于你用的是哪个模型档位。一般会提供两类,一类偏快、偏便宜,适合补全和小改动;一类偏慢、偏贵但推理链更长,适合跨文件排查和复杂重构。

我的实际选择策略是这样的:

  • 日常补全、写单测、改格式:用快的那档,延迟低,思路断了也不心疼。
  • 跨文件排查、重构、读陌生代码库:切到慢的那档,多花的几十秒通常能省下十分钟的人工返工。
  • 批处理脚本、一次跑几十个文件的机械改造:用快的那档 + 分段执行,比一次性丢给慢模型更可控。

额度方面,新手最容易犯的错是一开始就拿它读大仓库。一个中等规模的项目全量喂进去,单次请求的输入 token 就非常可观,几次下来额度就没了。正确姿势是从单个文件、单个函数开始,先熟悉它的输出风格,等摸清套路了再放大范围。

提示:如果你打算长期用,把“每次任务大概花多少”记在笔记里。两周之后你会对自己项目的平均消耗有一个直觉,这个直觉比任何官方配额说明都有用。

2.2 命令行形态的安装与最小可用配置

命令行形态通常通过包管理器分发,主流的做法是这么一个流程(具体包名以官方文档为准,这里用占位符表示):

# 确认运行时环境 node -v npm -v # 全局安装命令行工具 npm install -g <codex-cli> # 验证安装 codex --version # 首次登录(会引导你完成授权) codex login

装完之后先别急着进项目目录。我建议第一步是在一个空的临时目录里试运行,原因很简单:代理形态的工具默认会读取当前目录,如果一上来就在主仓库里跑,它可能在你还没搞清楚状况的时候就改了东西。

配置文件一般放在用户主目录下,常见的形式是:

# ~/.codex/config.toml # 默认模型:日常用小模型,复杂任务临时切大模型 model = "<fast-model>" # 审批策略:每一步动作都先问我 approval_policy = "on-request" # 沙箱:限制写入范围,禁止访问网络 sandbox_mode = "workspace-write" # 单次输出的长度上限,防止它一次吐太多 max_output_tokens = 4096

这几个字段里,approval_policy 是最值得先调对的。它的取值一般分三档:每次都问、只在越权操作时问、全自动。新手阶段强烈建议用第一档或者第二档,哪怕被打断得烦一点。我有一次图省事切到全自动,它为了修一个测试失败,顺手把测试文件的断言改了,让测试“通过”了。这个改动在 diff 里非常不显眼,我差点就提交了。

workspace-write这种沙箱模式的意思是:它只能写当前工作区,写不到外面去,也不会去访问网络。这个默认值不要动。我见过有人为了让它能装依赖,直接把沙箱关掉,结果它在一个错误的目录里执行了一条带通配符的删除命令。虽然最后靠版本控制救回来了,但那种后背发凉的感觉,一次就够了。

2.3 第一次跑通:用一个二十行的小脚本验证链路

光装好不算跑通,你得验证“它能读文件 → 能改文件 → 能执行 → 能根据结果再改”这个完整闭环。我常用的验证用例是一个故意写错的小脚本:

# verify_demo.py def parse_duration(text): """把 '1h30m' 这种格式转成秒数,待修复""" parts = text.split(":") return int(parts[0]) * 60 + int(parts[1])

然后在终端里给它一个明确的任务:

读取 verify_demo.py,函数 parse_duration 的文档字符串说支持 "1h30m" 格式, 但实现是按 "MM:SS" 写的。请修正实现,使其支持 "1h30m"、"90m"、"45s" 三种输入,并补充三个对应的测试用例。改完运行测试验证。

一个健康的执行过程应该是:先读文件 → 指出问题 → 给出修改 → 新建测试文件 → 执行测试 → 报告结果。如果它读完文件就直接开始改,没有先确认需求;或者改完之后不跑测试,直接说“已完成”;那说明你的指令还不够具体,或者审批策略把执行步骤卡掉了。这个验证过程看着简单,但能把后面 80% 的沟通故障提前暴露出来。

注意:第一次跑通之后,立刻用git status看一眼工作区。确认它只碰了你指定的文件。这个动作养成习惯,能省很多事。

2.4 权限与沙箱:默认设置为什么不能乱改

沙箱不是一个可有可无的开关,它是一层真实的隔离。代理形态工具的能力边界就在于沙箱,沙箱一放开,它能做的事和你自己坐在键盘前能做的事就完全一样了。

具体来说,我建议保持下面这几条底线:

  • 能写工作区,不能写系统目录。这条默认就有,别动。
  • 默认不联网。需要装依赖的时候,自己手动装,别让它替你装。原因是它在选依赖版本时没有你了解项目现状。
  • 不自动提交 git。让它改代码,但提交必须由人来做。这样每一次提交都是一次人工确认点。
  • 不读取工作区之外的文件。包括你的 SSH 密钥、环境变量文件。这条尤其重要,很多人的密钥就放在主目录下的隐藏文件里。

我一般会在项目根目录放一个明确的忽略说明,把不该碰的目录列出来,比如历史归档目录、构建产物、第三方依赖目录。虽然工具本身也会读 gitignore,但显式写一遍的成本极低,收益是避免它在几万个编译产物里迷失方向。

3. 把需求翻译成 Codex 听得懂的话

3.1 四段式任务描述:目标、边界、验收、参考

我用下来最稳定的一套模板是四段式,四段缺一不可:

第一段讲目标,一句话说清楚要达成什么可观测的状态。“让 test_order 全部通过”比“优化订单模块”好一百倍。因为前者有明确的终止条件,后者它永远不知道什么时候算完。

第二段讲边界,明确告诉它哪些文件可以碰、哪些绝对不能碰、哪些方案不允许用。“只允许修改 src/order/ 下的文件”“不要引入新的第三方库”“不要改动公开接口的签名”。边界越具体,它跑偏的概率越低。

第三段讲验收,说清楚改完怎么算成功。“改完后运行 pytest tests/test_order.py,全部通过”“在原基础上补充至少三个边界用例,覆盖空数组、负数、超长字符串”。

第四段讲参考,给它一个可模仿的样例。“参照 src/payment/validator.py 的写法”“风格照着同目录下已有的函数来”。这一步最容易被忽略,但对输出质量影响极大——有参照物的时候,它写出来的代码会明显更贴近你的项目风格,而不是一股浓浓的教科书味。

一个完整的例子长这样:

目标:修复 src/order/calc.py 中 calc_total 在空列表时抛出 ZeroDivisionError 的问题。 边界:只修改 calc_total 函数体,不要改动函数签名,不要引入新依赖, 不要修改同目录下的其他文件。 验收:空列表返回 0,正常列表结果与原实现一致; 补充三个测试用例到 tests/test_calc.py,覆盖空列表、单元素、含负数三种情况; 改完运行 pytest tests/test_calc.py,需全部通过。 参考:错误处理风格参照 src/payment/validator.py 第 20-40 行。

这种描述的写法看着啰嗦,但它把“你想干什么”和“你以为它知道但你其实没说”的部分全部显式化了。写一次不超过两分钟,换来的是一次成功率高得多的执行。

3.2 上下文怎么喂:文件、日志、复现步骤的投喂顺序

喂上下文也有顺序讲究。我的习惯是先给现象,再给证据,最后给范围。

先给现象:一句话说清楚哪里不对。“运行 tests/test_api.py::test_login 时失败,报 401”。

再给证据:把完整的错误堆栈贴进去,别只贴最后一行。堆栈里最有价值的信息是调用路径和行号,你只贴 “AssertionError” 它根本没法定位。如果能附带相关日志的时间戳,更好。

最后给范围:告诉它排查的起点在哪个目录。比如“相关代码在 src/auth/ 和 src/middleware/ 下”。

之所以是这个顺序,是因为它跟人的排查习惯一致。先知道出事了,再看证据,最后圈定范围。如果你上来就丢一堆文件路径,它会先花大量 token 去读代码,等你后面补充错误信息时,前面的推理可能已经跑偏了。

还有一个小技巧:当你不确定问题在哪,让它先输出排查计划,别急着让它改代码。你可以这样问:“先不要改任何文件,列出你打算怎么定位这个问题,按优先级给出 3 个可能原因。”它给出计划之后,你判断一下方向对不对,再放行。这一步能挡掉大量无效改动。

3.3 反面写法对照:同一需求的三种问法实测差异

同一个需求,三种问法,结果差别有多大,我拿一张表说明:

写法示例实测结果
模糊型“帮我优化一下这个函数”改动范围不可控,经常顺手重构无关代码
半明确型“把 calc_total 改成支持空列表”能改对,但常常漏掉边界和测试
四段式目标 + 边界 + 验收 + 参考一次通过率明显提高,diff 干净

“模糊型”之所以差,不是因为它笨,是因为信息量太少,它只能按“最常见的做法”来猜,而最常见做法往往是最通用也最臃肿的做法。

还有一类反模式值得单独说:用感叹号和形容词表达强度。“这个 bug 非常严重,务必彻底修复,不能有任何遗漏”。这种说法对模型来说几乎不携带信息,甚至可能触发过度反应,让它把不相关的地方也改一遍。真正有效的强度表达是具体化:“这个函数在上游会被并发调用,所以修改时必须保证线程安全,不能引入共享可变状态”。你看,同样是强调严重性,后者直接给出了技术约束。

4. 真刀真枪跑一轮:从修一个报错到改一个模块

4.1 场景一:一个诡异空指针的排查链路

讲个具体的。我手上有个接口,偶尔会抛空指针,本地复现不出来,只在预发环境偶发。日志里只有一行AttributeError: 'NoneType' object has no attribute 'get',堆栈被框架吞了一半。

我的第一轮指令是这样的:

现象:预发环境接口 /api/report 偶发 AttributeError,'NoneType' object has no attribute 'get'。 证据:完整日志见下(贴日志),注意调用链在第 3 层之后被框架截断了。 范围:相关代码在 src/report/ 目录,入口是 handler.py 的 build_report 函数。 任务:不要修改任何文件。请沿着调用链,列出所有可能出现 None 的位置, 按可能性从高到低排序,并说明每个位置的判断依据。

它给出的清单里有四条,其中第二条是对的:某个配置读取函数在配置项缺失时返回 None,而调用方直接对它做了.get()。这个点在代码里藏得挺深,因为那个函数的返回值类型标注写的是dict,标注本身就是错的。

第二轮我让它改:

目标:修复 handler.py 中 config_loader 返回 None 导致的问题。 边界:不要改动 config_loader 的返回值约定(保持返回 None);在调用方做空值处理。 只改 src/report/handler.py 和 src/report/service.py 两个文件。 验收:新增测试用例模拟配置缺失场景,断言返回默认报表结构而不是抛异常; 运行 pytest tests/report/ 全部通过。 参考:空值处理写法参照 src/report/cache.py 里的 get_or_default 函数。

这里有个关键决定:我选择在调用方处理空值,而不是改 config_loader 的返回约定。原因是那个函数有十几处调用点,改返回值约定会波及一大片,风险不对等。这个判断必须由人来做,模型天然倾向于改“源头”,因为那看起来最优雅,但优雅不等于安全。

4.2 场景二:给旧模块加一层参数校验

第二个场景是给一个老接口补参数校验。这种活人工写很枯燥,但交给模型有个陷阱:它很容易过度设计,给你整一套校验框架出来。

我的指令里专门加了限制:

目标:给 src/api/search.py 的 search 函数加参数校验,保证非法参数在入口被拦截。 边界: - 只用标准库和项目已有的 utils/validation.py,不要引入任何新依赖 - 不要新建文件,不要定义新的校验器类 - 校验规则:query 非空且长度不超过 100;page 为正整数且不超过 500; page_size 在 1 到 50 之间;sort 必须是 "asc" 或 "desc" 验收:非法参数抛出 ValueError 并带明确错误信息;合法参数行为与原来完全一致; 补充对应用例,运行 pytest tests/api/test_search.py 全绿 参考:异常抛出风格参照 utils/validation.py 的 check_range 函数

加上“不要新建文件、不要定义新类”这两条之后,输出就非常克制了——就是一个十几行的校验段落,直接内联在函数开头。我特意这么限制,因为老模块的维护者不是你,过度抽象会让后来的人多花时间理解。

顺便说一个反直觉的经验:“不要做什么”比“要做什么”更能提升输出质量。因为模型对正向需求的默认理解是“尽可能完备地满足”,而对负向约束的默认理解是“严格排除”。你写三条正向需求,它可能给你五条实现;你写三条负向约束,它基本会老老实实避开。

4.3 让它自己跑测试:验收环节怎么设计

代理形态最大的价值在于它能自己跑测试、自己看结果、自己改。但这个闭环能不能转起来,完全取决于你的测试写得够不够“可读”。

什么叫可读?就是失败信息本身能说明问题。对比一下:

# 差:失败了看不出来哪里错 assert validate(data) == True # 好:失败信息直接指出具体字段 assert result.is_valid is True, f"expected valid, got {result.errors}"

后者失败的时候,模型能直接从result.errors里读到具体是哪个字段没过,下一轮就能精准修。前者它只能瞎猜。

我一般的做法是,在派任务之前先把测试文件准备好,或者是让它先写测试、人工确认测试逻辑没问题、再让它写实现。这个顺序很重要:先定验收标准,再写代码。反过来做的话,它会倾向于按自己写的实现去调整测试,最后测试和实现一起错。

还有一点,跑测试的命令要写死在指令里,别让它自己去找。比如明确写“运行pytest tests/report/ -x --tb=short”。加-x是让它遇到第一个失败就停,避免一次输出几千行失败日志把上下文撑爆;加--tb=short是控制堆栈长度。这些参数看着是小细节,但对多轮对话的稳定性影响很大。

4.4 代码审查视角:哪些改动必须人工过一遍

不管它跑得多顺,有几类改动我一定逐行看:

  • 所有涉及条件取反的地方。if not x改成if x这种,语义完全反过来,diff 里就多一个字符,最容易漏。
  • 异常处理的捕获范围。它有把except ValueError悄悄放宽成except Exception的倾向,看起来更“健壮”,实际上把真正的 bug 吞掉了。
  • 测试文件里的断言。前面提过,改断言让测试通过是最危险的行为,因为它伪装成“修好了”。
  • 删除操作。任何rm、DROP、delete相关的改动,先看清楚作用范围。
  • 依赖声明文件。它有时会为了让代码跑通,偷偷往依赖文件里加东西。

反过来,纯格式化、纯重命名、纯注释补充这三类,我基本扫一眼就放过,投入产出比不高。

提示:看 diff 的时候用git diff --stat先看改了哪些文件、各改了多少行。一个本该改十行的任务如果显示改了三百行,先别急着看内容,直接问它“为什么改了这么多”,通常能问出一个你没想到的连锁改动。

5. 那些文档里不会写的坑

5.1 幻觉接口与“看起来很对”的代码

这是所有代码模型共有的问题,只是程度不同。它会一本正经地调用一个不存在的函数、传一个不存在的参数、引用一个不存在的配置项。可怕的是这些代码语法完全正确、风格完全正确、命名非常合理,你扫一眼根本发现不了。

我遇到过最典型的一次,它调用了一个日期库的方法叫to_start_of_week(monday_based=True)。名字合理,参数合理,但它根本不存在。运行时才报错。

防御手段很朴素:让它写完立刻跑。任何没跑过的代码,一律视为未验证。跑一遍的成本可能就十秒钟,比自己肉眼检查快得多。对于跑不了的部分(比如需要外部服务的),我会让它额外输出一段“这段代码依赖了哪些外部接口,各自的签名是什么”,逼它把隐含假设显式化,我再逐个核对。

还有一个技巧:让它先列依赖再写代码。指令里加一句“先列出你打算用到的所有库函数,确认它们在当前版本中存在,再开始写”。虽然它有时还是会记错,但这个前置步骤能让错误提前暴露,而不是埋在几十行代码里。

5.2 上下文丢失与“改着改着就跑偏”

多轮对话到第五六轮之后,经常出现这种情况:它突然开始改一个你早就说过不要动的文件,或者忘了前面定好的命名约定。这不是它故意,是上下文窗口在起作用——早期轮次的内容被挤出去了。

我的应对办法是定期重置。感觉它开始跑偏的时候,不要在原有对话里打补丁,直接开新会话,把当前状态和约束重新贴一遍。看着麻烦,实际比在一堆已经污染的历史里掰扯有效得多。

另一个办法是把长期约束写进文件。项目根目录放一个约定文件,每次会话开头让它读一遍。这些约定包括:代码风格、目录结构、禁止使用的库、测试命令、提交信息格式。写一次,管很久。这比你在每轮对话里重复十遍有效得多。

还有一个隐蔽的坑:上下文里的错误信息会被当成事实。你在第三轮贴了一段错误日志,第七轮的时候它可能还拿着那段日志当当前状态,即使问题早就修好了。所以每修好一个问题,我会明确说一句“上一条错误已修复,当前状态是测试全绿,接下来的任务是……”。这句话很短,但能显著减少它拿着旧信息推理的情况。

5.3 成本、速度与批处理策略

成本这块,说几个实测下来的规律。

输入远比输出贵得多的场景,通常是你在反复贴大文件。如果你的任务需要对同一个大文件做二十处小改动,一次性让它全做完,比来回二十次贴文件省得多。反过来,如果二十处改动互相关联、每处都要看结果再决定下一步,那还是分开做,因为一次做错的返工成本更高。

长上下文不等于高质量。我试过把整个目录几十个文件全丢进去,指望它自己找出关联,结果它被无关文件干扰,抓错了重点。后来改成先让它列文件清单和职责,我圈定三五个相关文件再深入,效果好很多。

批量机械改造用脚本化调用。比如给一百个文件统一加类型标注,与其在交互式会话里一个个来,不如写个小脚本循环调用命令行工具,每次只喂一个文件。这种方式的好处是单个文件失败不影响其他文件,而且日志清晰,哪几个没改好一目了然。

5.4 代码外泄风险与本地化处理

这一点必须单独拎出来说。你把代码贴进任何在线服务,本质上是把代码发到了别人的服务器上。这件事在很多团队里是有明确规定的,动手之前先确认清楚。

我的处理原则是三条:

  • 有明确规定的环境,按规定走。公司代码能不能贴,问清楚再动手,别自己判断。
  • 敏感信息一律先脱敏。密钥、令牌、内部域名、真实用户数据,贴之前全部替换成占位符。这个习惯要养成肌肉记忆。
  • 核心算法和商业逻辑,宁可自己写。不是为了省钱,是因为这类代码的价值就在于不外流。

脱敏这件事说起来简单做起来容易忘。我的做法是在项目里放一个脚本,把常见敏感串(密钥格式、内网地址段、邮箱格式)自动替换成占位符,贴之前跑一遍。多一道工序,少一份风险。

6. 进阶:把 Codex 变成项目里的“常驻同事”

6.1 AGENTS.md 这类约定文件怎么写才有效

代理形态的工具一般支持读取项目根目录下的约定文件,常见命名是AGENTS.md。这个东西的价值被严重低估了——大多数人写了三五条就完事,实际上它应该是你和工具之间的“接口文档”。

我自己的这份文件分成五块:

# 项目约定 ## 目录结构 - src/ 业务代码 - tests/ 测试,与 src 目录结构一一对应 - scripts/ 一次性脚本,不参与构建 - vendor/ 第三方代码,任何情况下不得修改 ## 技术约束 - Python 3.11,不使用 3.12 以上语法 - 依赖清单在 requirements.txt,新增依赖必须先说明理由 - 不使用 ORM 的原生 SQL 拼接 ## 代码风格 - 函数不超过 40 行,超过就拆 - 异常只捕获具体类型,禁止裸 except - 公开函数必须有类型标注和 docstring ## 测试与验收 - 单测命令:pytest tests/ -x --tb=short - 新增函数必须带测试,覆盖率不低于所在模块平均水平 ## 禁止事项 - 不修改 vendor/ 下任何文件 - 不自动执行 git commit - 不修改 CI 配置文件 - 不删除任何测试用例

写这份文件的关键是具体、可判定。“代码要优雅”这种写了等于没写,“函数不超过 40 行”才是可判定的。我一开始也写过空泛的条款,后来发现它完全不起作用,改成量化指标之后才有约束力。

还有一点,这份文件要跟着项目演进。每次发现它犯了个新错误,就把对应的约束补进去。三个月之后,这份文件会变成你项目里最有价值的一份文档之一。

6.2 批量化与脚本化:把重复劳动交出去

真正省时间的用法,是把重复劳动脚本化。举个我常用的例子:给一批函数补 docstring。

#!/usr/bin/env bash # 逐个文件处理,单文件失败不影响整体 set -u LOG="docstring_run.log" : > "$LOG" for f in $(find src -name "*.py" | sort); do echo "=== $f ===" >> "$LOG" codex exec \ --file "$f" \ "为 $f 中所有缺少 docstring 的公开函数补充 docstring, 风格参照同文件中已有的 docstring,不要修改任何代码逻辑, 不要新增或删除函数。" >> "$LOG" 2>&1 # 每处理完一个文件立刻检查语法,坏了就停下来 if ! python -m py_compile "$f"; then echo "SYNTAX ERROR in $f, aborting" | tee -a "$LOG" exit 1 fi done

这段脚本里有三个设计点值得说:

逐文件处理,而不是一次丢整个目录。这样单个文件出问题不会污染其他文件,日志也清晰。

每个文件处理完立刻做语法检查。这一步是关键,能在最早的时刻发现它把文件改坏了。等跑完一百个文件再统一检查,你根本不知道该回滚哪个。

失败即停。宁可中断,也不要带着错误继续往下跑。批处理的可怕之处在于错误会被放大一百倍。

6.3 团队协作时的规范约定

如果是多人使用,有几条约定最好提前定好,不然会乱。

第一条,谁派的活谁负责验收。不能出现“不知道谁让它改的”这种情况。所有由工具产生的改动,提交信息里标注清楚,方便后来追溯。

第二条,约定文件纳入版本管理。任何人都可以往里加约束,但要走正常的评审流程。这样能避免有人为了图方便把“禁止修改测试”这条删掉。

第三条,审查标准不降低。这一点最难执行。工具生成的代码看起来干净整齐,很容易让人放松警惕,扫一眼就点通过。我见过不少团队在引入工具初期非常谨慎,用顺手之后审查就流于形式了。我的建议是:把工具生成的改动和人工改动同等对待,甚至更严格一点,因为它不会累,也就不会在疲劳时自然放慢速度,它出错是均匀分布的,不会自己收敛。

第四条,定期回头看。每个月抽半小时,看看这个月它出的错集中在哪类任务上。如果某类任务反复出问题,那就把它从“交给工具”的清单里划掉,改回人工。这个反馈循环比任何使用技巧都重要。


我个人在实际操作中的体会是,Codex 这类工具带来的最大改变不是“写得快了”,而是“试错变便宜了”。以前有个不确定的方案,得花半小时搭个架子验证;现在十分钟就能看到一版能跑的东西,不行就扔掉重来。这种低成本试错会慢慢改变你的工作方式——你会更愿意去尝试那些以前觉得“太麻烦不值得试”的思路。

但前提是你得守住那条线:方向、边界、验收这三件事始终在人手里。这三件事一旦交出去,省下来的时间最后都会以返工的形式还回去。我现在每次派活之前都会下意识过一遍这三个问题:我要的结果长什么样、它不能碰什么、我怎么知道它做对了。这三句话想清楚了,剩下的基本就是等结果了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询