codex exec 完整指南:非交互模式、退出码与 CI 自动化

codex exec 是 Codex CLI 的非交互子命令——无 UI、无对话框、执行完毕即退出并返回退出码。它是将 AI 能力嵌入 GitHub Actions、GitLab CI、定时脚本的核心入口,本文从语法到生产实战全面讲解。

什么是 codex exec

codex exec 是 Codex CLI 1.0 引入的子命令,专为自动化和脚本集成场景设计。与打开全屏 TUI 的交互模式不同,codex exec 接受一条任务描述字符串,在后台调用模型完成任务,然后以退出码 0(成功)或非零(失败)退出。

它的核心价值在于三点:

  • 无需人工干预:没有审批弹窗,没有 stdin 等待,可以在完全无人值守的环境中运行。
  • 可靠的退出码:脚本和 CI 系统可以通过退出码判断任务是否成功,并据此决定流水线是否继续。
  • 可组合性:与 &&||timeoutif 等 Shell 原语无缝配合,可以构建复杂的自动化工作流。
i

典型使用场景:在每次 Pull Request 时自动运行代码风格检查、CHANGELOG 生成、安全扫描、单元测试补全,或者在定时任务中执行日报生成、数据处理等批量 AI 任务。

基本语法与所有参数

codex exec 的完整命令格式如下:

基本语法
codex exec [options] "<task>"

其中 <task> 是用自然语言描述的任务,通常用引号包裹。以下是所有支持的参数:

参数 简写 默认值 说明
--model <name> -m config.toml 中配置的模型 指定使用的模型,如 gpt-4.1-minio4-mini
--approval-mode <mode> -a suggest 设置审批模式:suggestauto-editfull-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、脚本、定时任务、批量处理
i

一个简单的判断方式:如果你需要"等人",用交互模式;如果你需要"等机器",用 codex exec

批准模式详解

批准模式(--approval-mode)控制 Codex 在执行读写文件、运行命令等操作时的行为。在非交互的 exec 场景下,选择合适的模式至关重要。

suggest 模式(默认)

这是默认模式。Codex 会生成代码建议和文件修改方案,但不会直接写入文件或执行命令——它只是将建议输出到 stdout。在 codex exec 中,这意味着你可以看到 Codex 的分析和建议,但工作区不会发生任何变化。

suggest 模式示例(只输出建议,不修改文件)
# 默认 suggest 模式:输出代码审查报告,不修改任何文件
$ codex exec "审查 src/ 目录下的代码,指出潜在的性能问题"

# 等价写法(明确指定)
$ codex exec --approval-mode suggest \
    "审查 src/ 目录下的代码,指出潜在的性能问题"

auto-edit 模式

Codex 可以自动读写工作区内的文件,但运行 Shell 命令(如 npm installgit commit)仍需确认。在 CI 中,如果任务只是修改代码文件而不需要执行命令,这是一个安全的选择。

auto-edit 模式示例(自动改文件,命令需确认)
# 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 推荐)
# 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 脚本中使用退出码:

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
i

GitHub Actions 默认在步骤退出码非零时标记为失败并停止后续步骤,无需额外处理。GitLab CI 行为相同。只有当你需要"失败时继续但记录"的特殊逻辑时才需要显式处理退出码。

GitHub Actions 集成

以下是一个完整的生产级 GitHub Actions 工作流,在每次 PR 时自动运行 Codex 进行代码检查和 CHANGELOG 更新。

.github/workflows/codex-ai-review.yml
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 注入方式。

i

在 GitLab 中配置 OPENAI_API_KEY:进入仓库 → Settings → CI/CD → Variables → Add variable。建议同时勾选 Masked(防止日志泄露)和 Protected(仅受保护分支可用)。

.gitlab-ci.yml
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 条目

生成 CHANGELOG
# 根据最近 10 个提交生成 CHANGELOG 条目并追加到文件顶部
$ codex exec --model gpt-4.1-mini --full-auto --quiet \
    "读取 git log --oneline -10 的输出,在 CHANGELOG.md 顶部追加一个 ## [Unreleased] 区块,每个提交一个条目,格式:- 类型: 描述"

自动修复 Lint 错误

Lint 自动修复
# 运行 lint 并自动修复所有可修复的错误
$ codex exec --full-auto --quiet \
    "运行 npm run lint 2>&1,分析输出,修复 src/ 目录下所有可自动修复的 ESLint 错误,然后再次运行 lint 确认无误"

批量生成 JSDoc

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 全部通过")
模糊 vs 清晰的任务描述
# 不好:模糊,容易返回退出码 1
codex exec "帮我检查代码"

# 好:具体,包含文件路径和期望输出
codex exec --full-auto \
  "检查 src/api/ 目录下所有 .ts 文件,将发现的问题列表(每行一条)写入 code-issues.txt"
退出码 2 — 环境变量 OPENAI_API_KEY 未设置

Codex 在启动时会检查 OPENAI_API_KEY 环境变量,如果未设置则立即以退出码 2 退出。

排查步骤

  1. 确认本地已设置:echo $OPENAI_API_KEY(应有输出)
  2. 在 GitHub Actions 中确认 env 块正确嵌套在对应的 step
  3. 确认 Secret 名称大小写完全一致,应为 OPENAI_API_KEY
  4. 在 OpenAI 控制台验证 Key 未过期且有余额
GitHub Actions 中正确注入 env
- 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 等命令无法工作。

修复方法:设置 fetch-depth
- 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,失败时仍返回 12。在 CI 中推荐使用 --quiet 减少日志噪音,同时保留对退出码的完整处理能力。

可以在 codex exec 中使用自定义 AGENTS.md 吗?

可以。codex exec 会自动读取项目根目录的 AGENTS.md 文件作为系统提示词的一部分,用于规范模型行为。你可以在 AGENTS.md 中定义代码风格规范、禁止操作的文件路径、输出格式要求等,这些规则在所有 codex exec 调用中都会生效。

如何确认 codex exec 实际修改了哪些文件?

在任务执行后立即运行 git diffgit status,可以看到所有被修改的文件。在 CI 中,可以在 codex exec 步骤之后添加一个 run: git diff --stat 步骤,将修改摘要输出到 CI 日志中,便于审计和排错。