Codex CLI Debugging Guide
Verbose mode · Log levels · Dry-run preview · Common failure patterns
codex --version.
1. Why debug Codex?
Codex CLI is an AI agent — it receives tasks, plans steps, invokes tools (write files / run commands), and waits for feedback. When it "hangs" or behaves unexpectedly, the root cause can live at multiple layers:
| Layer | Symptom | Debug approach |
|---|---|---|
| Network | No output, endless wait | --verbose to check connection |
| Auth | 401 / 403 errors | Check API key and env vars |
| Model | Poor output quality, hallucinations | Debug logs to inspect prompt; tune AGENTS.md |
| Tool calls | Wrong file edited, command fails | dry-run preview; narrow the task scope |
| Rate limit | 429 Too Many Requests | Confirm via logs; switch model or slow down |
With a few debugging tools, most issues can be pinpointed within 5 minutes.
2. --verbose: the fastest debug switch
--verbose (alias -v) is the most commonly used debugging tool. It works in both interactive and non-interactive modes.
Interactive mode
# Start an interactive session with verbose output
$ codex --verbose
# Short form
$ codex -v
Non-interactive mode (exec)
$ codex exec --verbose "Add unit tests for auth.py"
# Combined with model selection
$ codex exec -v --model o4-mini "Optimize this SQL query"
What does --verbose expose?
- HTTP requests: every request to the OpenAI API (URL, status code, latency)
- Token usage: prompt tokens / completion tokens per turn
- Tool calls: which tool Codex invokes (write_file, run_command, etc.) and its arguments
- Sandbox events: command execution results and exit codes inside the sandbox
- Full error details: complete stack traces (normal mode shows abbreviated messages)
codex -v 2>&1 | tee codex-debug.log
3. CODEX_LOG_LEVEL: fine-grained control
The CODEX_LOG_LEVEL environment variable provides more granular control than --verbose.
| Level | Output | When to use |
|---|---|---|
error | Errors only (default) | Normal operation |
warn | Warnings + errors | Watch for potential issues |
info | Basic run information | Understanding execution flow |
debug | Full API requests/responses, tool call parameters | Deep troubleshooting |
trace | All internal events (very verbose) | Development / bug reports |
# Temporary — current session only
$ CODEX_LOG_LEVEL=debug codex
# Persistent — add to shell config
$ echo 'export CODEX_LOG_LEVEL=info' >> ~/.zshrc
# Also works with exec
$ CODEX_LOG_LEVEL=debug codex exec "Generate API docs" 2> debug.log
Typical debug output example
[debug] POST https://api.openai.com/v1/chat/completions 200 (1243ms)
[debug] usage: { prompt_tokens: 3842, completion_tokens: 156, total_tokens: 3998 }
[debug] tool_call: write_file { path: "src/auth.test.ts", content: "..." }
[debug] sandbox: run_command "npm test" exit=0
debug/trace levels output prompt content (truncated) in logs, which may include code file contents. Avoid storing these logs on public logging platforms.
4. --dry-run: preview before executing
--dry-run tells Codex to plan the full execution steps without actually modifying any files or running any commands. Essential before high-risk operations.
# See how Codex would refactor — no actual changes
$ codex exec --dry-run "Convert all synchronous functions in user_controller.py to async"
# Always dry-run destructive operations first
$ codex exec --dry-run "Delete all .bak files under src/"
# Combine with verbose for more detail
$ codex exec --dry-run --verbose "Refactor the database connection pool"
Sample dry-run output
📋 Planned actions (DRY RUN — nothing will be executed):
Step 1: Read user_controller.py
Step 2: Identify synchronous function definitions (found 7)
Step 3: Rewrite functions with async/await patterns
Step 4: Update import: add 'asyncio'
Step 5: Write modified file → user_controller.py
Files that WOULD be modified: [user_controller.py]
Commands that WOULD run: none
Total estimated tokens: ~4200
When to use dry-run
- Tasks involving file deletion or large-scale modifications
- In CI/CD pipelines — dry-run first to validate Codex's plan, then execute for real
- Demos for new team members to show what Codex will do
- Debugging prompt wording — compare planned actions for different prompt variants
5. Reading log output
With verbose enabled, logs can be voluminous. Here's how to interpret the key fields:
HTTP status codes
| Status | Meaning | Fix |
|---|---|---|
200 | Success | — |
401 | Invalid or missing API key | Check OPENAI_API_KEY; or run codex login |
403 | Insufficient permissions / geo-blocked | Check account type; verify proxy exit IP |
429 | Rate limit exceeded | Wait 60s; switch to a less-used model |
500/503 | OpenAI server error | Check status.openai.com; retry later |
ECONNREFUSED | Connection refused | Proxy not running or wrong port |
ETIMEDOUT | Connection timed out | High proxy latency or DNS poisoning |
Token usage
[debug] usage: {
prompt_tokens: 12453, ← tokens sent to the model (includes context)
completion_tokens: 892, ← tokens the model generated
total_tokens: 13345 ← total consumed this turn
}
When prompt_tokens exceeds 15,000, consider:
- Using
.codexignoreto exclude unnecessary files - Optimizing
AGENTS.mdto remove redundant instructions - Breaking large tasks into multiple smaller ones
Tool call logs
[debug] tool_call: read_file { path: "src/api/users.ts" }
[debug] tool_call: write_file {
path: "src/api/users.ts",
content: "import { ... }" ← truncated
}
[debug] tool_call: run_command { command: "npx tsc --noEmit" }
[debug] sandbox: exit=2, stderr: "error TS2345: ..."
6. Five common failure patterns
Pattern 1: Codex starts but produces no output
codex, the cursor blinks, nothing appears — no error either.
Diagnostic steps:
# Step 1: enable verbose — check for any HTTP logs
$ codex --verbose
# Step 2: test whether the proxy works
$ curl -v https://api.openai.com/v1/models \
-H "Authorization: Bearer $OPENAI_API_KEY"
# Step 3: confirm proxy env vars are set
$ env | grep -i proxy
Common causes: HTTPS_PROXY not set; proxy process not running; socks5 proxy (Codex doesn't support it — convert to http).
Pattern 2: Poor output quality / task misunderstanding
Diagnostic steps:
# Step 1: dry-run to verify Codex's execution plan
$ codex exec --dry-run "[your task]"
# Step 2: check prompt content in debug logs
$ CODEX_LOG_LEVEL=debug codex exec "[task]" 2> prompt-debug.log
# Step 3: generate AGENTS.md to set explicit constraints
$ codex /init
Fix: Specify file paths explicitly in your prompt; improve the project structure section of AGENTS.md; break vague large tasks into concrete smaller steps.
Pattern 3: 429 rate limit firing frequently
[error] 429 Too Many Requests, task aborted.
# Check which model is hitting 429
$ CODEX_LOG_LEVEL=info codex exec "..." 2>&1 | grep -i "429\|model\|rate"
# Switch to a model with lower usage
$ codex exec --model gpt-4.1-mini "..."
# Set default model in config.toml
# model = "gpt-4.1-mini"
Fix: Wait 60 seconds and retry; switch model (o4-mini → gpt-4.1-mini); upgrade API quota tier; spread batch tasks over multiple time windows.
Pattern 4: Sandbox command failures
# Find sandbox command output in verbose logs
$ codex --verbose
# Look for: [debug] sandbox: exit=1, stderr: "..."
# In AGENTS.md, specify test commands so Codex can self-verify
# ## Testing
# - Always run `npm test` to validate changes
# - TypeScript: `npx tsc --noEmit` for type checking
Fix: Explicitly specify compile/test commands in AGENTS.md. When Codex fails in the sandbox it tries to self-correct — ensure the approval mode allows it (auto-edit or full-auto).
Pattern 5: Auth expiry / session interruption
# Check whether both auth methods are conflicting
$ env | grep OPENAI_API_KEY # output = using API key
$ cat ~/.codex/auth.json 2>/dev/null # content = using OAuth
# Conflict: remove OAuth, use API key only
$ rm ~/.codex/auth.json
$ export OPENAI_API_KEY="sk-..."
# Or: OAuth only, no API key
$ unset OPENAI_API_KEY
$ codex login
7. Debug checklist
When something breaks, work through this list in order:
8. FAQ
How do I enable verbose logging in Codex CLI?
Two options: ① add --verbose when running Codex (codex --verbose); ② set the env var CODEX_LOG_LEVEL=debug. The flag applies only to the current session; the env var persists.
What does Codex dry-run do?
codex exec --dry-run 'task' plans the full execution steps without actually modifying files or running commands. Use it to verify Codex's understanding before committing.
Codex is stuck with no output — what do I do?
Run with --verbose: if you see no HTTP logs, the connection is failing (check proxy). If you see API logs but no result, the issue is on the model side. Common causes: missing HTTPS_PROXY, invalid API key, or 429 rate limiting.
How can I see Codex's API request content?
Set CODEX_LOG_LEVEL=debug — logs will show a truncated version of the prompt sent to the API and token usage per turn, helping you optimize your AGENTS.md.
Can I save debug logs to a file?
Yes: codex -v 2>&1 | tee codex-debug.log (interactive), or CODEX_LOG_LEVEL=debug codex exec "..." 2> debug.log (non-interactive). Logs go to stderr by default — redirect stderr with 2>.