编者:Codex 是 OpenAI 推出的 AI 编程助手,近期备受关注。此前我们介绍了《如何在 GPT 官网使用 Codex》,本次特邀大 V @haima 撰写教程,讲解如何在 CLI(命令行)中调用 Codex 助力编程。
写给对 AI 编程感兴趣的朋友:一步步用 Codex 写 + Gemini 审查 如何落地一个小游戏。
一、为什么要用 AI 协作写代码
- 加速开发:样板逻辑、基础模块、异常处理等交给 AI 起草,人类聚焦业务与体验。
- 辅助审查:第二视角发现潜在 bug、风格不一致、边界遗漏。
- 降低门槛:即便是新手,也能用 prompt 得到可运行版本,再逐步优化。
-
AI + AI 协作:Codex 负责“写”,Gemini 负责“审”,最后人工完成终审与测试。
二、Codex 的使用方式与费用概览
2.1 使用方式
| | | |
---|
CLI(命令行) | | | prompt 要明确、带上下文;多文件项目注意路径与依赖 |
IDE 插件 | | | |
OpenAI/ChatGPT 网页 | |
| |
API 调用 | | | |
2.2 费用与限额(通俗说明)
-
ChatGPT 会员(plus/pro):Codex 通常已经包含在对应付费计划里免费提供,但需要遵循按“消息/任务”配额限制使用,根据 OpenAI 的文档,Plus 用户可以在 5 小时窗口中发送大约 30–150 条 Codex 消息,同时还受到“每周总额度”的限制。Pro 用户的额度则远高一些:约 5 小时内 300–1,500 条消息。
- API 用户:按 token/请求计费;需自行控制成本、限流与重试。
- Gemini(审查/Code Assist):有免费额度/订阅层级,频繁调用需关注配额与速率,用于 vibe coding 时每分钟不超过 60 次,每天不超过 6000 次。
三、CLI 实操演示:Codex + Gemini 协作写一个 Python 贪吃蛇(由于作者使用 MacOS,本文以 MacOS 为示意)
目标:在命令行里完成“写 → 审查 → 修正 → 测试”的闭环。
首先需要安装 codex(如何安装询问GPT即可搞定)
首先安装 node.js,并安装 node.js 的包管理器 npm,具体方法如果不会可以直接问 GPT,安装完成后执行命令 npm install -g @openai/codex; 安装完成后打开一个终端窗口,执行命令:
mkdir snake_game
cd snake_game
python -m venv .venv && source .venv/bin/activate # 可选
用于创建项目目录并初始化 python 环境
在项目目录下输入:codex 即可进入 codex 对话编程模式。
(登录时系统会跳出提示,让你登录GPT Plus完成账号认证)
页面会弹出自动修改和审核修改代码的选项,新手建议选择审核修改,以便观察 codex 在修改哪个文件;
【图 1:项目初始化选择审核修改的界面】
选择好后就进入对话模式,此时可以看到屏幕提示通过提示符“/”执行系统功能,我们先执行/model,去选择 chatgpt-5 codex(high)模型,这里模型越大,效果越好,但是速度越慢,根据自己的情况选择。
【图 2:选择模型大小】
接下来我们就可以进入到 codex 辅助编程的模式了
3.1 初始化项目
pip install pygame # 运行需要
3.2 用 Codex 生成初稿
在 codex 窗口里执行
使用 Python + Pygame 写一个简单贪吃蛇游戏snake.py,窗口 640x480,方向键控制,吃食物变长,撞墙或碰自己游戏结束,显示得分。
【截图 3:codex开发游戏】
此时生成的代码常见以下问题:未禁止“反向掉头”、食物可能生成在蛇身上、未渲染文字分数等。
3.3 用 Gemini 审查并给出优化建议
再打开一个终端窗口,进入项目目录,并通过 gemini 命令进入 gemini coding 界面。在 gemini cli 窗口输入
请审查 snake.py,指出代码存在的问题并修改这些问题。
【图 5:Gemini 的审查结果并让 gemini 根据审查结果直接修改代码】
3.4 应用修改并循环
我已经让gemini帮你审查了snake.py代码并进行了优化,请你再次查看snake.py并反馈你是否对gemini的修改认可并接受。
【图 6:codex 再次审查代码后通过的输出情况】
3.5 运行与验收
python snake.py
【图 7:Pygame 游戏窗口(可见蛇、食物、得分)】
根据游戏体验,完成人工验收清单:

四、进阶用法:把“工程规范”写进仓库:agent.md 与各工具的规则文件
目的:让 AI 始终遵循你的工程标准与约定。在仓库放置规则文件,配合不同工具自动读取或手动注入上下文,显著提升生成质量与一致性。
4.1 建议在仓库根目录新增 agent.md
推荐大纲:
# agent.md — 项目 AI 使用指南 / 工程规范
## 1. 项目背景与目标
- 项目一句话定位与主要用户。
- Tech stack(语言/框架/运行环境)。
## 2. 代码风格与格式
- 语言版本、格式化工具(black/ruff/prettier 等)与命令。
- 命名约定、文件组织、注释规范、Docstring 模板。
## 3. 架构与模块边界
- 目录结构、模块职责、依赖约束(禁止/允许)。
- 可复用的工具函数/公共库。
## 4. 安全与合规
- 严禁输出或硬编码任何密钥/凭据。
- 网络/文件访问的白名单、脱敏与日志要求。
## 5. 测试与验证
- 单测/集成测试要求,覆盖率目标与命令。
- 本地运行与验证步骤(重要)。
## 6. PR/提交规范
- Commit 信息、分支策略、PR 模板、评审要点清单。
## 7. 常见陷阱(Do/Don’t)
- 典型误用与修正示例,性能/并发/边界注意事项。
## 8. 提示语模版(Prompts)
- 生成/重构/修复/审查的标准 Prompt 模版。
使用方法:
- CLI/网页模式:把
agent.md
的关键段落拷入 Prompt(或让工具支持的“文件上下文”读取)。 - IDE/编辑器模式:若工具支持仓库规则文件(见下节),保持
agent.md
与工具规则文件同源更新。
4.2 针对不同工具的“规则文件”落地
- Cursor / Windsurf 等编辑器:在仓库添加
.cursor/
下的规则文件或根目录 .cursorrules
(与 agent.md
同步)。 - GitHub Copilot:在仓库加入
.github/copilot-instructions.md
(可从 agent.md
抽取精华) - Gemini Code Assist(GitHub 集成):在仓库添加
.gemini/
目录,放置 config.yaml
与 styleguide.md
(从 agent.md
派生风格与约束)。
维护策略:把 agent.md
作为单一事实来源(SSOT),其余规则文件自动或手工同步,以避免分叉。
4.3 styleguide.md
(给审查器看的风格/约束示例)
# styleguide.md — 审查风格与约束
- 统一使用 snake_case / camelCase(按项目约定)。
- Pygame 循环内绘制与事件处理分离,绘制函数无副作用。
- 禁止反向掉头的按键切换:上 ↔ 下、左 ↔ 右互斥。
- 食物随机生成不得落在蛇身(需重采样)。
- 必须渲染分数文本,字体最小 16px,统一颜色。
- 新增功能必须附带最小可行单测或可运行 demo。
- PR 必须包含:变更摘要、风险与回滚方案、测试记录截图。
提示:在 PR 审查中,@提及审查器(如 /gemini
)并引用 styleguide.md
的关键条目,可显著提升审查一致性。
五、常见问题与风险提示
-
上下文/窗口限制:大型多文件项目需分步提供上下文或用“规则文件”。
- 并发修改冲突:建议“写 → 审 → 再写”的节奏,避免两个工具同时改同一文件。
- 误判/漏判:审查器并非 100% 正确,最终仍需人工测试与代码评审。
- 配额/成本/速率限制:频繁调用需关注额度与重试策略。
- 安全与隐私:避免在 prompt/代码中泄露密钥与敏感数据。
六、流程小结
明确需求 → Codex 生成初稿 → Gemini 审查/给补丁 → 应用修改 → 本地运行/测试 → 循环迭代 → 合规提交/发布
附:最小可运行贪吃蛇
import pygame, sys, random
pygame.init()
W,H=640,480; S=10
screen=pygame.display.set_mode((W,H))
clock=pygame.time.Clock(); font=pygame.font.SysFont(None,24)
def rand_food(snake):
whileTrue:
f=(random.randrange(0,W//S)*S, random.randrange(0,H//S)*S)
if f notin snake: return f
snake=[(100,100),(90,100),(80,100)]; dir=(S,0)
food=rand_food(snake); score=0; pending=None
whileTrue:
for e in pygame.event.get():
if e.type==pygame.QUIT: pygame.quit(); sys.exit()
if e.type==pygame.KEYDOWN:
x,y=dir
if e.key==pygame.K_UP and y==0: pending=(0,-S)
if e.key==pygame.K_DOWN and y==0: pending=(0,S)
if e.key==pygame.K_LEFT and x==0: pending=(-S,0)
if e.key==pygame.K_RIGHT and x==0: pending=(S,0)
if pending: dir=pending; pending=None
head=(snake[0][0]+dir[0
], snake[0][1]+dir[1])
ifnot (0<=head[0]and0<=head[1]or head in snake: break
snake.insert(0,head)
if head==food: score+=1; food=rand_food(snake)
else: snake.pop()
screen.fill((0,0,0))
for x,y in snake: pygame.draw.rect(screen,(0,255,0),(x,y,S,S))
pygame.draw.rect(screen,(255,0,0),(food[0],food[1],S,S))
screen.blit(font.render(f"Score: {score}",True,(255,255,255)),(8,8))
pygame.display.flip(); clock.tick(12)
print("Game Over! Score:",score)