Plenty of Codex CLI cheat sheets still tell you to start with codex --full-auto, a flag the current release rejects with a parse error. This Codex CLI cheat sheet lists the keyboard shortcuts, slash commands, flags and config keys that work today, and it puts the removed ones next to the exact error they print, so you can fix an old script in one pass instead of guessing.
You get the TUI shortcuts (clear the input, quit, switch to Plan mode, change reasoning effort) and the full slash menu grouped by job. After those come codex exec recipes with real JSON output for scripts and CI, the sandbox and approval presets, the model catalog, and the profile files that replaced [profiles] tables. Codex CLI is OpenAI’s open source terminal agent, and every command, shortcut and error below was run against Codex CLI 0.163.0 on macOS, re-checked against the release notes through 0.166.0 in November 2026.
Codex CLI Keyboard Shortcuts
Press Ctrl+U to clear what you’ve typed in the Codex composer, and Ctrl+C or Ctrl+D on an empty prompt to quit. Both quit on the first press in the current release, with no “press again” confirmation, so a reflex Ctrl+C on an idle session ends it. With text in the composer, Ctrl+C clears the text instead of quitting, which is the other quick way to clear input.
Shift+Tab is not an auto mode shortcut, even though that’s what most people search for. It flips the session between Default and Plan mode, and in our session the toggle also printed Model changed to gpt-6-luna medium for Plan mode, because Plan mode carries its own reasoning effort. If what you want is Codex approving its own commands, open /permissions and pick Approve for me, or launch with codex --approve-for-me. To change the model, type /model. To nudge reasoning effort without opening a menu, use Option+, and Option+. (Alt on Linux and Windows).
Press ? on an empty prompt to open the shortcut overlay. This is what it lists, with the four lab-checked rows (clear, quit) folded in:
| Shortcut | What it does |
|---|---|
Ctrl+U | Clear the composer (what you typed) |
Ctrl+C | Clear the composer; on an empty prompt, quit at once |
Ctrl+D | Quit at once on an empty prompt |
Shift+Tab | Toggle Default and Plan mode |
Option+, / Option+. | Less / more reasoning effort (Alt on Linux and Windows) |
Tab | Send the message; queues a slash command while a turn runs |
Esc Esc | Edit your last message |
Ctrl+J | Insert a new line |
Ctrl+V | Paste an image from the clipboard |
Ctrl+G | Edit the prompt in your external editor |
Ctrl+R | Search prompt history |
Ctrl+O | Copy the latest finished output (same as /copy) |
/ @ ! | Slash menu, attach a file, run a shell command |
Left arrow (empty prompt) | Open the agent command center |
Option+Left / Option+Right | Switch between subagents |
F4 | Inspect activity |
F8 / F9 | Voice input / mute voice |
Ctrl+T | Open the transcript |
F3 | Find in the transcript |
PgUp / PgDn | Scroll the transcript |
Ctrl+Space | Start a selection |
Ctrl+Home / Ctrl+End | Jump to the top / latest |
Ctrl+X | Leader key for custom bindings (set in /keymap) |
On macOS, the Option shortcuts only work when your terminal sends Option as Meta. If Option+, types ≤ into the prompt instead of lowering the effort, turn on “Use Option as Meta key” in Terminal.app’s keyboard profile (iTerm2 calls it “Esc+” for the Option key). Rebind anything you don’t like with /keymap, which writes the change to config.toml.
Run the Codex Commands You Need Daily
These twenty cover a normal working day: starting and resuming sessions, scripting a one-off task, checking what Codex changed and getting out. The rest of the page is detail behind each row.
| Task | Command or key |
|---|---|
| Start a session in this repo | codex |
| Start with a prompt | codex "fix the failing auth test" |
| Resume the last session | codex resume --last |
| Pick a past session | codex resume |
| Run one task and exit | codex exec "summarize this repo" |
| Pipe an error log in | cat err.log | codex exec "explain this" |
| Let Codex approve safe actions | codex --approve-for-me |
| Plan before editing | Shift+Tab or /plan |
| Switch model or effort | /model |
| Review uncommitted changes | codex review --uncommitted |
| See the diff Codex made | /diff |
| Generate AGENTS.md | /init |
| Free up context | /compact |
| Fresh chat, same session | /new |
| Model, policy, context left | /status |
| Attach a file | @src/app.ts |
| Run a shell command | !git status |
| Use a profile file | codex -p quick |
| Check the install | codex doctor |
| Quit | Ctrl+C or /exit |
Install or update Codex with npm (npm install -g @openai/codex) or Homebrew (brew install --cask codex), then run codex update to stay current. A ChatGPT plan signs in through the browser on first launch. For an API key, pipe it in once so it never lands in your shell history:
printenv OPENAI_API_KEY | codex login --with-api-key
On a server with no browser, codex login --device-auth prints a code to enter on another device, and codex login status tells you which method is active.
Fix Codex Commands That Stopped Working
Most “Codex is broken” reports after an upgrade come from a handful of removed options, one config format change and two argument-order traps. Every error in this table was printed by the current release on our machine, so you can match the message you see and jump straight to the fix:
| Old usage | What Codex prints now | Use instead |
|---|---|---|
codex --full-auto | error: unexpected argument '--full-auto' found | codex --approve-for-me |
-a untrusted | error: invalid value 'untrusted' for '--ask-for-approval <APPROVAL_POLICY>' | -a on-request; per-project trust_level = "untrusted" still works |
-a on-failure | error: invalid value 'on-failure' for '--ask-for-approval <APPROVAL_POLICY>' | -a on-request |
codex exec -a never ... | error: unexpected argument '-a' found | codex -a never exec ... |
[profiles.fast] in config.toml | Error loading config.toml: --profile `fast` cannot be used while ... contains legacy ... config | ~/.codex/fast.config.toml |
model_reasoning_effort = "minimal" | Unsupported value: 'minimal' is not supported with the 'gpt-6-luna' model (HTTP 400) | low |
codex exec -i shot.png "prompt" | No prompt provided via stdin. | Prompt first, or -i shot.png -- "prompt" |
codex mcp-server | Error: stdin is not a terminal | No longer a subcommand; codex app-server serves editor integrations |
personality = "pragmatic" | Nothing; the key is accepted and ignored | Delete it; use developer_instructions |
The mcp-server row is the sneaky one. Codex does not reject an unknown word. It treats it as the opening prompt for an interactive session, and in a script with no terminal that session dies with “stdin is not a terminal”. The same thing happens to any mistyped subcommand, so when a script prints that error, check the spelling of the first argument before anything else.
Pick a Codex Slash Command by Job
Type / and keep typing to filter the menu. In our session it listed 57 entries, and the exact set depends on your plan and platform (/setup-default-sandbox only appears on Windows, /daybreak only on eligible accounts). While a turn is running, you can type a slash command and press Tab to queue it for the next turn. The commands fall into four groups.
Session and context
| Command | What it does |
|---|---|
/new | New chat in the same CLI session |
/clear | Clear the terminal and start a fresh chat |
/compact | Summarize the chat to free tokens |
/recap | Summary of the chat without compacting it |
/resume | Reopen a saved chat |
/fork | Branch the chat into a new one |
/side or /btw | Throwaway side chat that leaves the main transcript alone |
/rename, /archive, /delete | Name, hide or permanently delete the session |
/export | Save the conversation as Markdown |
/copy | Copy the latest finished output |
/status | Model, approval policy, writable roots, context left |
/exit or /quit | Leave Codex |
Model, permissions and settings
| Command | What it does |
|---|---|
/model | Choose the model and its reasoning effort |
/fast | Toggle the Fast service tier when the model has one |
/permissions | Switch between Ask, Approve for me, Full Access and Read Only |
/approve | Retry one action the auto reviewer denied |
/config | Search and change settings; shows which need a restart |
/keymap | Rebind shortcuts and set the leader key |
/vim | Toggle Vim editing in the composer |
/experimental | Toggle experimental features |
/memories | Turn memory use and generation on or off |
/theme, /statusline, /title, /pets | Highlighting theme, footer items, terminal title, terminal pet |
/tui, /raw | Fullscreen or scrollback mode, raw copy-friendly scrollback |
/logout | Sign out |
Code, project and tools
| Command | What it does |
|---|---|
/init | Write an AGENTS.md scaffold for this directory |
/plan | Switch to Plan mode, optionally with a prompt |
/goal | Set, pause or clear a goal Codex tracks across a long task |
/review | Review the working tree |
/diff | Git diff including untracked files |
/mention | Attach a file or folder |
/worktree | Work in a managed Git worktree |
/cd, /pwd | Change or show the working directory |
/ps, /stop | Show or stop background terminals |
/ide | Pull open files and selection from your editor |
/import | Import Claude Code or Cursor setup and chats |
Agents, extensions and diagnostics
| Command | What it does |
|---|---|
/agents, /subagents | Agent command center, switch subagent thread |
/mcp | List MCP tools; /mcp verbose for details, /mcp login <name> for OAuth |
/skills, /plugins, /hooks | Browse skills, plugins and lifecycle hooks |
/voice | Start a voice conversation |
/app | Continue this session in the desktop app |
/daemon | Background server controls and restart |
/warnings | Warnings retained from this session |
/feedback | Send logs to the Codex maintainers |
If you also run Claude Code, /import is worth trying once: it brings over Claude Code or Cursor setup, projects and chats, which beats rewriting instructions by hand. Our Claude Code cheat sheet covers the slash commands on that side.
Hermes Agent has a similar slash-command set plus /goal, /steer and /bg. The Hermes Agent cheat sheet maps them side by side with its CLI flags.
Script Codex with codex exec
codex exec (alias codex e) runs one task without the TUI and exits, which is what you want in a shell script, a cron job or CI. The examples below use a profile called quick (gpt-6-luna at low effort, shown in the config section) so test runs stay cheap. Every run prints a header to stderr and only the final answer to stdout, so $(codex exec ...) captures the answer alone:
codex -p quick exec "Remember the code word falcon. Reply ok"
The stderr header is the fastest way to confirm what a run actually used. Look at approval: never, which is the exec default even with approval_policy = "on-request" in config.toml, and at the writable roots in brackets after the sandbox mode.
OpenAI Codex v0.163.0
--------
workdir: /Users/josphat/projects/demo
model: gpt-6-luna
provider: openai
approval: never
sandbox: workspace-write [workdir, /tmp, $TMPDIR]
reasoning effort: low
reasoning summaries: none
session id: 01a158fc-7c80-73d0-8251-1c544384fe00
--------
user
Remember the code word falcon. Reply ok
codex
ok
tokens used
13,305
That 13,305 is the real floor for a one-word answer, because nearly all of it is the system prompt and tool definitions Codex sends on every turn, and AGENTS.md, skills and MCP tools only add to it. A cron job that fires every minute sends roughly 19 million input tokens a day before it does any work, so batch small checks into one prompt instead of many tiny runs.
Continue a scripted session
codex exec resume --last picks the previous run back up with its full context, so a two-step job doesn’t need the first answer pasted back in:
codex -p quick exec resume --last "What code word did I give you?"
It answered from the earlier turn. The header also showed the same session id (01a158fc-7c80-...) as the first run, so the id line is how you tell a resume from a fresh session in your logs:
falcon
Use codex exec resume <SESSION_ID> instead of --last when two jobs run in the same directory, because --last simply takes the newest session and a parallel job can slip in between your two steps. codex exec fork <SESSION_ID> branches a run without changing the original, and since it has no --last it always needs the id.
Get JSON events and schema-checked output
Add --json to stream one JSON event per line on stdout instead of the plain answer:
codex -p quick exec --json "Reply with the single word ok"
A one-word run emits four events, and turn.completed carries the token usage you’d feed into a cost dashboard. Our two runs, taken hours apart, both showed cached_input_tokens: 0 with the whole prompt written to cache, so check that field on your own schedule before you count on cached pricing.
{"type":"thread.started","thread_id":"01a15916-c95b-7250-a673-e11706c8bc13"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"ok"}}
{"type":"turn.completed","usage":{"input_tokens":13297,"cached_input_tokens":0,"cache_write_input_tokens":13294,"output_tokens":5,"reasoning_output_tokens":0}}
When another program has to parse the answer, give Codex a JSON Schema and it shapes the final message to match. Create schema.json in the project:
vim schema.json
This schema asks for a single integer and nothing else. Codex sends output schemas to the API in strict mode, which requires additionalProperties: false on every object and every property listed in required, so drop either one when you adapt this file and the run fails with an HTTP 400 before any output arrives.
{"type":"object","properties":{"files":{"type":"integer"}},"required":["files"],"additionalProperties":false}
Pass it with --output-schema, and use -o to write the final message to a file as well:
codex -p quick exec --output-schema schema.json -o last.txt "Count the .txt files in this directory"
The model ran find . -maxdepth 1 -type f -name '*.txt' | wc -l on its own, and both stdout and last.txt held only the object, ready for jq:
{"files":2}
The schema only shapes the final message. The agent still decided how to count, so for anything that matters, check the command it ran in the stderr log rather than trusting the number on its own.
Pipe logs and files into a prompt
When stdin is piped and a prompt is also given, Codex appends the piped text to the prompt as a <stdin> block. That makes it a handy log explainer:
printf 'Error: EACCES: permission denied, open /var/log/app.log\n' | codex -p quick exec "In one sentence, what does this error mean?"
The answer came back as one line on stdout.
The app tried to open `/var/log/app.log`, but it lacks permission to access that file.
The flip side is that exec reads stdin whenever it isn’t a terminal, and says so with Reading additional input from stdin... at the top of stderr. In a script where stdin is something you don’t control, end the command with < /dev/null so nothing unexpected gets appended to your prompt.
Review code from a script
Both codex review and codex exec review pick what to review with one of three flags:
--uncommittedfor staged, unstaged and untracked changes--base mainfor everything since a branch--commit <SHA>for a single commit
Only the exec form accepts --json and -o, because plain codex review stops with error: unexpected argument '--json' found. Use the exec form in CI so the findings land in a file a later step can parse.
codex exec review --base main --json > review.jsonl
A pre-commit hook is the opposite case. Nobody parses the output there, a human reads it, so codex review --uncommitted is the better fit, and it sees untracked files that git diff alone would miss.
Error: “unexpected argument ‘-a’ found”
Some options belong to the top-level codex command only, so they do not exist after exec, and putting one there fails before any model call is made. The four you are most likely to hit:
-a,--ask-for-approval--searchfor live web search--remotefor a remote app server--no-alt-screenfor the inline TUI
This is what codex exec -a never "Reply ok" prints:
error: unexpected argument '-a' found
tip: to pass '-a' as a value, use '-- -a'
Usage: codex exec [OPTIONS] [PROMPT]
codex exec [OPTIONS] <COMMAND> [ARGS]
Move the flag in front of the subcommand and the same run works, as in codex -a never exec "...". The rule of thumb is that anything printed by codex exec --help is safe after exec, because exec parses its own option list and stops at the first one it does not know. The model, sandbox and approve-for-me flags are all in that list, so they work on either side.
Error: “No prompt provided via stdin” with -i
-i accepts several files, so in codex exec -i shot.png "describe this" it swallows your prompt as a second image path. Codex then looks for a prompt on stdin, finds none and stops with No prompt provided via stdin. Put the prompt first, or end the image list with --:
codex exec -i before.png,after.png -- "compare these two screenshots"
Comma-separated paths work as one list: with a red and a blue test image, that command answered Bright red, bright blue. A single image with the prompt placed first (codex exec "describe this" -i shot.png) works too.
A misspelled profile is ignored silently
codex -p nosuch exec "..." exits 0 and runs on your base config, with no warning that the profile file does not exist. If a CI job suddenly costs more or runs a different model, read the model: line in the stderr header before you suspect anything else, because it shows the profile was never applied.
Choose Sandbox and Approval Settings
Two settings decide what Codex may do. The sandbox limits what a command can touch, and the approval policy decides when Codex stops to ask you. /permissions wraps the common combinations into four presets, listed here exactly as the menu shows them:
| Preset | What the menu says | Closest launch flag |
|---|---|---|
| Ask for approval (default) | Read and edit workspace files and run commands, with approval required for internet access or edits outside the workspace | -s workspace-write -a on-request |
| Approve for me | Only ask for actions detected as potentially unsafe | --approve-for-me |
| Full Access | Codex can edit files outside this workspace and access the internet without approval | -s danger-full-access -a never |
| Read Only | Read workspace files, with approval required for edits or internet access | -s read-only |
--approve-for-me (alias --not-so-yolo) routes approval requests to a hidden reviewer model, codex-auto-review, while keeping the workspace-write sandbox. It does not open the network. Our run with it still printed approval: on-request and sandbox: workspace-write, and a curl inside it failed exactly as below. When the reviewer denies something you want, /approve retries that one action. At the far end, --yolo is short for --dangerously-bypass-approvals-and-sandbox and belongs only inside a container or VM that is already isolated.
Error: “curl: (6) Could not resolve host” inside Codex
The workspace-write sandbox has no network, so any curl, npm install or pip install the agent runs fails DNS. This is the command line Codex ran and what came back:
/bin/zsh -lc "curl -sS -o /dev/null -w '%{http_code}' https://example.com" in /Users/josphat/projects/demo
exited 6 in 0ms:
curl: (6) Could not resolve host: example.com
000
Allow outbound traffic for one run with a config override, without switching to full access:
codex -p quick -c sandbox_workspace_write.network_access=true exec "Run curl -sS -o /dev/null -w '%{http_code}' https://example.com and print only what it outputs"
The same command now reaches the site and gets a 200.
/bin/zsh -lc "curl -sS -o /dev/null -w '%{http_code}' https://example.com" in /Users/josphat/projects/demo
succeeded in 391ms:
200
To make it permanent for a project that always needs package downloads, set network_access = true under [sandbox_workspace_write] in config.toml. Keep it off by default, because the network is what turns a prompt-injected agent into one that can send your code somewhere.
Pick a Codex Model and Reasoning Effort
Codex loads its model list from your account, so the roster can differ between a ChatGPT plan and an API key. codex debug models prints the raw catalog as JSON. This is what it returned for our API key, sorted by the catalog’s own priority field, and the first visible model in that order is the default.
| Model | Catalog description | Default effort | Highest effort |
|---|---|---|---|
gpt-6.1-sol (default) | Latest workhorse model for coding and everyday work | low | ultra |
gpt-6-astra | Frontier intelligence for the most demanding work | low | ultra |
gpt-6-sol | Previous generation workhorse model | medium | ultra |
gpt-6-luna | Fast and affordable model for easier tasks | medium | max |
gpt-5.6-sol | Older generation workhorse; upgrade prompt points to gpt-6-sol | low | ultra |
gpt-5.6-terra | Older balanced model; upgrade prompt points to gpt-6-sol | medium | ultra |
gpt-5.6-luna | Older fast model; upgrade prompt points to gpt-6-luna | medium | max |
gpt-5.5 | Legacy coding model | medium | xhigh |
Every listed model reports a 272K context window. The catalog also holds hidden entries that /model doesn’t show: codex-auto-review (the approval reviewer) and the Daybreak cybersecurity models, which need an eligible account. Effort levels run low, medium, high, xhigh, max and ultra, and gpt-6-luna stops at max. Our GPT-6 Sol and Luna breakdown covers how the two families compare on benchmarks.
Set the model and effort for one run on the command line when a single task is hard. Pinning gpt-6-astra in config.toml instead makes every small question pay for the frontier model, so most people keep a cheaper default and reach for the flag:
codex -m gpt-6-astra -c model_reasoning_effort="high"
Plan mode has its own key, plan_mode_reasoning_effort, which is why toggling into Plan mode can change the effort shown in the footer. Leave it unset to use the built-in preset, or set it higher than your normal effort if you want Codex to think harder before it touches files.
Configure config.toml, Profiles and AGENTS.md
Codex merges settings from several layers, and the higher layer wins whenever two set the same key. Highest priority first, per the config basics docs:
- Command-line flags and
-coverrides .codex/config.tomlin a trusted project (the closest one wins)- The profile file picked with
-p ~/.codex/config.toml/etc/codex/config.toml
The project layer has one catch. A repo’s .codex/config.toml cannot set profile, model_provider, notify or base URLs, and Codex ignores those keys there, so a teammate’s provider override in the repo does nothing. Put provider and notification settings in your user config instead.
Open your user config. Codex writes to this file too (trusted project entries and TUI flags such as [tui] settings), so edit around those entries rather than pasting a fresh file over them, because deleting the trust entries brings back the trust prompt in every repo.
vim ~/.codex/config.toml
This is the file we loaded with --strict-config, which errors out on any key the installed version doesn’t recognize, so every key below is valid on the current release. The two MCP servers at the bottom are GitHub’s hosted server (it reads a personal access token from GITHUB_PAT) and the Context7 docs server, written by the codex mcp add commands in the MCP section, so swap them for your own:
model = "gpt-6.1-sol"
model_reasoning_effort = "medium"
plan_mode_reasoning_effort = "high"
sandbox_mode = "workspace-write"
approval_policy = "on-request"
web_search = "cached"
developer_instructions = "Run the test suite before you report a task as done."
[sandbox_workspace_write]
network_access = false
[mcp_servers.github]
url = "https://api.githubcopilot.com/mcp/"
bearer_token_env_var = "GITHUB_PAT"
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
Run codex --strict-config after every upgrade. A typo such as model_reasoning_efort is silently ignored without it, while with it Codex stops and points at the line (quick.config.toml:3:1: unknown configuration field `model_reasoning_efort`). The flag works on codex and codex exec but not on codex mcp or codex features, which reject it.
Create a profile file
Profiles are now separate files next to config.toml, named <name>.config.toml, and -p <name> layers one over your base config. Create the quick profile used throughout this page:
vim ~/.codex/quick.config.toml
Two lines are enough, because everything else comes from the base config. Keep profiles that small, so a change to your sandbox or MCP servers in config.toml reaches every profile without editing each file.
model = "gpt-6-luna"
model_reasoning_effort = "low"
With the base config above set to gpt-6.1-sol, a codex -p quick exec run printed model: gpt-6-luna and reasoning effort: low in its header, so the profile wins over the base file. It does not win over a trusted project’s .codex/config.toml, which sits above profiles, so a repo that pins a model overrides -p for that key. Make a second one, such as deep.config.toml with gpt-6-astra and xhigh, for architecture work.
Write AGENTS.md project instructions
AGENTS.md is the Codex counterpart of Claude Code’s CLAUDE.md: plain Markdown loaded at the start of every session in that repo. /init writes a first draft, which you then trim to what the agent can’t work out from the code. Edit it at the repo root:
vim AGENTS.md
Keep it to build commands and rules, because every line is sent with every turn:
# My Project
## Build Commands
- Test: `npm test`
- Build: `npm run build`
- Lint: `npm run lint -- --fix`
## Rules
- Use TypeScript strict mode for all new files
- Write unit tests for every new function
- Never commit directly to main branch
The files Codex keeps under ~/.codex follow the same split: config.toml and profile files, auth.json for stored credentials, rules/ for execution policy, skills/ for the bundled system skills and log/ for debug logs. Point CODEX_HOME somewhere else and Codex uses that directory instead, which is how you keep a throwaway test setup away from your real login.
Use the Codex CLI Subcommands
Most of these appear in codex --help. execpolicy is hidden from that list and debug models sits under debug, and the docs mark both as experimental along with the others flagged below:
| Command | What it does |
|---|---|
codex exec (codex e) | Run non-interactively; subcommands resume, fork, review |
codex review | Code review without the TUI |
codex resume / codex fork | Reopen or branch a session; --last skips the picker, --all shows every directory |
codex archive / unarchive / delete | Manage saved sessions by id or name |
codex queue | Queue a message for an existing session |
codex agents | Browse agent sessions on the local background server |
codex login / logout | Sign in with ChatGPT, an API key, an access token or a device code |
codex mcp | list, get, add, remove, login, logout for MCP servers |
codex plugin | Manage plugins |
codex doctor | Check install, config, auth, network and the background server |
codex update | Update Codex in place |
codex features list | Feature flags with stage and current state |
codex debug models | Raw model catalog as JSON (experimental) |
codex execpolicy check | Test a command against your rules files (experimental) |
codex sandbox | Run any command inside the Codex sandbox |
codex apply <TASK_ID> (codex a) | Apply a cloud task’s diff with git apply |
codex cloud | Codex Cloud tasks (experimental) |
codex app / app-server | Desktop app, or the server editors connect to (app-server is experimental) |
codex completion zsh | Completion script for bash (default), zsh, fish, elvish or PowerShell |
codex doctor --summary is the first thing to run when something feels off. On our Mac it reported 20 checks ok and one failure, TERMINFO unreadable, which only means the terminal capabilities could not be read from a non-interactive shell and did not affect any run on this page.
Set Codex Flags on the Command Line
These apply to codex and, unless the last column says otherwise, to codex exec as well:
| Flag | Purpose | Where |
|---|---|---|
-m, --model | Model for this run | both |
-p, --profile | Layer $CODEX_HOME/<name>.config.toml | both |
-c key=value | Override any config key (value parsed as TOML) | both |
-s, --sandbox | read-only, workspace-write, danger-full-access | both |
-a, --ask-for-approval | on-request or never | before exec only |
--approve-for-me | Auto review of approvals in workspace-write | both |
--yolo | No sandbox, no approvals | both |
-C, --cd | Working root directory | both |
--add-dir | Extra writable directory | both |
--worktree | Run in a new managed Git worktree | both |
-i, --image | Attach images (end the list with --) | both |
--search | Live web search | before exec only |
--oss --local-provider ollama | Local model through Ollama or LM Studio | both |
--enable / --disable | Turn a feature flag on or off | both |
--strict-config | Fail on unknown config keys | both |
--json, -o, --output-schema | Machine-readable output | exec only |
--ephemeral | Don’t save the session to disk | exec only |
--skip-git-repo-check | Run outside a Git repo | exec only |
--ignore-user-config, --ignore-rules | Skip config.toml or execpolicy rules for this run | exec only |
--no-alt-screen | Inline TUI that keeps terminal scrollback | TUI only |
For a fully offline setup, --oss talks to a local server instead of OpenAI. If you already run models locally, our Ollama commands cheat sheet covers pulling and serving them.
Add MCP Servers to Codex
codex mcp add writes the server into config.toml for you, which is less error-prone than editing TOML by hand. Everything after -- is the command for a local stdio server, and --url adds a remote streamable HTTP server:
codex mcp add github --url https://api.githubcopilot.com/mcp/ --bearer-token-env-var GITHUB_PAT
codex mcp add context7 -- npx -y @upstash/context7-mcp
Skip the old @modelcontextprotocol/server-github package that many guides still show, because npm now marks it “Package no longer supported”. codex mcp list then shows stdio and HTTP servers in two separate tables:
Name Command Args Env Cwd Status Auth
context7 npx -y @upstash/context7-mcp - - enabled Unsupported
Name Url Bearer Token Env Var Status Auth
github https://api.githubcopilot.com/mcp/ GITHUB_PAT enabled Bearer token
A server that cannot be reached does not stop the session. When we pointed one at a URL that doesn’t exist, it logged ERROR rmcp::transport::worker: worker quit with fatal: Transport channel closed three times on stderr, and the task still finished. In CI, grep stderr for rmcp if a tool you depend on seems to be missing. HTTP servers that use OAuth sign in with codex mcp login <name>, or /mcp login <name> from inside a session, and --bearer-token-env-var covers token-based ones.
Limit Commands with Skills and Rules
Skills are reusable instructions with optional scripts. Codex scans .agents/skills/ in the project, ~/.agents/skills/ for your personal ones and /etc/codex/skills/ system-wide. Call one with $skill-name in the composer, or browse them with /skills.
Execution policy rules are the harder guardrail: Starlark files in ~/.codex/rules/ that mark a command prefix as allowed, prompt or forbidden. Create one:
vim ~/.codex/rules/default.rules
These two rules block direct pushes and make recursive deletes ask first. A delete gets prompt rather than forbidden because the agent has real reasons to clean a build directory, while a push to a shared remote is never something it should do unattended.
prefix_rule(
pattern = ["git", "push"],
decision = "forbidden",
justification = "No direct pushes, open a pull request instead",
)
prefix_rule(
pattern = ["rm", "-rf"],
decision = "prompt",
justification = "Destructive delete needs a human",
)
Test a command against the file before you rely on it:
codex execpolicy check --rules ~/.codex/rules/default.rules --pretty -- git push origin main
The push matches the first rule and comes back forbidden, with your justification attached.
{
"matchedRules": [
{
"prefixRuleMatch": {
"matchedPrefix": [
"git",
"push"
],
"decision": "forbidden",
"justification": "No direct pushes, open a pull request instead"
}
}
],
"decision": "forbidden"
}
Checking rm -rf build returned "decision":"prompt", and ls -la returned an empty matchedRules list, which means no rule applies and the normal approval policy decides.
Set Codex Environment Variables
| Variable | Purpose |
|---|---|
CODEX_HOME | Config directory instead of ~/.codex |
CODEX_API_KEY | API key for codex exec, without touching the stored login |
OPENAI_API_KEY | Key you pipe into codex login --with-api-key |
CODEX_CA_CERTIFICATE | Custom CA bundle for corporate TLS proxies |
HTTPS_PROXY | Outbound proxy |
CODEX_THREAD_ID | Set by Codex inside commands it runs, so scripts know the thread |
CODEX_API_KEY earns its place in CI. A stale ChatGPT login makes codex exec cycle through Reconnecting... 1/5 (workspace routing discovery unauthorized (401)) retries, then an HTTPS fallback with more of the same, before it fails, while the variable bypasses the stored login for that one run and leaves it untouched.
Hand Tasks to Codex Cloud
codex cloud sends a task to a disposable container on OpenAI’s side and gives you back a diff. It is still marked experimental, and the CLI cannot look up environments from a script yet, so copy the environment ID from the interactive picker (codex cloud with no arguments) and keep the IDs in variables:
export CODEX_ENV=env_9f2c1a7b
export CODEX_TASK=task_7b3e40d2
Submit, track and apply a task. --attempts asks for best-of-N candidate solutions and --branch sets the Git branch to run on (your current branch by default):
codex cloud exec --env "${CODEX_ENV}" "upgrade all dependencies to their latest minor versions and fix any test breakage"
codex cloud list --env "${CODEX_ENV}" --json
codex cloud status "${CODEX_TASK}"
codex cloud diff "${CODEX_TASK}"
codex cloud apply "${CODEX_TASK}"
Read the diff before you apply it. The container ran with whatever network access and secrets the cloud environment grants, which is a different trust boundary from your local sandbox, so a change that looks harmless can still carry a dependency bump you never asked for. codex cloud diff costs nothing and shows exactly what apply will write.
Compare Codex CLI with Claude Code
The two tools now overlap on most features, so the choice usually comes down to which models you pay for and how much sandboxing you want by default:
| Feature | Codex CLI | Claude Code |
|---|---|---|
| Models | GPT-6.1 Sol, GPT-6 Astra, Sol and Luna, plus local models | Claude Opus, Sonnet, Haiku and Fable |
| Sandbox | OS-level (Seatbelt on macOS, Bubblewrap on Linux), on by default | Permission rules; optional sandbox |
| Project instructions | AGENTS.md | CLAUDE.md |
| Scripted runs | codex exec | claude -p |
| Hands-off approvals | --approve-for-me (reviewer model) | auto mode (classifier) |
| Hard command rules | Starlark execpolicy files | Permission allow and deny rules, hooks |
| Local models | --oss with Ollama or LM Studio | No built-in local provider flag |
| Import from the other | /import (Claude Code, Cursor) | claude import codex |
If you’d rather not be tied to one vendor, OpenCode talks to most providers, the Gemini CLI brings Google’s models to the same workflow, and Aider commits every change to Git as it goes. Our AI coding agent comparison for DevOps work ranks all of them on infrastructure tasks.
For the reasoning behind these commands rather than the commands themselves, Agentic Coding with OpenAI Codex CLI (paid link) by Daniel Vaughan (Packt, August 2026, 670 pages) is the one book written for this tool. It covers AGENTS.md, MCP servers, hooks, subagents, CI/CD and security hardening, and it made our list of the best AI coding books.
Upgrade an Old Codex Config
If your ~/.codex predates profile files, the first -p run after an upgrade fails with the legacy-profile error, and the scripts around it fail on removed flags. Work through it in this order, because each step clears the error the next one would otherwise hide:
- Move each
[profiles.NAME]table out of config.toml into~/.codex/NAME.config.toml, dropping the table header, and delete any top-levelprofile = "NAME"line. - Delete
personalityand change anymodel_reasoning_effort = "minimal"tolow. - Replace
approval_policy = "untrusted"or"on-failure"with"on-request"; keep untrusted projects astrust_level = "untrusted"entries. - Search your scripts for
--full-auto,exec -aandexec -i file "prompt", and apply the fixes from the removed-flags table. - Run
codex --strict-config -p NAME exec "Reply ok"for each profile and check themodel:line in the header. - Finish with
codex doctor --summaryand read every row that isn’t ok.
Step 5 is the one people skip, and it’s the only step that catches a misspelled profile name, because Codex runs on the base config without complaint when the file isn’t there. Once each profile prints the model you expect, the config is safe for the next upgrade too.