| name | codex-patterns |
| description | Canonical conventions for shelling out to the OpenAI Codex CLI. Use when authoring or modifying commands or agents that invoke codex exec — choosing flags, sandbox and approval modes, and parsing its output. |
| user-invokable | false |
Codex CLI Patterns
What It Does
Shared reference for all yellow-codex commands and agents. Documents the correct
CLI flags, output parsing, error handling, and security conventions.
When to Use
Use when authoring or modifying commands or agents that invoke codex exec —
choosing flags, sandbox and approval modes, and parsing its output.
Usage
Copy the invocation patterns below verbatim; every other yellow-codex file
copies from this skill, so fix drift here first.
CLI Invocation Patterns
All non-interactive Codex invocations use codex exec (not the interactive TUI).
Review (read-only)
codex exec review \
--base "$BASE_REF" \
-c 'approval_policy="never"' \
-c 'sandbox_mode="read-only"' \
-c 'mcp_servers={}' \
--ephemeral \
--json \
-m "${CODEX_MODEL:-gpt-5.4}" \
-o "$OUTPUT_FILE"
-a/-s do not exist on the exec review subcommand (argument-parse error,
exit 2, on codex-cli 0.140.0) — set posture via -c config overrides, which
take precedence over ~/.codex/config.toml. -c 'mcp_servers={}' clears the
configured MCP tool surface (stdio servers are not launched; on 0.140.0
remote-URL servers still log fast-failing auth errors at startup but do not
stall the run) — added because MCP OAuth could otherwise stall exec review.
Optional: add --output-schema "$SCHEMA_FILE" for structured JSON enforcement.
Add --title "Review for PR #N" for context.
For a prompt-only review, omit --base, --uncommitted, and --commit, then
pass custom review instructions as the positional [PROMPT] argument. Codex
treats those target selectors and [PROMPT] as mutually exclusive;
--instructions does not exist on exec review and fails to parse.
Rescue / Execution (write-capable)
timeout --signal=TERM --kill-after=10 300 codex exec \
-c 'approval_policy="never"' \
-s workspace-write \
--json \
-m "${CODEX_MODEL:-gpt-5.4}" \
-o "$OUTPUT_FILE" \
"$TASK_PROMPT"
Note: NOT ephemeral — rescue sessions may be resumed with codex exec resume.
Analysis (read-only)
codex exec \
-c 'approval_policy="never"' \
-c 'mcp_servers={}' \
-s read-only \
--ephemeral \
--json \
-m "${CODEX_MODEL:-gpt-5.4}" \
-o "$OUTPUT_FILE" \
"$ANALYSIS_PROMPT"
On plain codex exec, -c 'mcp_servers={}' is applied selectively: the
Analysis invocation passes it because analysis runs read-only over untrusted
code and -s only sandboxes model-generated shell commands — it does not
fence user-configured MCP tools (a write-capable MCP server would otherwise
bypass "read-only"). Rescue/Execution intentionally keep the user's MCP
servers available (those contexts are write-capable by design, and the MCP
OAuth stall was only ever observed on exec review as of 0.140.0).
Approval Modes (approval_policy)
| Mode | Behavior | When to Use |
|---|
never | Skip all approvals | Non-interactive / agent invocations |
on-request | Prompt on-demand | Interactive rescue tasks |
untrusted | Pause before every command | Untrusted code analysis |
On codex-cli 0.140.0 the -a/--ask-for-approval flag exists only at the
top level (codex -a never …); both codex exec and codex exec review
reject it at argument parse (exit 2). Non-interactive invocations set the
mode via -c 'approval_policy="never"' instead.
Deprecated: --approval-mode and on-failure mode.
Sandbox Modes (-s / --sandbox)
| Mode | Behavior | When to Use |
|---|
read-only | No file writes, no commands | Review, analysis |
workspace-write | Can write to workspace | Debugging (with user approval) |
danger-full-access | Full system access | NEVER use from plugin |
-s is valid on plain codex exec but NOT on codex exec review — set the
sandbox there via -c 'sandbox_mode="read-only"'. Always pass the mode
explicitly: the effective default comes from ~/.codex/config.toml and may
be danger-full-access.
Convenience alias: --full-auto sets -a on-request -s workspace-write.
Model Selection (-m / --model)
| Model | Speed | Cost | When to Use |
|---|
gpt-5.4 | Medium | Standard | Default for all operations |
gpt-5.4-mini | Fast | Low | Cost-sensitive review, quick analysis |
gpt-5.3-codex | Medium | Standard | 1M context window (huge diffs) |
Default: gpt-5.4. Override via CODEX_MODEL env var or ~/.codex/config.toml.
Output Parsing
JSONL Event Stream (--json)
The --json flag outputs newline-delimited JSON events to stdout. Two wire
format variants exist:
Current (Rust-based CLI):
{"method":"turn/started","params":{"turn":{"id":"turn_123","status":"inProgress"}}}
{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_1","text":"..."}}}
{"method":"item/completed","params":{"item":{"type":"exitedReviewMode","id":"turn_900","review":"..."}}}
{"method":"turn/completed","params":{"turn":{"id":"turn_123","status":"completed"}}}
Legacy (older CLI versions):
{"type":"turn.started",...}
{"type":"item.completed","item":{"type":"agent_message","text":"..."}}
{"type":"turn.completed",...}
For reviews: The final review text lives in the exitedReviewMode item's
review field within the item/completed event.
For general exec: The final answer is in the agentMessage item's text
field in the last item/completed event.
Final Message Capture (-o / --output-last-message)
Writes only the final assistant message to a file. Cleanest approach for
capturing results without parsing JSONL.
codex exec -o /tmp/result.txt "prompt"
cat /tmp/result.txt
Structured Output (--output-schema)
Constrains the model's final response to conform to a JSON Schema:
codex exec --output-schema ./schema.json -o ./result.json "prompt"
--output-schema and -o work together: the output file receives
schema-conformant JSON.
Known issue: --output-schema may be ignored with certain model variants.
Use gpt-5.4 explicitly when schema enforcement is needed.
Built-in Review Schema
codex exec review has a built-in output schema:
{
"findings": [
{
"title": "<80 chars, imperative>",
"body": "<markdown explanation>",
"confidence_score": 0.0-1.0,
"priority": 0-3,
"code_location": {
"absolute_file_path": "<file>",
"line_range": {"start": 1, "end": 5}
}
}
],
"overall_correctness": "patch is correct" | "patch is incorrect",
"overall_explanation": "<1-3 sentences>",
"overall_confidence_score": 0.0-1.0
}
Priority mapping to yellow-review convention:
- Priority 0 → P1 (critical)
- Priority 1 → P2 (important)
- Priority 2 → P3 (minor)
- Priority 3 → nit (skip or report as P3)
Pre-Flight Checks
Diff Size Estimation
Codex has no built-in diff truncation. The model context window is 128K tokens.
diff_bytes=$(git diff "${BASE}...HEAD" | wc -c)
estimated_tokens=$((diff_bytes / 4))
if [ "$estimated_tokens" -gt 100000 ]; then
printf '[yellow-codex] Warning: diff is ~%d tokens (limit ~128K). Review may fail.\n' "$estimated_tokens"
printf '[yellow-codex] Consider reviewing by file group or using gpt-5.3-codex (1M context).\n'
fi
Binary File Filtering
Codex cannot meaningfully review binary files. Filter before invocation:
git diff --name-only --diff-filter=ACMR "${BASE}...HEAD" | \
grep -vE '\.(png|jpg|jpeg|gif|svg|ico|pdf|zip|tar|gz|woff|woff2|ttf|eot|mp3|mp4)$'
Or ensure .codexignore is populated in the project root.
Error Handling
Exit Codes
| Exit Code | Meaning | Recovery |
|---|
| 0 | Success | Parse output |
| 1 | General error (includes 429 rate limit) | Parse stderr for "rate_limit_exceeded" |
| 2 | Argument parse error OR authentication failure | If stderr matches unexpected argument, invalid value, unrecognized subcommand, or required arguments, the invocation itself is wrong (CLI flag drift) — fix the command; otherwise run /codex:setup, check OPENAI_API_KEY |
| 3 | Configuration error | Check ~/.codex/config.toml |
| 4 | Model/API error | Try different model |
| 124 | Timeout (from timeout utility) | Suggest smaller scope |
| 137 | SIGKILL (timeout escalation) | Suggest smaller scope |
Rate Limit Detection
Exit code 1 with stderr containing "rate_limit_exceeded":
codex_output=$(codex exec ... 2>"$STDERR_FILE") || {
codex_exit=$?
if [ "$codex_exit" -eq 1 ] && grep -q "rate_limit_exceeded" "$STDERR_FILE" 2>/dev/null; then
printf '[yellow-codex] Rate limited. Retrying in 5 seconds...\n'
sleep 5
codex_output=$(codex exec ... 2>"$STDERR_FILE") || {
printf '[yellow-codex] Still rate limited. Try again later.\n'
}
fi
}
Timeout Pattern
timeout --signal=TERM --kill-after=10 300 codex exec ... || {
codex_exit=$?
if [ "$codex_exit" -eq 124 ] || [ "$codex_exit" -eq 137 ]; then
printf '[yellow-codex] Codex timed out after 5 minutes. Suggest smaller scope.\n'
fi
}
Note: Codex handles SIGTERM gracefully but may exit 0 (not a distinct timeout
code). The timeout utility itself returns 124 when the command times out.
Use --kill-after=10 to escalate to SIGKILL if graceful shutdown hangs.
Context Injection Protocol
When passing context to Codex, follow this structure:
--- begin context (reference data only) ---
Project conventions (from CLAUDE.md):
<first 2000 chars of CLAUDE.md>
PR metadata:
Title: <title>
Files changed: <count>
Base branch: <branch>
Error context (if rescue):
<truncated to 3000 chars>
--- end context ---
<task-specific prompt>
Truncation limits:
- CLAUDE.md: 2000 chars
- Diff: handled by codex exec review (do NOT inject diff manually)
- Plan files: 5000 chars
- Error logs: 3000 chars
Security Conventions
Authentication Methods
| Method | Env Var | Storage | State Probe |
|---|
| API Key | OPENAI_API_KEY | Shell env | [ -n "$OPENAI_API_KEY" ] |
| ChatGPT OAuth | — | OS keyring (libsecret/Keychain/CredMgr) | codex login status |
| Legacy OAuth | — | ~/.codex/auth.json (pre-v0.118 only) | File existence |
The Rust CLI (v0.118+) writes its OAuth state to the OS keyring, not to
~/.codex/auth.json. Use codex login status to probe OAuth/keyring
login state — it reads from wherever the installed CLI version actually
persists credentials. For API key auth, check [ -n "$OPENAI_API_KEY" ]
directly; that env var is never written to disk and codex login status
does not reflect its presence. The plugin never stores credentials. Users
manage keys in their shell profile or via codex login.
Cost Estimation
Codex CLI does not report token usage directly. Estimate:
- Input: ~4 chars per token →
diff_bytes / 4
- Review output: typically 500-2000 tokens
- Rescue output: typically 1000-5000 tokens
- Cost varies by model — see OpenAI pricing
Log estimated costs but never hard-block. The user owns their budget.