cheat sheet
Codex Configuration
Complete config.toml reference for Codex CLI — model selection, approval policies, sandbox modes, profiles, MCP server stubs, shell environment, notify hooks, and project trust levels.
Codex Configuration
What it is
Codex CLI is configured via a TOML file at ~/.codex/config.toml. A project-level .codex/config.toml inside a trusted project directory is merged on top of the user config, letting you set per-repo model, approval, and sandbox overrides without touching your global defaults.
File location
Codex resolves configuration by reading the global config first, then layering the project-level config on top if the current project is trusted. The merge is a deep merge — tables compose, but scalar keys are overwritten from highest priority (project) to lowest (global). Set CODEX_HOME to relocate the entire configuration tree (handy for project-scoped sandboxes or testing).
| File | Purpose |
|---|---|
~/.codex/config.toml | Global user configuration |
<project>/.codex/config.toml | Project-level overrides (requires trust) |
CODEX_HOME/config.toml | Override base dir via env var CODEX_HOME |
Inspect the merged active config:
codex --print-config
Output:
model = "gpt-4o"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
profile = "sprint"
project_doc_max_bytes = 65536
[history]
persistence = "save"
...
Minimal config
A three-line config.toml is enough to fully configure Codex for day-to-day development. Everything else has sane defaults. Start here and add keys only when the default behaviour does not match what you need.
model = "gpt-4o"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
Output: (none — config file, not a runnable command)
Verify it parses:
codex --print-config | head -3
Output:
model = "gpt-4o"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
Model settings
Sets the default model and provider for all Codex sessions. The model key takes the model name; model_provider selects the API backend ("openai" by default, or "azure" / a custom endpoint); model_reasoning_effort controls how much compute reasoning models spend before responding.
# The model to use for all sessions
model = "gpt-4o"
# Alternative provider (e.g., "azure", "custom")
model_provider = "openai"
# Reasoning effort: "minimal" | "low" | "medium" | "high" | "xhigh"
model_reasoning_effort = "medium"
GPT-5 family models (as of 2026): gpt-5, gpt-5-pro, gpt-5.5, gpt-5.4, gpt-5.3-codex.
Per-model effort overrides
You can override model_reasoning_effort per profile, so a "deep" profile spends more compute and a "quick" profile spends less:
[profiles.deep]
model = "gpt-5-pro"
model_reasoning_effort = "xhigh"
[profiles.quick]
model = "gpt-5"
model_reasoning_effort = "minimal"
Listing available models
codex models
Output:
gpt-4o general purpose, vision
gpt-4o-mini cheap and fast
gpt-5 reasoning model, default
gpt-5-pro flagship reasoning
gpt-5.3-codex code-tuned variant
Approval policy
Controls when Codex asks for your approval before executing commands. The default for interactive sessions is "on-request" (Codex only asks when sandbox escalation would be needed), and the default for codex exec is "never". The approval_policy setting in config.toml overrides both defaults; pass -a on the command line to override per-invocation.
# "untrusted" — always prompt on mutating commands (safest)
# "on-request" — prompt when sandbox escalation is needed (default interactive)
# "on-failure" — prompt after a command fails (deprecated)
# "never" — never prompt (default for codex exec / non-interactive)
approval_policy = "on-request"
See Approvals & Sandbox for full detail.
Sandbox mode
Controls what the agent is allowed to do to your filesystem and network without an explicit approval. "workspace-write" is the practical default for most development work — it confines writes to the current working directory and blocks outbound network. Use "read-only" for untrusted code review and "danger-full-access" only inside disposable containers.
# "read-only" — no filesystem writes, no network
# "workspace-write" — writes confined to cwd, network blocked by default
# "danger-full-access" — no restrictions (use only in trusted containers)
sandbox_mode = "workspace-write"
Shell environment
Determines which environment variables are visible to the commands Codex runs. "inherit" (the default) passes your full shell env through, which is convenient but may leak secrets; "clean" starts with a minimal env; "custom" uses only the variables you define in the [env] table below.
[shell_environment_policy]
# "inherit" — pass through the parent shell's env vars (default)
# "clean" — start with a minimal env
# "custom" — set only the vars in [env] below
inherit = "inherit"
[env]
MY_VAR = "value"
History persistence
Controls whether session transcripts are written to disk. With "save", full conversation history is stored under ~/.codex/history/ and can be resumed or audited later. Use "no-save" when working with sensitive data you do not want persisted locally.
[history]
# "save" — persist session transcripts to ~/.codex/history/
# "no-save" — ephemeral sessions only
persistence = "save"
Profiles
A "profile" is a named bundle of overrides — model, reasoning effort, approval policy, sandbox mode — that you activate per-invocation with -p <name>. Profiles let you keep a conservative default (e.g., on-request + workspace-write) while still having a one-flag escape hatch for read-only review or CI use. Profile values override the top-level keys but are themselves overridden by command-line flags. Named profiles let you switch model/approval/sandbox combos with -p <name> or codex --profile <name>.
[profiles.quick]
model = "gpt-4o-mini"
approval_policy = "never"
sandbox_mode = "workspace-write"
[profiles.deep]
model = "gpt-5-pro"
model_reasoning_effort = "xhigh"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
[profiles.safe-review]
model = "gpt-4o"
approval_policy = "untrusted"
sandbox_mode = "read-only"
Activate a profile:
codex --profile deep
Output: (TUI opens using gpt-5-pro at xhigh reasoning)
Set a default profile:
profile = "quick"
List defined profiles:
codex profiles
Output:
quick gpt-4o-mini never workspace-write
deep gpt-5-pro on-request workspace-write
safe-review gpt-4o untrusted read-only
ci gpt-4o-mini never workspace-write
Inspect a single profile:
codex profiles show deep
Output:
[profiles.deep]
model = "gpt-5-pro"
model_reasoning_effort = "xhigh"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
Project trust
Project trust is Codex's escape hatch for "should I load arbitrary config and hooks from this directory?". A new directory is untrusted by default; loading its .codex/config.toml would let a malicious repo silently disable your sandbox or wire up a hook that exfiltrates env vars. Trusting a directory in ~/.codex/config.toml opts it in to those overrides. Codex only loads .codex/config.toml and .codex/hooks.json from a project directory if the project is trusted.
[projects."/home/alice/myproject"]
trust_level = "trusted"
[projects."/home/alice/untrusted-repo"]
trust_level = "untrusted"
Trust a project interactively on first run — Codex prompts you to trust the directory and writes the entry automatically.
List trusted projects:
codex projects list
Output:
/home/alice/myproject trusted
/home/alice/work/api trusted
/home/alice/notes untrusted
Trust a project from the CLI:
codex projects trust /home/alice/myproject
Output:
Trusted /home/alice/myproject
Revoke trust:
codex projects untrust /home/alice/myproject
Output:
Removed trust for /home/alice/myproject
Notify (turn-complete callback)
Run an external command whenever an agent turn completes. Useful for desktop notifications or logging.
notify = ["python3", "/path/to/notify.py"]
The command receives a JSON payload on stdin:
{
"type": "agent-turn-complete",
"thread-id": "th_01abc",
"turn-id": "t_01xyz",
"cwd": "/home/alice/myproject",
"input-messages": [...],
"last-assistant-message": "Done. Added docstrings to 12 functions."
}
Example notify script:
import json, sys, subprocess
data = json.load(sys.stdin)
msg = data.get("last-assistant-message", "Codex turn complete")
subprocess.run(["osascript", "-e", f'display notification "{msg}" with title "Codex"'])
Output: (none — stdout from notify.py is discarded)
File opener
Specifies the editor command Codex invokes when you ask it to open a file (e.g., "open that file in my editor"). Accepts any command on your PATH — "cursor", "code", "vim", "nvim", etc. Defaults to the value of $EDITOR if unset.
file_opener = "cursor" # or "code", "vim", "nvim", etc.
AGENTS.md config
AGENTS.md (or a fallback like CLAUDE.md) is a per-project instruction file that Codex reads automatically when it starts in a trusted directory. These keys control how large that file may be and what filenames to look for, letting you standardize on a single instruction file name across a mixed-agent workflow.
# Max bytes to read from AGENTS.md (default 32768)
project_doc_max_bytes = 65536
# Filenames to look for as project instructions (in order)
project_doc_fallback_filenames = ["AGENTS.md", "CLAUDE.md", "COPILOT-INSTRUCTIONS.md"]
Telemetry and updates
Codex sends anonymous usage telemetry by default. Disable globally:
[telemetry]
enabled = false
Or per-invocation via env var:
CODEX_NO_TELEMETRY=1 codex
Output: (TUI opens; no telemetry pings sent)
Disable update checks:
[updates]
check_for_updates = false
Full annotated example
A representative ~/.codex/config.toml showing how the top-level keys, profiles, projects, and MCP server blocks fit together. Copy this as a starting point and trim what you don't need.
# ~/.codex/config.toml
model = "gpt-4o"
model_reasoning_effort = "medium"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
profile = "quick"
file_opener = "code"
project_doc_max_bytes = 65536
notify = ["python3", "/home/alice/.codex/notify.py"]
[history]
persistence = "save"
[shell_environment_policy]
inherit = "inherit"
[env]
EDITOR = "vim"
[telemetry]
enabled = false
[profiles.quick]
model = "gpt-4o-mini"
approval_policy = "never"
[profiles.deep]
model = "gpt-5-pro"
model_reasoning_effort = "xhigh"
[profiles.safe-review]
model = "gpt-4o"
approval_policy = "untrusted"
sandbox_mode = "read-only"
[projects."/home/alice/work/prod"]
trust_level = "trusted"
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/alice/work"]
enabled = true
Output: (none — TOML config file)
Common pitfalls
-
TOML is whitespace-sensitive around tables.
[profiles.quick]and[ profiles.quick ]parse the same, but[profiles . quick]is a syntax error. Runcodex --print-configafter edits to confirm the file parsed. -
Top-level keys must precede
[table]headers. Once you open a table (e.g.,[history]), every subsequent key belongs to that table until the next header. Ifmodel = "gpt-4o"is below[history], it becomeshistory.modeland Codex ignores it. -
Profile keys override top-level keys, but flags override both. Order of precedence is: command-line flag > active profile > top-level config > built-in default. If a setting "doesn't take effect," check which layer is winning.
-
[env]is set, not merged. ListingEDITOR = "vim"under[env]does NOT add to your inherited env — it setsEDITORafter the inherit step. Use this for variables you want to force regardless of the parent shell. -
project_doc_max_bytessilently truncates. If yourAGENTS.mdis larger than the configured limit, Codex truncates mid-line without warning. Increase the limit or split into includes. -
A trusted project's
.codex/config.tomlcannot upgrade sandbox mode beyond what the global config permits. Codex only allows the project config to narrow the sandbox (e.g., fromworkspace-writetoread-only). It cannot widen it todanger-full-access— that always requires a flag. -
notifyruns synchronously. A slow notify script blocks the next turn. Keep it under 1 second of work, or fork into a subshell (subprocess.Popenwithstart_new_session=True).
Real-world recipes
Profile per branch via direnv
Drop a .envrc into your repo that sets CODEX_HOME to a project-scoped config. Each git worktree gets its own profile set, MCP servers, and history.
# .envrc
export CODEX_HOME="${PWD}/.codex"
Output: (none — direnv-allowed file)
Then place a config.toml at .codex/config.toml with the per-branch overrides you want.
CI profile that fails fast
A CI profile that refuses to escalate the sandbox and exits 1 on the first unrecoverable error. Combine with codex exec in your pipeline.
[profiles.ci]
model = "gpt-4o-mini"
approval_policy = "never"
sandbox_mode = "workspace-write"
model_reasoning_effort = "minimal"
codex exec -p ci "Run pytest and apply mechanical fixes; exit 1 if any test still fails."
Output:
Ran 142 tests, 142 passed. No edits required.
Per-machine override via include
Codex itself has no include directive, but you can simulate one by symlinking a shared snippet:
ln -s /shared/codex-team-base.toml ~/.codex/team-base.toml
codex --config ~/.codex/team-base.toml --config ~/.codex/config.toml
Output: (TUI opens with both configs merged, later override earlier)
Disable sandbox for a single ad-hoc invocation
Useful for one-off npm install-driven debugging without modifying global config.
codex --sandbox danger-full-access "Run npm install and tell me what failed"
Output:
[agent] Running npm install…
[agent] Failed at step "node-gyp rebuild" — Python 3.13 is incompatible.
Print effective config to a file for review
Useful when sharing your setup with a teammate or filing a bug.
codex --print-config > /tmp/codex-effective.toml
Output: (none — writes resolved config to file)
Switch model mid-CI based on diff size
LINES=$(git diff origin/main...HEAD | wc -l)
if [ "$LINES" -gt 500 ]; then
codex exec -p deep "Review this diff for correctness."
else
codex exec -p quick "Review this diff for correctness."
fi
Output:
[agent review output]