什么是 codex exec
codex exec 是 Codex CLI 1.0 引入的子命令,专为自动化和脚本集成场景设计。与打开全屏 TUI 的交互模式不同,codex exec 接受一条任务描述字符串,在后台调用模型完成任务,然后以退出码 0(成功)或非零(失败)退出。
它的核心价值在于三点:
- 无需人工干预:没有审批弹窗,没有 stdin 等待,可以在完全无人值守的环境中运行。
- 可靠的退出码:脚本和 CI 系统可以通过退出码判断任务是否成功,并据此决定流水线是否继续。
- 可组合性:与
&&、||、timeout、if等 Shell 原语无缝配合,可以构建复杂的自动化工作流。
典型使用场景:在每次 Pull Request 时自动运行代码风格检查、CHANGELOG 生成、安全扫描、单元测试补全,或者在定时任务中执行日报生成、数据处理等批量 AI 任务。
基本语法与所有参数
codex exec 的完整命令格式如下:
codex exec [options] "<task>"
其中 <task> 是用自然语言描述的任务,通常用引号包裹。以下是所有支持的参数:
| 参数 | 简写 | 默认值 | 说明 |
|---|---|---|---|
--model <name> |
-m |
config.toml 中配置的模型 | 指定使用的模型,如 gpt-4.1-mini、o4-mini |
--approval-mode <mode> |
-a |
suggest |
设置审批模式:suggest、auto-edit、full-auto |
--quiet |
-q |
false | 静默模式,只输出最终结果,抑制中间过程日志 |
--full-auto |
— | false | --approval-mode full-auto 的快捷写法 |
--dangerously-auto-approve-everything |
— | false | 关闭所有审批和沙箱限制,完全自动执行。仅在受控 CI 环境使用 |
--working-dir <path> |
— | 当前目录 | 指定工作目录,默认为命令执行时的当前目录 |
--config <path> |
— | ~/.codex/config.toml | 指定自定义配置文件路径 |
几个典型的命令示例:
# 最简单:仅指定任务
$ codex exec "为 src/utils.ts 中所有 public 方法添加 JSDoc 注释"
# 指定模型 + 静默模式(CI 友好)
$ codex exec --model gpt-4.1-mini --quiet \
"根据 git log --oneline -20 输出更新 CHANGELOG.md"
# 全自动模式(CI 中推荐加上 --quiet)
$ codex exec --full-auto --quiet \
"运行 npm test,如果有测试失败则修复 src/ 下相关文件"
# 完全不受限模式(生产环境慎用)
$ codex exec --dangerously-auto-approve-everything \
"安装依赖、构建项目并运行端到端测试"
与交互模式的区别
理解两种模式的本质差异是正确使用 codex exec 的前提。
| 特性 | 交互模式 (codex) |
非交互模式 (codex exec) |
|---|---|---|
| 启动方式 | 打开全屏终端 UI(TUI) | 接受参数直接执行,无 UI |
| stdin 依赖 | 需要 TTY / 交互式终端 | 不需要,可在管道和 CI 中运行 |
| 审批对话框 | 每个敏感操作弹出确认框 | 无任何交互提示,完全自动 |
| 退出方式 | 用户手动按 q 或 Ctrl+C | 任务完成后自动退出 |
| 退出码 | 不适用(始终返回 0) | 0=成功,1=任务失败,2=配置错误 |
| 斜杠命令 | 支持 /model、/init 等 |
不支持,通过 CLI 参数替代 |
| 多轮对话 | 支持,可追问和修正 | 不支持,单次执行 |
| 适用场景 | 日常开发、探索代码库、创意任务 | CI/CD、脚本、定时任务、批量处理 |
一个简单的判断方式:如果你需要"等人",用交互模式;如果你需要"等机器",用 codex exec。
批准模式详解
批准模式(--approval-mode)控制 Codex 在执行读写文件、运行命令等操作时的行为。在非交互的 exec 场景下,选择合适的模式至关重要。
suggest 模式(默认)
这是默认模式。Codex 会生成代码建议和文件修改方案,但不会直接写入文件或执行命令——它只是将建议输出到 stdout。在 codex exec 中,这意味着你可以看到 Codex 的分析和建议,但工作区不会发生任何变化。
# 默认 suggest 模式:输出代码审查报告,不修改任何文件
$ codex exec "审查 src/ 目录下的代码,指出潜在的性能问题"
# 等价写法(明确指定)
$ codex exec --approval-mode suggest \
"审查 src/ 目录下的代码,指出潜在的性能问题"
auto-edit 模式
Codex 可以自动读写工作区内的文件,但运行 Shell 命令(如 npm install、git commit)仍需确认。在 CI 中,如果任务只是修改代码文件而不需要执行命令,这是一个安全的选择。
# auto-edit:自动修改文件,适合格式化、添加注释等任务
$ codex exec --approval-mode auto-edit \
"将 src/ 下所有 .ts 文件的 console.log 替换为 logger.debug"
在非交互的 exec 模式下,如果 auto-edit 模式中遇到需要执行命令的操作,Codex 会跳过该操作而非等待确认,这可能导致任务不完整。建议在需要执行命令的任务中使用 full-auto。
full-auto 模式
Codex 在沙箱环境内可以自动执行一切操作:读写文件、运行命令、安装依赖等。沙箱仍会限制对工作区以外文件系统的访问和网络请求(除 OpenAI API 外)。这是 CI/CD 中最常用的模式。
# full-auto:在沙箱内完全自动,适合大多数 CI 任务
$ codex exec --full-auto --quiet \
"运行 npm run lint,修复所有可自动修复的 ESLint 错误"
# 等价写法
$ codex exec --approval-mode full-auto --quiet \
"运行 npm run lint,修复所有可自动修复的 ESLint 错误"
dangerously-auto-approve-everything 模式
这个标志完全移除所有安全限制,包括沙箱。Codex 可以访问任意文件系统路径、执行任意命令、访问网络。仅在你完全信任任务内容且在隔离的 CI runner 中使用。
名字里的 "dangerously" 是认真的。在本地开发机上使用此标志可能导致意外的系统级操作。生产环境的 CI 也应优先考虑 --full-auto,除非有明确的理由需要突破沙箱限制。
退出码详解
codex exec 的退出码设计遵循 Unix 惯例,可以直接在脚本中使用。
| 退出码 | 含义 | 常见原因 |
|---|---|---|
0 |
成功 | 任务按预期完成,Codex 认为目标已达到 |
1 |
任务执行失败 | 模型无法理解指令、文件操作被沙箱拒绝、任务描述不够具体导致结果不完整 |
2 |
配置或参数错误 | OPENAI_API_KEY 未设置、无效的 --model 参数、配置文件格式错误 |
在 Shell 脚本中使用退出码:
#!/bin/bash
set -e # 任意命令失败时立即退出脚本
# 运行任务
codex exec --full-auto --quiet "更新 CHANGELOG.md"
# 手动检查退出码
if codex exec --full-auto "运行测试并修复失败的用例"; then
echo "任务成功,准备提交"
git add -A && git commit -m "chore: AI 自动修复测试"
else
EXIT_CODE=$?
echo "任务失败,退出码: $EXIT_CODE"
exit $EXIT_CODE
fi
GitHub Actions 默认在步骤退出码非零时标记为失败并停止后续步骤,无需额外处理。GitLab CI 行为相同。只有当你需要"失败时继续但记录"的特殊逻辑时才需要显式处理退出码。
GitHub Actions 集成
以下是一个完整的生产级 GitHub Actions 工作流,在每次 PR 时自动运行 Codex 进行代码检查和 CHANGELOG 更新。
name: AI Code Review & Changelog
on:
pull_request:
branches: [main, develop]
paths:
- 'src/**'
- 'lib/**'
- '!**/*.md'
permissions:
contents: write
pull-requests: write
jobs:
ai-review:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # 拉取完整历史,支持 git diff
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install project dependencies
working-directory: .
run: npm ci
- name: Install Codex CLI
run: npm install -g @openai/codex
- name: Run AI code review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
working-directory: .
run: |
codex exec \
--model gpt-4.1-mini \
--full-auto \
--quiet \
"审查本次 PR 的改动(git diff origin/main...HEAD),将代码审查报告写入 .ai-review.md,包括:潜在 bug、性能问题、安全漏洞。"
- name: Update CHANGELOG
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
working-directory: .
run: |
codex exec \
--model gpt-4.1-mini \
--full-auto \
--quiet \
"根据 git diff origin/main...HEAD 在 CHANGELOG.md 顶部追加一条 Unreleased 条目,格式遵循 Keep a Changelog 规范,只修改 CHANGELOG.md 文件。"
- name: Commit AI changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .ai-review.md CHANGELOG.md
git diff --staged --quiet || git commit -m "chore(ai): update review and changelog [skip ci]"
git push
关键细节:permissions: contents: write 是允许工作流向仓库提交改动的必要权限。fetch-depth: 0 确保 git diff origin/main...HEAD 能正常工作。git diff --staged --quiet || git commit 确保只有在有改动时才提交,避免空提交失败。
GitLab CI 集成
GitLab CI 的集成方式与 GitHub Actions 基本相同,差异主要在配置文件格式和 Secret 注入方式。
在 GitLab 中配置 OPENAI_API_KEY:进入仓库 → Settings → CI/CD → Variables → Add variable。建议同时勾选 Masked(防止日志泄露)和 Protected(仅受保护分支可用)。
stages:
- ai-review
- deploy
variables:
NODE_VERSION: "22"
ai-code-review:
stage: ai-review
image: node:22-slim
only:
- merge_requests
variables:
OPENAI_API_KEY: $OPENAI_API_KEY # 从 GitLab CI/CD Variables 注入
before_script:
- npm install -g @openai/codex
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
script:
- |
codex exec \
--model gpt-4.1-mini \
--full-auto \
--quiet \
"审查本次 MR 的改动(git diff origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}),
将问题列表写入 .ai-review.md,包括:代码质量、潜在 bug、安全问题。
只修改 .ai-review.md 文件,不修改其他任何文件。"
- |
codex exec \
--model gpt-4.1-mini \
--full-auto \
--quiet \
"根据 git diff origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME} 在 CHANGELOG.md
顶部追加一条 Unreleased 条目,格式遵循 Keep a Changelog 规范。"
after_script:
- git config user.email "[email protected]"
- git config user.name "GitLab CI"
- git add .ai-review.md CHANGELOG.md
- git diff --staged --quiet || git commit -m "chore(ai): update review and changelog [skip ci]"
- git push "https://oauth2:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
"HEAD:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"
timeout: 10 minutes
interruptible: true
实用脚本示例
以下是几个直接可用的 Bash 单行或短脚本,覆盖最常见的自动化场景。
自动生成 CHANGELOG 条目
# 根据最近 10 个提交生成 CHANGELOG 条目并追加到文件顶部
$ codex exec --model gpt-4.1-mini --full-auto --quiet \
"读取 git log --oneline -10 的输出,在 CHANGELOG.md 顶部追加一个 ## [Unreleased] 区块,每个提交一个条目,格式:- 类型: 描述"
自动修复 Lint 错误
# 运行 lint 并自动修复所有可修复的错误
$ codex exec --full-auto --quiet \
"运行 npm run lint 2>&1,分析输出,修复 src/ 目录下所有可自动修复的 ESLint 错误,然后再次运行 lint 确认无误"
批量生成 JSDoc
# 为指定文件的所有 export function 生成 JSDoc 注释
$ codex exec --approval-mode auto-edit \
"为 src/utils/helpers.ts 中所有导出函数添加完整的 JSDoc 注释,包括 @param、@returns 和 @example,保持函数实现不变"
生成单元测试
# 使用 timeout 命令防止无限等待(设置 5 分钟超时)
$ timeout 300 codex exec --full-auto \
"为 src/auth/login.ts 中的每个导出函数编写 Vitest 单元测试,测试文件保存到 src/auth/__tests__/login.test.ts,覆盖正常路径和边界情况"
RESULT=$?
if [ $RESULT -eq 124 ]; then
echo "超时!任务可能需要拆分为更小的子任务。"
fi
成本控制
在 CI/CD 中频繁调用 AI API 会积累成本,以下是经过验证的降本策略。
选择合适的模型
不同模型的成本差异极大,应根据任务复杂度选择:
| 模型 | 相对成本 | 适合场景 |
|---|---|---|
gpt-4.1 |
高(基准) | 复杂安全审查、深度重构、需要强推理的任务 |
gpt-4.1-mini |
低(约 1/20) | CHANGELOG 生成、代码格式化、简单注释、日常 PR 检查 |
gpt-4.1-nano |
极低(约 1/100) | 简单文本分类、格式转换、关键词提取 |
o4-mini |
中(按推理 token 计费) | 需要多步推理的复杂逻辑分析、算法优化 |
# 低成本任务:用 mini 模型 + quiet 模式(减少输出 token)
$ codex exec --model gpt-4.1-mini --quiet --full-auto \
"更新 CHANGELOG.md"
# 超时保护:防止因任务卡住产生不必要的 token 消耗
$ timeout 180 codex exec --model gpt-4.1-mini --quiet \
"分析 src/ 下最近修改的文件并输出摘要"
# 按文件路径过滤:只在关键文件变更时才运行 AI 任务
# (在 GitHub Actions YAML 中设置 paths: filter)
优化触发条件
- 路径过滤:在 GitHub Actions 的
on.pull_request.paths中限制只在源代码目录有变更时才触发,避免文档变更也跑一遍。 - 分支过滤:只在合并到主分支的 PR 上运行,不在 feature 分支的每次 push 上运行。
- 手动触发:对于昂贵的全量测试生成任务,使用
workflow_dispatch手动触发,而非在每次 PR 上自动运行。 - 任务具体化:越具体的任务描述通常消耗越少的 token,因为模型不需要"猜测"你想要什么。
常见错误与排查
退出码 1 — 任务描述不够清晰
最常见的失败原因之一。当任务描述模糊时,Codex 可能认为它完成了某种形式的任务(如输出了分析文字)但实际上没有达到预期效果,或者无法确定"完成"的标准而返回失败。
解决方法:在任务描述中明确指定:
- 要读取/修改的具体文件路径
- 期望的输出格式
- 成功的判断标准(如"运行 npm test 全部通过")
# 不好:模糊,容易返回退出码 1
codex exec "帮我检查代码"
# 好:具体,包含文件路径和期望输出
codex exec --full-auto \
"检查 src/api/ 目录下所有 .ts 文件,将发现的问题列表(每行一条)写入 code-issues.txt"
退出码 2 — 环境变量 OPENAI_API_KEY 未设置
Codex 在启动时会检查 OPENAI_API_KEY 环境变量,如果未设置则立即以退出码 2 退出。
排查步骤:
- 确认本地已设置:
echo $OPENAI_API_KEY(应有输出) - 在 GitHub Actions 中确认
env块正确嵌套在对应的step下 - 确认 Secret 名称大小写完全一致,应为
OPENAI_API_KEY - 在 OpenAI 控制台验证 Key 未过期且有余额
- name: Run codex exec
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # ← 必须在 step 级别
run: codex exec --full-auto "你的任务"
沙箱阻止写入 — 文件操作被拒绝
在 suggest 或受限沙箱模式下,Codex 会拒绝写入文件。这不会导致脚本崩溃,但任务实际上没有完成任何文件修改。
解决方法:对于需要修改文件的任务,使用 --full-auto;如果任务需要写入工作区以外的路径,使用 --dangerously-auto-approve-everything(需评估安全风险)。
任务超时 — CI Job 长时间未完成
Codex 在处理复杂任务时可能耗时较长,尤其是大型代码库的全量分析。
- 在 GitHub Actions 步骤中添加
timeout-minutes: 10 - 在命令行使用
timeout 300 codex exec ...(300 秒) - 将大任务拆分为多个具体的小任务,分步执行
- 使用
--model gpt-4.1-mini提升响应速度,降低延迟
git diff 返回空 — 无法分析 PR 变更
GitHub Actions 默认使用浅克隆(fetch-depth: 1),导致 git diff origin/main 等命令无法工作。
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 0 = 拉取全部历史,支持任意 git diff
常见问题 FAQ
codex exec 和直接运行 codex 有什么区别?
codex(无子命令)会打开全屏交互式 TUI,需要人工输入并逐步确认每个操作;codex exec 接受任务字符串作为参数,跳过所有 UI,执行完毕自动退出并返回退出码。前者为人设计,后者为机器设计。
codex exec 能在 Windows 上使用吗?
可以,但建议在 Windows Subsystem for Linux(WSL2) 中使用以获得最佳兼容性。原生 Windows PowerShell 或 CMD 在路径处理和沙箱机制上可能有兼容性问题。在 CI 中推荐直接使用 ubuntu-latest 镜像。
--quiet 模式会影响退出码吗?
不会。--quiet 只抑制 stdout 的中间过程日志输出,退出码的逻辑完全不受影响。成功时仍返回 0,失败时仍返回 1 或 2。在 CI 中推荐使用 --quiet 减少日志噪音,同时保留对退出码的完整处理能力。
可以在 codex exec 中使用自定义 AGENTS.md 吗?
可以。codex exec 会自动读取项目根目录的 AGENTS.md 文件作为系统提示词的一部分,用于规范模型行为。你可以在 AGENTS.md 中定义代码风格规范、禁止操作的文件路径、输出格式要求等,这些规则在所有 codex exec 调用中都会生效。
如何确认 codex exec 实际修改了哪些文件?
在任务执行后立即运行 git diff 或 git status,可以看到所有被修改的文件。在 CI 中,可以在 codex exec 步骤之后添加一个 run: git diff --stat 步骤,将修改摘要输出到 CI 日志中,便于审计和排错。