Codex CLI in GitHub Actions: production-grade CI integration
Plug Codex CLI into GitHub Actions for automatic PR review / test generation / doc sync. Covers OAuth vs API-key auth, npm caching, worktree concurrency isolation, audit and budget guardrails.
How to
Prepare OpenAI auth
Create an OAuth credential (org-scoped) in the OpenAI console, note the device-flow client id + secret. Store the client secret in the repo's secret OPENAI_OAUTH_CLIENT_SECRET.
Write the workflow file
Create .github/workflows/codex-review.yml: on pull_request → checkout → install Codex CLI → exchange device-flow token → run codex exec --json review diff → post PR comment.
Add caching and concurrency
Add actions/cache (key: codex-npm-${{ hashFiles('package-lock.json') }}) and concurrency field limiting one review job per PR at a time.
Wire audit and budget
Set MAX_TOKENS=50000 env, upload Codex JSON output as artifact (7 day retention), set monthly budget in the OpenAI console.
Test-run and tune the prompt
Open a test PR to trigger the workflow. Common adjustments: (1) include diff context in prompt; (2) cap review scope to 200 lines; (3) require JSON output for downstream automation.
Running Codex locally makes one developer faster. Running it in CI makes the whole team faster. This guide walks you through wiring Codex into GitHub Actions: four canonical use cases, two auth options, concurrency isolation, caching, and audit guardrails. A reusable workflow template closes the article.
Why put Codex in CI
Local Codex = one user. CI Codex = whole team. Three differences that count:
- Consistency: every PR passes the same AI review, no more "some PRs reviewed, some not".
- Audit trail: CI output is auto-archived as artifact, ready for compliance, post-mortem, or replay.
- Scale: a single machine is one Codex; CI scales to dozens of concurrent review jobs.
The cost is CI complexity: auth, caching, concurrency. We tackle each below.
Scenario matrix: pick the pain you want to solve first
| Scenario | Input | Output | Recommended model | Avg tokens |
|---|---|---|---|---|
| PR auto-review | diff + PR description | review comment (inline + summary) | gpt-5.6-terra | 20k-50k |
| Test gen | source + interface contract | new test files + unit tests | gpt-5.6-sol | 30k-80k |
| Doc sync | changed files + README | updated docs (README / API doc) | gpt-5.6-luna | 10k-30k |
| Weekly digest | git log + Slack | markdown weekly digest | gpt-5.6-luna | 5k-15k |
Start with PR auto-review - one file, clear input, high impact. Weekly digest is simplest but easy to deprioritize.
Auth: API key vs OAuth
# Not recommended: API key
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# Recommended: OAuth device flow
env:
OPENAI_OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }}
OPENAI_OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }}
API key problem: one secret leak = rotate every key in every repo (the key is account-wide). OAuth device-flow win: short-lived refresh tokens (default 1 hour), per-repo revocable, blast radius is one repo.
OAuth setup is one-time: in the OpenAI console, API Keys → OAuth, create an org-scoped credential, note the client id + secret.
Concurrency isolation
The biggest CI Codex footgun is "two concurrent jobs writing to the same worktree". Three rules:
jobs:
codex-review:
runs-on: ubuntu-latest
# Rule 1: one job per PR at a time
concurrency:
group: codex-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
with:
# Rule 2: each job gets its own worktree
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
- name: Install Codex CLI
run: npm install -g @openai/codex
env:
# Rule 3: each job gets its own config dir
CODEX_HOME: /tmp/codex-${{ github.run_id }}
Three guardrails: concurrency limits one job per PR + checkout to independent worktree + Codex config in a temp dir.
Caching: 90s to 20s
- name: Cache Codex + npm
uses: actions/cache@v4
with:
path: |
~/.npm
~/.codex
key: codex-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
codex-${{ runner.os }}-
~/.npm: npm global package cache (Codex CLI installs globally)~/.codex: Codex config cache (OAuth tokens, prompt cache)
Result: second workflow run averages 90s → 20s.
Audit guardrails
Codex in CI carries a "AI breaks the codebase" compliance risk. Three gates:
- Log trail: every
--jsonCodex output saved as artifact (7 day retention) for incident replay. - Human gate: auto-PRs require at least one human approval (branch protection:
required_approving_review_count: 1). - Token budget: workflow-level
MAX_TOKENScap prevents prompt anomalies from burning tokens.
- name: Run Codex review
run: codex exec --json "review diff" > codex-output.json
env:
MAX_TOKENS: 50000
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: codex-review-${{ github.event.pull_request.number }}
path: codex-output.json
retention-days: 7
Working template: PR review workflow
name: Codex PR Review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
codex-review:
runs-on: ubuntu-latest
concurrency:
group: codex-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Codex CLI
run: npm install -g @openai/codex
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.npm
~/.codex
key: codex-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Run Codex review
id: review
run: |
codex exec --json \
"Review the following PR diff. Focus on: bugs, edge cases, test coverage. Output as JSON with keys: summary, issues[]. Provide line-level comments." \
< <(git diff origin/${{ github.base_ref }}...HEAD) \
> codex-review.json
env:
MAX_TOKENS: 50000
OPENAI_OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }}
OPENAI_OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }}
- name: Post review comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = JSON.parse(fs.readFileSync('codex-review.json', 'utf8'));
const body = [
'## Codex Review',
'**Summary**: ' + review.summary,
'',
'**Issues**:',
...review.issues.map(i => `- ${i.file}:${i.line} - ${i.message}`)
].join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body
});
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: codex-review-${{ github.event.pull_request.number }}
path: codex-review.json
retention-days: 7
Swap in your own OAUTH_CLIENT_ID / OAUTH_CLIENT_SECRET and you are live.
Common pitfalls
- Reusing OAuth tokens across jobs: each job must run its own device flow. Do not cache the refresh token with
actions/cache. - Diff too large for context: over 500 lines, split into multi-pass review or use
git diff --unified=0to drop context. - Codex touches files outside review scope: force read-only with
codex exec --readonlyto prevent scope creep. - Artifacts fill storage: gzip the JSON output (
codex-review.json.gz). - Prompt has no output format constraint: Codex drifts. Require JSON / table / inline-comment explicitly.
Next steps
- New to Codex locally? Read Getting started with OpenAI Codex CLI: from install to daily use.
- Multi-branch team workflow with worktrees? Read Codex Team Workflow: worktrees, reviews, and CI integration.
- Curious about the model family? Read The complete guide to GPT models (2026-07): GPT-5.6 Sol, Terra, Luna.
Key points
- Prefer OAuth device-flow over API-key auth: short-lived refresh tokens, per-repo revocation, much smaller blast radius if leaked
- Concurrency safety via worktree: each job checks out to an independent worktree (ref: pull_request.head.ref) so Codex edits never pollute the main branch
- Two-layer caching: actions/cache for ~/.npm + ~/.codex cuts workflow time from 90s to 20s on subsequent runs
- Audit guardrails: verbose logs to artifact, human approval gate on every auto-PR, MAX_TOKENS budget to prevent runaway spend
- Prompt template per scenario: PR review needs diff, test gen needs source + interface contract, doc sync needs README, weekly digest needs git log
Frequently asked questions
Official references
Related articles
Codex CLI vs Cursor vs Aider vs Claude Code: 2026 AI coding tools compared
Codex CLI / Cursor / Aider / Claude Code side-by-side: positioning, model support, UI/UX, CI fit, cost curve, migration cost. Decision matrix for teams and individual developers.
Read articleCodex Team Workflow: worktrees, reviews, and CI integration
How to use Codex CLI in a team without breaking things: independent git worktrees, diff review, CODEOWNERS, CI integration, sensitive-path whitelist, and PR review checklist.
Read articleGetting started with OpenAI Codex CLI: from install to daily use
A practical guide to installing OpenAI's Codex CLI, configuring auth, shipping your first change, and integrating it into daily coding.
Read articleSubscribe to GPTMap Weekly
One email every Monday: curated OpenAI updates, deep dives, and best practices. No ads, unsubscribe anytime.