// ai

Codex

Comprehensive guide for OpenAI Codex - the codex CLI, IDE extension, cloud, authentication, configuration, and automation

codex · openai · ai · cli · coding-assistant

A practical reference for OpenAI Codex: the codex CLI, the IDE extension, Codex cloud, and the automation surfaces around them. Commands are written for a POSIX shell unless marked otherwise. Checked against Codex CLI 0.147.0, published on 2026-08-07 as npm @openai/codex@0.147.0 and GitHub release tag rust-v0.147.0. Note that GitHub release tags carry a rust-v prefix, so searching the releases page for a bare 0.147.0 will not match.

Codex is a coding agent that runs on your machine. It reads and edits files, runs commands inside an OS-enforced sandbox, and asks for approval before it crosses the boundary you set. The same config.toml drives the CLI, the IDE extension, and Codex in the ChatGPT desktop app.

Table of Contents

Install & Update

Standalone installer

# macOS / Linux — the same command installs and updates
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# Windows — the same command installs and updates
powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"

Package managers

npm install -g @openai/codex        # install and update
brew install --cask codex           # install
brew upgrade --cask codex           # update

Self-update and version

codex update                # apply an update when the release supports self-update
codex --version             # installed CLI version
codex doctor                # local diagnostic report (installation, auth, git, terminal)
codex doctor --json         # redacted machine-readable support report

Installer variables

# Skip installer prompts; prompts take their default answer
curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh

# Change where the `codex` command lands
# Default: ~/.local/bin (macOS/Linux), %LOCALAPPDATA%\Programs\OpenAI\Codex\bin (Windows)
CODEX_INSTALL_DIR=/opt/bin curl -fsSL https://chatgpt.com/codex/install.sh | sh

# Force GitHub Releases instead of releases.openai.com
curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_INSTALLER_USE_RELEASES_OPENAI_COM=false sh

System requirements

RequirementDetails
Operating systemmacOS 12+, Ubuntu 20.04+/Debian 10+, Windows 11 (native or WSL2)
Git2.23+ recommended; Codex refuses to run outside a Git repo by default
RAM4 GB minimum, 8 GB recommended

WSL1 was supported through Codex 0.114. Starting with 0.115 the Linux sandbox uses bwrap, so WSL1 no longer works.

Sign In & Authentication

codex login                                        # browser OAuth with a ChatGPT account
codex login --device-auth                          # device-code flow for headless machines
printenv OPENAI_API_KEY | codex login --with-api-key
printenv CODEX_ACCESS_TOKEN | codex login --with-access-token
codex login status                                 # exits 0 when credentials exist
codex logout                                       # clears both API key and ChatGPT credentials

Signing in with ChatGPT uses your plan’s included usage and your workspace’s admin controls. Signing in with an API key bills at standard API rates and follows your API organization’s data settings instead. Codex cloud requires ChatGPT sign-in.

Credential storage

# ~/.codex/config.toml
cli_auth_credentials_store = "keyring"   # file | keyring | auto

file writes ~/.codex/auth.json, keyring uses the OS credential store, and auto prefers the credential store and falls back to the file. Treat auth.json like a password; it holds access tokens.

Headless and remote machines

# Preferred: device code
codex login --device-auth

# Fallback 1: copy an existing credential file
ssh user@remote 'mkdir -p ~/.codex && cat > ~/.codex/auth.json' < ~/.codex/auth.json

# Fallback 2: forward the local OAuth callback port
ssh -L 1455:localhost:1455 user@remote
# then run `codex login` inside that SSH session

Corporate TLS

export CODEX_CA_CERTIFICATE=/path/to/corporate-root-ca.pem   # takes precedence over SSL_CERT_FILE
codex login

Quick Start

cd ~/code/my-project
codex                                  # launch the interactive TUI
codex "explain this project"           # launch with a first prompt
codex -m gpt-5.6-terra "fix the failing test"
codex --sandbox read-only              # look but do not touch
codex resume --last                    # reopen the most recent chat here
codex exec "summarize the repo"        # one-shot, no TUI

Inside the session:

StepCommand
Write project instructions/init then edit AGENTS.md
Check the boundary you are running under/status
Change what Codex may do without asking/permissions
Switch model or reasoning effort/model
Inspect what changed/diff
Get a second opinion on the diff/review
Free context on a long chat/compact

Commit before and after a Codex task. A clean git status makes its patches easy to isolate and revert.

Command Reference

CommandPurpose
codexLaunch the interactive terminal UI in the current directory
codex exec (codex e)Run a task non-interactively for scripts and CI
codex resumeContinue a saved interactive session
codex forkBranch a saved session into a new chat
codex reviewRun a code review non-interactively
codex apply <TASK_ID>Apply the latest diff from a Codex cloud chat locally
codex cloudBrowse cloud chats; cloud exec submits one, cloud list lists them
codex login / logoutManage credentials
codex mcpAdd, list, inspect, and authenticate MCP servers
codex mcp-serverRun Codex itself as an MCP server over stdio
codex pluginInstall, list, and remove plugins from marketplaces
codex archive / unarchiveHide or restore a saved session without deleting it
codex delete <SESSION>Permanently delete a session transcript
codex sandboxRun a command under the same sandbox policy Codex uses
codex execpolicy checkTest .rules files against a command
codex featuresList, enable, or disable feature flags
codex completion <shell>Print a shell completion script
codex doctorProduce a local diagnostic report
codex updateUpdate the CLI in place
codex appOpen the ChatGPT desktop app from the terminal
codex app-serverRun the local app server (development and protocol clients)
codex remote-controlStart, stop, and pair the remote-control daemon
codex debug modelsPrint the raw model catalog as JSON

Sessions

codex resume                       # pick from saved sessions in this directory
codex resume --last                # most recent session in this directory
codex resume --all                 # widen the picker beyond this directory
codex resume <SESSION_ID>          # by UUID or session name
codex fork --last                  # branch the most recent session
codex archive <SESSION>            # hide from the picker, keep the transcript
codex unarchive <SESSION>
codex delete <SESSION_UUID> --force

When the current directory differs from the session’s saved directory, Codex asks which one to use. Set tui.resume_cwd = "current" or "session" to answer that once and for all; an explicit --cd still wins.

Review

codex review --uncommitted                       # staged, unstaged, and untracked changes
codex review --base main                         # branch diff against a base branch
codex review --commit 1a2b3c4 --title "Fix auth" # one commit
codex review "focus on error handling"           # custom instructions
echo "check for race conditions" | codex review -

--uncommitted, --base, --commit, and a custom prompt are mutually exclusive. --title only applies with --commit.

Shell completions

codex completion zsh > "${fpath[1]}/_codex"
# or evaluate directly from your shell rc file
eval "$(codex completion zsh)"

# If zsh reports `command not found: compdef`
autoload -Uz compinit && compinit
eval "$(codex completion zsh)"

Supported shells: bash, zsh, fish, powershell, elvish.

Global Flags

These apply to codex and propagate to most subcommands.

FlagValuesPurpose
--model, -mstringOverride the configured model
--sandbox, -sread-only, workspace-write, danger-full-accessSandbox policy for generated commands
--ask-for-approval, -auntrusted, on-request, neverWhen Codex pauses to ask
--dangerously-bypass-approvals-and-sandbox, --yoloNo sandbox, no approvals. Use only inside an isolated VM or container
--cd, -CpathSet the working directory before the agent starts
--add-dirpath (repeatable)Grant write access to extra directories
--image, -ipath[,path…]Attach images to the first prompt
--searchLive web search for this run (web_search = "live")
--profile, -pnameLayer $CODEX_HOME/<name>.config.toml over the base config
--config, -ckey=valueOverride any config key; the value is parsed as TOML
--enable / --disablefeature (repeatable)Force a feature flag on or off for this run
--ossUse a local open-source provider
--local-providerlmstudio, ollamaPick the local provider for --oss
--strict-configFail when config.toml holds unrecognized fields
--no-alt-screenKeep terminal scrollback instead of the alternate screen
--remotews://, wss://, unix://[PATH]Attach the TUI to a running app server
--remote-auth-token-envenv var nameBearer token source for --remote
--dangerously-bypass-hook-trustRun enabled hooks without persisted trust

codex exec adds

FlagPurpose
--jsonEmit newline-delimited JSON events on stdout
--output-last-message, -o <path>Write the final message to a file (still printed to stdout)
--output-schema <path>Force the final response to match a JSON Schema
--ephemeralDo not persist session rollout files
--skip-git-repo-checkAllow running outside a Git repository
--ignore-user-configSkip $CODEX_HOME/config.toml
--ignore-rulesSkip user and project .rules files
--coloralways, never, auto (default auto)
--full-autoDeprecated. Use --sandbox workspace-write

Config overrides on the command line

codex --model gpt-5.6-terra                                   # prefer a dedicated flag
codex -c model='"gpt-5.6-terra"'                              # values are TOML, so strings need quotes
codex -c sandbox_workspace_write.network_access=true
codex -c 'shell_environment_policy.include_only=["PATH","HOME"]'
codex -c mcp_servers.context7.enabled=false                   # dot notation reaches nested keys
codex -c log_dir=./.codex-log                                 # also enables the plaintext TUI log

Interactive Session

Keyboard and composer

InputEffect
@Search workspace files and insert the path
$Mention a skill; $app-slug mentions an app
! at line startRun a local shell command under the current sandbox and approval settings
Up / DownRestore draft history
Ctrl+RSearch prompt history; Enter accepts, Esc cancels
Ctrl+OCopy the latest completed response (same as /copy)
Tab while workingQueue a follow-up prompt, slash command, or shell command
Enter while workingInject new instructions into the running turn
Esc Esc on an empty composerEdit the previous message and fork from that point
Ctrl+GOpen $VISUAL (or $EDITOR) to write a long prompt
Ctrl+LClear the terminal view but keep the chat
Alt+RToggle raw scrollback (same as /raw)
Ctrl+CExit the session

Rebind any of these with /keymap, which writes to tui.keymap in config.toml:

[tui.keymap.global]
open_transcript = "ctrl-t"

[tui.keymap.composer]
submit = ["enter", "ctrl-m"]

[tui.keymap.chat]
interrupt_turn = "f12"

An empty binding list unbinds the action. Context-specific bindings override tui.keymap.global.

Images

codex -i screenshot.png "Explain this error and suggest the smallest fix"
codex --image before.png,after.png "Compare these states and list the regressions"

You can also paste an image straight into the composer. Repeat --image or separate paths with commas.

Slash Commands

Session control

CommandPurpose
/modelChoose the model and reasoning effort
/fastToggle the model’s Fast service tier when the catalog offers one
/permissionsChoose the approval preset (Read Only, Auto, and so on)
/approveRetry once an action that automatic review denied
/planSwitch to plan mode, optionally with an inline prompt
/goalSet, edit, pause, resume, view, or clear a persistent objective (max 4,000 characters)
/personalityChoose friendly, pragmatic, or none
/statusShow model, approval policy, writable roots, and token usage
/usageShow account token activity (daily, weekly, cumulative)
/compactSummarize the chat so far to free context
/newStart a fresh chat in the same CLI session
/clearClear the terminal and start a fresh chat
/renameRename the current chat
/forkClone the current chat into a new one
/side, /btwStart a throwaway side chat off the current one
/resumeReopen a saved chat from the picker
/archive, /deleteArchive or delete the current session, then exit
/quit, /exitLeave the CLI

Code and context

CommandPurpose
/initGenerate an AGENTS.md scaffold in the current directory
/diffShow the Git diff, including untracked files
/reviewReview the working tree, a base branch, or a commit
/mention <path>Attach a file to the chat
/idePull open files and the current selection into the next prompt
/copyCopy the latest completed response
/psList background terminals and recent output
/stop (/clean)Stop all background terminals

Extensions

CommandPurpose
/skillsBrowse and apply a local skill
/pluginsBrowse installed and available plugins; Space toggles one
/appsBrowse connectors and insert one as $app-slug
/mcpList MCP servers and tools; /mcp verbose adds diagnostics
/hooksInspect, trust, disable, or re-enable lifecycle hooks
/agent, /subagentsSwitch between agent threads
/memoriesTurn memory use and generation on or off
/importImport a Claude Code setup, project files, and recent chats

Appearance and diagnostics

CommandPurpose
/themePick a syntax-highlighting theme (tui.theme)
/statuslineChoose and order footer items (tui.status_line)
/titleChoose and order terminal title items (tui.terminal_title)
/keymapRemap TUI shortcuts (tui.keymap)
/vimToggle composer Vim mode
/rawToggle raw scrollback for easier copying
/pets, /petChoose or hide a terminal pet
/experimentalToggle experimental features
/debug-configPrint config layer order and policy diagnostics
/feedbackSend logs and diagnostics to the maintainers
/logoutClear local credentials

Windows-only: /setup-default-sandbox installs the elevated sandbox, and /sandbox-add-read-dir C:\path grants read access to one more directory.

Models & Reasoning

ModelShape of work
gpt-5.6-solFlagship. Ambiguous, high-value, open-ended work that needs judgment and polish
gpt-5.6-terraBalanced all-rounder for everyday coding and tool use
gpt-5.6-lunaFast and cheap. Clear, repeatable, high-volume tasks
gpt-5.3-codex-sparkResearch preview, text only, near-instant iteration (ChatGPT Pro)
gpt-5.5Previous-generation frontier model
codex --model gpt-5.6                    # `gpt-5.6` resolves to a recommended model
codex exec -m gpt-5.6-terra "review the current changes"
model = "gpt-5.6"
review_model = "gpt-5.6"            # only used by /review
model_reasoning_effort = "high"     # minimal | low | medium | high | xhigh
model_reasoning_summary = "auto"    # auto | concise | detailed | none
model_verbosity = "medium"          # low | medium | high

Use the lowest reasoning effort that produces the result you need. The desktop app and IDE label the lowest level Light where the CLI calls it Low, and some models expose deeper Max and Ultra levels. Ultra runs subagents in parallel rather than thinking longer in one thread.

Retirements

gpt-5.4 and gpt-5.4-mini retire from Codex with ChatGPT sign-in on August 31, 2026. Replace gpt-5.4 with gpt-5.6-terra and gpt-5.4-mini with gpt-5.6-luna in config files, custom agents, and scheduled tasks. gpt-5.2 and gpt-5.3-codex are already deprecated for ChatGPT sign-in. The OpenAI API and API-key Codex usage are not affected.

codex debug models            # print the catalog Codex actually sees
codex debug models --bundled  # only the catalog compiled into this binary

Sandbox & Approvals

Two independent controls decide what happens:

  • Sandbox mode sets what Codex can do — where it writes and whether it reaches the network.
  • Approval policy sets when Codex must ask before it acts.
Sandbox modeEffect
read-onlyRead files only
workspace-writeRead anywhere allowed, write inside the workspace and configured writable roots; network off by default
danger-full-accessNo filesystem or network restriction
Approval policyEffect
untrustedRun only known-safe read operations automatically; ask before anything that can mutate state
on-requestRun inside the sandbox freely; ask before leaving it
neverNever ask; Codex does its best within the sandbox you set

Common combinations

IntentFlags
Auto (the default in a Git repo)--sandbox workspace-write --ask-for-approval on-request
Read-only browsing--sandbox read-only --ask-for-approval on-request
Read-only in CI--sandbox read-only --ask-for-approval never
Edit freely, gate commands--sandbox workspace-write --ask-for-approval untrusted
Route approvals to a reviewer agent--sandbox workspace-write -a on-request -c approvals_reviewer=auto_review
No guardrails--dangerously-bypass-approvals-and-sandbox (alias --yolo)

On launch Codex recommends Auto in a version-controlled folder and read-only elsewhere. codex exec defaults to a read-only sandbox. The workspace includes the current directory plus temporary directories such as /tmp; run /status to see the actual writable roots.

Configuration

approval_policy = "on-request"     # untrusted | on-request | never
sandbox_mode    = "workspace-write"
allow_login_shell = false          # optional hardening: reject login-shell requests

[sandbox_workspace_write]
network_access = true              # off by default
writable_roots = ["/srv/build-cache"]
exclude_tmpdir_env_var = false
exclude_slash_tmp = false

Granular approvals keep some prompt categories interactive and auto-reject the rest:

approval_policy = { granular = {
  sandbox_approval    = true,
  rules               = true,
  mcp_elicitations    = true,
  request_permissions = false,
  skill_approval      = false
} }

Protected paths

Inside a writable root these stay read-only, recursively:

  • <root>/.git (and the resolved Git directory when .git is a pointer file)
  • <root>/.agents
  • <root>/.codex

Automatic approval review

approval_policy = "on-request"
approvals_reviewer = "auto_review"   # user (default) | auto_review

A reviewer agent screens only the requests that already need approval: sandbox escalations, blocked network calls, request_permissions prompts, and side-effecting app or MCP tool calls. It checks for data exfiltration, credential probing, persistent security weakening, and destructive actions. It denies critical-risk actions and fails closed on parse or prompt-build errors. It costs extra model calls.

Permission profiles

default_permissions = ":workspace"   # built-ins: :read-only, :workspace, :danger-full-access

[permissions.ci]
description = "Read-only with one allowed host"
extends = ":read-only"
network.enabled = true
network.domains = { "api.example.com" = "allow" }

Do not combine default_permissions with sandbox_mode or [sandbox_workspace_write].

OS enforcement

PlatformMechanism
macOSSeatbelt via sandbox-exec with a profile matching the selected mode
Linuxbwrap plus seccomp
Windows (WSL2)The Linux sandbox
Windows (native)The Windows sandbox: windows.sandbox = "elevated" recommended, "unelevated" as fallback

Test the sandbox

codex sandbox macos   [--permissions-profile <name>] [--log-denials] -- <command>...
codex sandbox linux   [--permissions-profile <name>] -- <command>...
codex sandbox windows [--permissions-profile <name>] -- <command>...

codex sandbox seatbelt and codex sandbox landlock are aliases, and the whole group is also reachable as codex debug.

Containers

Inside Docker the sandbox may fail when the host blocks the namespace, setuid bwrap, or seccomp operations Codex needs. Make the container the security boundary, then run codex --sandbox danger-full-access inside it so Codex does not try to build a second sandbox layer. The secure devcontainer example ships an Ubuntu image, bubblewrap, and an allowlist firewall:

devcontainer up --workspace-folder . --config .devcontainer/devcontainer.secure.json

A devcontainer is not a complete boundary. With --yolo inside it, a hostile repository can still exfiltrate anything the container can reach, including Codex credentials.

Network Access

workspace-write blocks outbound network until you turn it on:

[sandbox_workspace_write]
network_access = true

Turning access on alone gives unrestricted outbound traffic. Add the network_proxy feature to constrain it:

[features.network_proxy]
enabled = true
domains = { "api.openai.com" = "allow", "example.com" = "deny" }
allow_local_binding = false          # default: block loopback and private ranges
codex \
  -c 'features.network_proxy.enabled=true' \
  -c 'features.network_proxy.domains={ "api.openai.com" = "allow" }' \
  -c 'sandbox_workspace_write.network_access=true'
NetworkProxyResult
offonNetwork stays off; the feature does nothing
onoffUnrestricted direct outbound access
ononOutbound traffic constrained by your policy

Domain rules are allowlist-first. example.com matches only itself, *.example.com matches subdomains but not the apex, **.example.com matches both, and * matches any public host. deny always beats allow. Codex classifies resolved addresses before allowing a hostname, so names that resolve to private IPs stay blocked, but that check reduces DNS-rebinding risk rather than removing it. Enforce egress at the network layer too when hostile DNS is in scope.

web_search = "cached"    # cached (default) | indexed | live | disabled

Cached mode serves an OpenAI-maintained index instead of fetching pages live, which lowers prompt-injection exposure. --search switches one run to live. Under --yolo or another full-access setting, web search defaults to live. Treat every web result as untrusted input.

AGENTS.md

Codex reads AGENTS.md before it does any work and rebuilds the instruction chain once per run.

Discovery order:

  1. Global$CODEX_HOME/AGENTS.override.md, otherwise $CODEX_HOME/AGENTS.md. Only the first non-empty file counts.
  2. Project — walk from the project root down to the current directory. In each directory try AGENTS.override.md, then AGENTS.md, then any project_doc_fallback_filenames. At most one file per directory.
  3. Merge — concatenate root-first. Files nearer your working directory appear later and therefore win.

Codex skips empty files and stops once the combined size reaches project_doc_max_bytes (32 KiB by default).

# AGENTS.md

## Repository expectations

- Run `npm run lint` before opening a pull request.
- Use `make test-payments` in `services/payments/`, not `npm test`.
- Document public utilities in `docs/` when behavior changes.

## Code Review Rules

### Experiment cohorts

- Do not filter treatment comparisons on post-exposure behavior.
  Safe path: build cohorts from assignment or exposure; report conversion as an outcome.
project_doc_max_bytes = 65536
project_doc_fallback_filenames = ["TEAM_GUIDE.md", ".agents.md"]
project_root_markers = [".git", ".hg", ".sl"]   # [] means "current directory is the root"

Verify what loaded:

codex --ask-for-approval never "Summarize the current instructions."
codex --cd services/payments -a never "List the instruction sources you loaded."
codex -c log_dir=./.codex-log      # then read ./.codex-log/codex-tui.log

Keep it short. Start minimal and add a rule only after Codex repeats a mistake. Put durable rules here rather than in every prompt.

Skills

A skill is a directory holding a SKILL.md with name and description in front matter, plus optional scripts/, references/, and assets/.

---
name: release-notes
description: Draft release notes from merged PRs. Use when preparing a tagged release.
---

1. List merged PRs since the previous tag.
2. Group them by user-visible change, then by internal change.
3. Write one line per change with the PR number.
ScopeLocation
Repo$CWD/.agents/skills, any .agents/skills above it, $REPO_ROOT/.agents/skills
User$HOME/.agents/skills
Admin/etc/codex/skills
SystemBundled with Codex

Invoke a skill explicitly with /skills or by typing $skill-name. Codex also picks skills implicitly by matching your task against the description, so front-load the trigger words. The initial skill list is capped at 2% of the context window (or 8,000 characters when the window is unknown); Codex shortens descriptions first and warns if it has to omit skills.

$skill-creator          # built-in authoring assistant
$skill-installer linear # install a curated skill
# Disable a skill without deleting it
[[skills.config]]
path = "/path/to/skill/SKILL.md"
enabled = false

Optional agents/openai.yaml inside the skill sets display metadata, invocation policy, and tool dependencies:

interface:
  display_name: "Release notes"
  short_description: "Draft release notes from merged PRs"
policy:
  allow_implicit_invocation: false
dependencies:
  tools:
    - type: "mcp"
      value: "openaiDeveloperDocs"
      transport: "streamable_http"
      url: "https://developers.openai.com/mcp"

Custom prompts (deprecated)

Markdown files in ~/.codex/prompts/ still work as /prompts:<name> slash commands, with $1$9, $ARGUMENTS, and named $UPPERCASE placeholders. Prefer skills: they can be shared through a repository and invoked implicitly.

Subagents & Custom Agents

Subagents keep noisy intermediate output — exploration notes, test logs, stack traces — off the main thread. Ask for them directly:

Review this branch with parallel subagents. Spawn one for security risks, one for
test gaps, and one for maintainability. Wait for all three, then summarize the
findings by category with file references.

Use /agent (or /subagents) to switch between agent threads. Subagents inherit the parent’s sandbox policy and any live overrides you set with /permissions or --yolo, even when a custom agent file says otherwise. They cost more tokens than one comparable run, so prefer them for read-heavy work — exploration, triage, tests, summarization — and be cautious with parallel writes.

Built-in agents: default, worker, explorer.

Custom agent files

One TOML file per agent under ~/.codex/agents/ (personal) or .codex/agents/ (project). name, description, and developer_instructions are required; any other config.toml key may appear too.

# .codex/agents/reviewer.toml
name = "reviewer"
description = "PR reviewer focused on correctness, security, and missing tests."
model = "gpt-5.6-terra"
model_reasoning_effort = "high"
sandbox_mode = "read-only"
developer_instructions = """
Review code like an owner.
Prioritize correctness, security, behavior regressions, and missing test coverage.
Lead with concrete findings and include reproduction steps when possible.
Avoid style-only comments unless they hide a real bug.
"""

[mcp_servers.openaiDeveloperDocs]
url = "https://developers.openai.com/mcp"
# config.toml
[agents]
enabled = true
max_concurrent_threads_per_session = 8
default_subagent_model = "gpt-5.6-luna"
default_subagent_reasoning_effort = "medium"
interrupt_message = true

Codex identifies an agent by its name field, not the filename. A custom agent that reuses a built-in name replaces it.

MCP Servers

Model Context Protocol servers give Codex tools beyond the repository. The CLI, IDE extension, and desktop app share the same configuration.

codex mcp add context7 -- npx -y @upstash/context7-mcp
codex mcp add gh --env GITHUB_TOKEN=$TOKEN -- npx -y @modelcontextprotocol/server-github
codex mcp add figma --url https://mcp.figma.com/mcp --bearer-token-env-var FIGMA_OAUTH_TOKEN
codex mcp list --json
codex mcp get context7
codex mcp login <name>            # OAuth, streamable HTTP servers only

stdio servers

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
cwd = "/opt/tools"
env_vars = ["LOCAL_TOKEN", { name = "REMOTE_TOKEN", source = "remote" }]

[mcp_servers.context7.env]
MY_ENV_VAR = "MY_ENV_VALUE"

Streamable HTTP servers

[mcp_servers.chrome_devtools]
url = "http://localhost:3000/mcp"
auth = "oauth"                       # oauth (default) | chatgpt
bearer_token_env_var = "DEVTOOLS_TOKEN"
http_headers = { "X-Region" = "us-east-1" }
env_http_headers = { "X-Trace" = "TRACE_ID" }
enabled = true
required = false                     # true makes `codex exec` fail if it cannot start
startup_timeout_sec = 20             # default 10
tool_timeout_sec = 45                # default 60
enabled_tools = ["open", "screenshot"]
disabled_tools = ["screenshot"]      # applied after enabled_tools
default_tools_approval_mode = "prompt"   # auto | prompt | writes | approve

[mcp_servers.chrome_devtools.tools.open]
approval_mode = "approve"
# Only needed when your OAuth provider demands a fixed callback
mcp_oauth_callback_port = 5555
mcp_oauth_callback_url = "https://devbox.example.internal/callback"

writes prompts only for tools that are not marked read-only. Tool calls that advertise a destructive annotation always require approval.

Codex as an MCP server

codex mcp-server        # speaks MCP over stdio so another agent can call Codex

Useful servers: OpenAI Docs, Context7, Playwright, Chrome DevTools, GitHub, Sentry, Figma.

Plugins

Plugins package skills, connectors, MCP servers, and hooks for distribution.

codex plugin marketplace add openai/skills          # GitHub shorthand, Git URL, SSH URL, or local path
codex plugin marketplace add owner/repo@v1 --sparse skills/
codex plugin marketplace list --json
codex plugin marketplace upgrade                    # refresh all Git-backed marketplaces
codex plugin marketplace remove <name>

codex plugin add <plugin>@<marketplace> --json
codex plugin list --available --json
codex plugin remove <plugin> -m <marketplace>
[plugins."sample@test".mcp_servers.sample]
enabled = true
default_tools_approval_mode = "prompt"
enabled_tools = ["read", "search"]

Browse and toggle plugins in the TUI with /plugins.

Hooks

Hooks run your own scripts inside the agent loop — to log turns, block pasted secrets, enforce a validation step, or add directory-specific context.

TimingEvents
During a turnPreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop
At session or subagent startSessionStart, SubagentStart
When the main thread endsSessionEnd (not for subagents)

Codex reads hooks.json or an inline [hooks] table next to each active config layer. The four locations that matter in practice:

  • ~/.codex/hooks.json
  • ~/.codex/config.toml
  • <repo>/.codex/hooks.json
  • <repo>/.codex/config.toml
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.codex/hooks/session_start.py",
            "statusMessage": "Loading session notes",
            "additionalContextLimit": 5000
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "python3 ~/.codex/hooks/check_bash.py", "timeout": 30 }
        ]
      }
    ]
  }
}
# Equivalent inline form
[[hooks.PreToolUse]]
matcher = "^Bash$"

[[hooks.PreToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
timeout = 30
statusMessage = "Checking Bash command"

Every matching hook from every layer runs, and matching command hooks for one event start concurrently. A non-managed command hook must be reviewed and trusted before it runs; Codex records trust against the hook’s hash, so editing a hook sends it back for review. Manage all of this with /hooks. Project hooks load only when the project .codex/ layer is trusted.

Rules (execpolicy)

Rules decide which commands may run outside the sandbox. They are experimental and written in Starlark.

# ~/.codex/rules/default.rules
prefix_rule(
    pattern = ["gh", "pr", "view"],
    decision = "prompt",                     # allow | prompt | forbidden
    justification = "Viewing PRs is allowed with approval",
    match = [
        "gh pr view 7888",
        "gh pr view --repo openai/codex",
    ],
    not_match = [
        "gh pr --repo openai/codex view 7888",   # pattern must be an exact prefix
    ],
)
codex execpolicy check --pretty \
  --rules ~/.codex/rules/default.rules \
  -- gh pr view 7888 --json title,body,comments

Codex scans rules/ under every active config layer, including <repo>/.codex/rules/ when the project is trusted. When several rules match, the most restrictive decision wins (forbidden > prompt > allow). Allowing a command from the TUI writes it to ~/.codex/rules/default.rules.

Codex splits a shell wrapper such as bash -lc "git add . && rm -rf /" into separate commands when the script is a plain chain joined by &&, ||, ;, or |, then evaluates each one — so allowing git add never auto-allows the rm. When the script uses redirection, substitution, variables, globs, or control flow, Codex refuses to split it and applies your rules to the whole invocation.

Non-Interactive Mode (codex exec)

codex exec "summarize the repository structure and list the top 5 risky areas"
codex exec --sandbox workspace-write "fix the failing unit test"
codex exec --ephemeral "triage this repository"      # no rollout files on disk
codex e "short form"

Progress goes to stderr; only the final message goes to stdout, so piping is clean:

codex exec "generate release notes for the last 10 commits" | tee release-notes.md

Stdin

# Prompt as the argument, piped output as context
npm test 2>&1 | codex exec "summarize the failing tests and propose the smallest fix"

# Stdin is the whole prompt
cat prompt.txt | codex exec -
generate_prompt.sh | codex exec - --json > result.jsonl

Machine-readable output

codex exec --json "summarize the repo structure" | jq
{"type":"thread.started","thread_id":"0199a213-81c0-7800-8aa1-bbab2a035a53"}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"item_1","type":"command_execution","command":"bash -lc ls","status":"in_progress"}}
{"type":"item.completed","item":{"id":"item_3","type":"agent_message","text":"Repo contains docs, sdk, and examples."}}
{"type":"turn.completed","usage":{"input_tokens":24763,"cached_input_tokens":24448,"output_tokens":122,"reasoning_output_tokens":0}}

Event types: thread.started, turn.started, turn.completed, turn.failed, item.*, error. Items cover agent messages, reasoning, command executions, file changes, MCP tool calls, web searches, and plan updates.

Structured output

{
  "type": "object",
  "properties": {
    "project_name": { "type": "string" },
    "programming_languages": { "type": "array", "items": { "type": "string" } }
  },
  "required": ["project_name", "programming_languages"],
  "additionalProperties": false
}
codex exec "Extract project metadata" \
  --output-schema ./schema.json \
  -o ./project-metadata.json

Resume

codex exec "review the change for race conditions"
codex exec resume --last "fix the race conditions you found"
codex exec resume <SESSION_ID> "now add tests"
codex exec resume --last --all "continue"    # consider sessions from any directory

Automation notes

  • Set the least permission the job needs. The default is read-only.
  • codex exec refuses to run outside a Git repository; use --skip-git-repo-check when you are sure.
  • CODEX_API_KEY works only in codex exec. Set it inline for the single invocation, never as a job-level variable in a workflow that also runs repository-controlled code.
  • An enabled MCP server with required = true that fails to initialize makes codex exec exit with an error.
  • Pair --json with -o in CI to capture both the event stream and the final summary.

Configuration

User settings live in ~/.codex/config.toml. Project overrides live in .codex/config.toml files inside the repository.

Precedence, highest first

  1. CLI flags and -c / --config overrides
  2. Project config: .codex/config.toml, root down to the working directory (closest wins, trusted projects only)
  3. Profile file selected with --profile <name> (~/.codex/<name>.config.toml)
  4. User config: ~/.codex/config.toml
  5. System config: /etc/codex/config.toml
  6. Built-in defaults

Run /debug-config to print the resolved layer order and any policy that overrides it.

Project trust

If a project is untrusted, Codex skips every project .codex/ layer — config, hooks, and rules. User and system layers still load. Project config also cannot set machine-local keys; Codex ignores and warns about openai_base_url, chatgpt_base_url, apps_mcp_product_sku, model_provider, model_providers, notify, profile, profiles, experimental_realtime_ws_base_url, and otel in a project file.

Profiles

Each profile is its own file with top-level keys:

# ~/.codex/deep-review.config.toml
model = "gpt-5.6-sol"
model_reasoning_effort = "xhigh"
approval_policy = "on-request"
codex --profile deep-review
codex exec --profile deep-review "review this change"

Since Codex 0.134.0, [profiles.<name>] tables inside config.toml and the top-level profile = "<name>" selector no longer work. Move them to separate profile files.

Model providers

model = "gpt-5.6-terra"
model_provider = "proxy"

[model_providers.proxy]
name = "OpenAI via LLM proxy"
base_url = "https://proxy.example.com/v1"
env_key = "OPENAI_API_KEY"          # or requires_openai_auth = true to reuse Codex login
wire_api = "responses"
http_headers = { "X-Example" = "value" }
env_http_headers = { "X-Features" = "EXAMPLE_FEATURES" }

[model_providers.azure]
name = "Azure"
base_url = "https://YOUR_PROJECT.openai.azure.com/openai"
env_key = "AZURE_OPENAI_API_KEY"
query_params = { api-version = "2025-04-01-preview" }
wire_api = "responses"

To point the built-in provider at a proxy without defining a new one, set openai_base_url. openai, ollama, and lmstudio are reserved provider IDs. Chat Completions support is deprecated; prefer wire_api = "responses".

Command-backed auth for providers that mint short-lived tokens:

[model_providers.proxy.auth]
command = "/usr/local/bin/fetch-codex-token"
args = ["--audience", "codex"]
timeout_ms = 5000
refresh_interval_ms = 300000        # 0 refreshes only after an auth retry

The command receives no stdin and prints the token to stdout. Do not combine it with env_key, experimental_bearer_token, or requires_openai_auth.

Amazon Bedrock is built in:

model_provider = "amazon-bedrock"
model = "<bedrock-model-id>"

[model_providers.amazon-bedrock.aws]
profile = "default"
region = "eu-central-1"

Local models

codex --oss --local-provider ollama
oss_provider = "ollama"   # ollama | lmstudio

codex exec --oss errors out when neither --local-provider nor oss_provider is set; the interactive CLI prompts instead.

Feature flags

codex features list
codex features enable memories
codex features disable hooks
codex --enable network_proxy --disable pets   # one run only
FlagDefaultPurpose
appstrueApp (connector) integrations
goalstruePersisted goals and automatic continuation
hookstrueLifecycle hooks
fast_modetrueFast service tier and /fast
memoriesfalseMemories (experimental)
multi_agenttrueSubagent tools
personalitytruePersonality selection
remote_plugintrueRemote plugin catalog
shell_snapshottrueCache the shell environment between commands
shell_tooltrueThe default shell tool
unified_exectrue except WindowsPTY-backed exec tool and background terminals
network_proxyfalseConstrain outbound traffic to a policy

web_search, web_search_cached, and web_search_request are deprecated flags; use the top-level web_search setting instead.

Command environment

[shell_environment_policy]
inherit = "core"                 # all | core | none
ignore_default_excludes = false  # false turns ON filtering of *KEY*, *SECRET*, *TOKEN*

[shell_environment_policy.filters]
"PATH" = "include"
"HOME" = "include"

ignore_default_excludes defaults to true, meaning Codex does not filter variables whose names contain KEY, SECRET, or TOKEN. Set it to false to turn that filtering on.

Notifications

notify = ["python3", "/path/to/notify.py"]   # external program, user config only

[tui]
notifications = true              # or ["agent-turn-complete", "approval-requested"]
notification_method = "auto"      # auto | osc9 | bel
notification_condition = "unfocused"   # unfocused | always

The notify program receives one JSON argument. The only event today is agent-turn-complete, and the payload carries type, thread-id, turn-id, cwd, input-messages, and last-assistant-message.

History

[history]
persistence = "save-all"   # save-all | none
max_bytes = 104857600      # 100 MiB; oldest entries drop first

Clickable citations

file_opener = "vscode"   # vscode | vscode-insiders | windsurf | cursor | none

A citation like /home/user/project/main.py:42 becomes a vscode://file/…:42 link.

Config Key Reference

The keys you are most likely to set. See /debug-config for what is actually in effect.

KeyValuesNotes
modelstringActive model
review_modelstringModel for /review only
model_providerprovider idDefault openai
model_reasoning_effortminimalxhighResponses API models
model_reasoning_summaryauto, concise, detailed, noneSummary detail
model_verbositylow, medium, highResponse length
model_context_windownumberOverride the detected window
model_auto_compact_token_limitnumberWhen automatic compaction kicks in
personalitynone, friendly, pragmaticCommunication style
service_tierstringfast maps to request priority
approval_policyuntrusted, on-request, never, { granular = … }on-failure is deprecated
approvals_revieweruser, auto_reviewWho screens approval requests
sandbox_moderead-only, workspace-write, danger-full-accessCommand sandbox
sandbox_workspace_write.network_accessbooleanOff by default
sandbox_workspace_write.writable_rootsarrayExtra writable directories
allow_login_shellbooleanDefault true; false rejects login shells
default_permissionsprofile nameDo not mix with sandbox_mode
web_searchdisabled, cached, indexed, liveDefault cached
windows.sandboxelevated, unelevatedNative Windows only
project_doc_max_bytesnumberDefault 32768
project_doc_fallback_filenamesarrayExtra instruction filenames
project_root_markersarrayDefault [".git"]
developer_instructionsstringExtra instructions injected into the session
model_instructions_filepathReplaces the built-in instructions instead of AGENTS.md
history.persistencesave-all, noneLocal transcript storage
history.max_bytesnumberCap the history file
tool_output_token_limitnumberToken budget per stored tool output
file_openereditor schemeClickable citations
notifyarrayExternal notification command
tui.notificationsboolean or arrayTerminal notifications
tui.resume_cwdcurrent, sessionSkip the resume directory prompt
tui.alternate_screenauto, always, nevernever keeps terminal scrollback
tui.vim_mode_defaultbooleanVim composer by default
tui.themetheme nameSyntax highlighting
tui.status_linearray or nullFooter items
hide_agent_reasoningbooleanQuieter CI logs
show_raw_agent_reasoningbooleanSurface raw reasoning when emitted
check_for_update_on_startupbooleanDisable when updates are centrally managed
cli_auth_credentials_storefile, keyring, autoCredential storage
forced_login_methodchatgpt, apiManaged environments
forced_chatgpt_workspace_idUUIDRestrict to one workspace
log_dirpathSetting it enables codex-tui.log
sqlite_homepathSQLite-backed runtime state

Environment Variables

VariableUsed byPurpose
CODEX_HOMEeverythingRoot for config, auth, logs, sessions, skills. Codex creates the default ~/.codex for you, but when you set CODEX_HOME yourself the directory must already exist — Codex does not create it and exits with CODEX_HOME points to "…", but that path does not exist
CODEX_SQLITE_HOMECLI, app serverSQLite state location; sqlite_home config wins
CODEX_API_KEYcodex exec onlyAPI key for a single non-interactive run
CODEX_ACCESS_TOKENCLI, app serverChatGPT or Codex access token for trusted automation
CODEX_CA_CERTIFICATEHTTPS, login, WebSocketPEM CA bundle; takes precedence over SSL_CERT_FILE
SSL_CERT_FILEHTTPS, login, WebSocketFallback CA bundle
RUST_LOGCLI, app serverLog filter: error, warn, info, debug, trace, or targeted filters
CODEX_NON_INTERACTIVEinstallersSkip installer prompts
CODEX_INSTALL_DIRinstallersWhere the codex command is installed
VISUAL / EDITORTUIEditor opened by Ctrl+G
# Verbose troubleshooting run with a plaintext log
RUST_LOG=debug codex -c log_dir=./.codex-log
tail -F ./.codex-log/codex-tui.log

# Targeted filters
RUST_LOG=codex_core=debug,codex_tui=debug codex

# Create the directory first when you point CODEX_HOME somewhere new
mkdir -p /srv/codex-home
CODEX_HOME=/srv/codex-home codex

codex exec defaults to RUST_LOG=error and prints messages inline instead of to a separate log file.

Files & State Locations

PathContents
~/.codex/config.tomlUser configuration
~/.codex/<profile>.config.tomlProfile layer selected with --profile
~/.codex/AGENTS.md, AGENTS.override.mdGlobal instructions
~/.codex/auth.jsonCached credentials when using file storage. Treat as a secret
~/.codex/history.jsonlSession transcript history when history.persistence is on
~/.codex/sessions/Session transcripts (session-*.jsonl)
~/.codex/archived_sessions/Archived transcripts
~/.codex/agents/Personal custom agent files
~/.codex/rules/execpolicy .rules files
~/.codex/prompts/Deprecated custom prompts
~/.codex/themes/Custom .tmTheme files
~/.codex/hooks.jsonUser hooks
~/.codex/worktrees/Desktop-app managed worktrees
~/.codex/log/Logs, including codex-login.log
~/.agents/skills/User skills
<repo>/.codex/config.tomlProject configuration (trusted projects only)
<repo>/.codex/agents/, rules/, hooks.jsonProject agents, rules, hooks
<repo>/.agents/skills/Repository skills
<repo>/AGENTS.mdProject instructions
/etc/codex/config.tomlSystem configuration
/etc/codex/skills/Machine-wide skills
~/Library/Logs/com.openai.codex/YYYY/MM/DDDesktop app logs (macOS)

Code Review

codex review --uncommitted
codex review --base main
codex review --commit 1a2b3c4

In a session, /review offers four scopes:

  • Against a base branch — finds the merge base and reviews the branch diff.
  • Uncommitted changes — staged, unstaged, and untracked files.
  • A commit — the exact change set of one commit.
  • Custom instructions — your own criteria.

The reviewer reads the diff and reports prioritized findings without touching your working tree. It uses the session model unless you set review_model. If you then ask Codex to apply the fixes, your normal sandbox and approval settings apply.

Repository-wide review criteria belong in a ## Code Review Rules section of the AGENTS.md nearest the code they govern. Keep them about behavior, and leave formatting to CI.

Codex in CI

Prefer the openai/codex-action over installing the CLI and exporting a key yourself. The action installs Codex, starts a Responses API proxy, and runs codex exec under a safety strategy.

name: Codex pull request review
on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  codex:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    outputs:
      final_message: ${{ steps.run_codex.outputs.final-message }}
    steps:
      - uses: actions/checkout@v5
        with:
          ref: refs/pull/${{ github.event.pull_request.number }}/merge
          fetch-depth: 0
          persist-credentials: false

      - name: Run Codex
        id: run_codex
        uses: openai/codex-action@v1
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          prompt-file: .github/codex/prompts/review.md
          output-file: codex-output.md
          sandbox: read-only
InputPurpose
prompt / prompt-fileInline instructions or a repository path. Set exactly one
codex-argsExtra CLI flags as a JSON array (["--ephemeral"]) or a string
model, effortModel and reasoning effort
sandboxread-only, workspace-write, danger-full-access
output-fileWhere to save the final message
codex-versionPin a CLI release
codex-homeReuse a configuration directory across steps
safety-strategydrop-sudo (default), unprivileged-user, read-only, unsafe
codex-userAccount to run as with unprivileged-user
allow-users, allow-botsWho may trigger the workflow beyond write collaborators

Windows runners require safety-strategy: unsafe. The final-message output carries the last Codex message.

Separate the key from write access

Give the Codex job contents: read and have it upload a patch artifact. Apply that patch and open the pull request in a second job that has write permission but no API key:

      - name: Create patch artifact
        run: |
          git add -N .
          git diff --binary HEAD > codex.patch

Sanitize any prompt text that comes from pull requests, commit messages, or issue bodies. Hidden HTML comments are a prompt-injection vector.

Codex SDK

TypeScript (Node 18+)

npm install @openai/codex-sdk
const codex = new Codex();
const thread = codex.startThread();

const result = await thread.run("Make a plan to diagnose and fix the CI failures");
console.log(result.finalResponse);

const next = await thread.run("Implement the plan");

const resumed = codex.resumeThread("<thread-id>");
await resumed.run("Pick up where you left off");

Python (3.10+)

pip install openai-codex
from openai_codex import Codex, Sandbox

with Codex() as codex:
    thread = codex.thread_start(
        model="gpt-5.6-terra",
        sandbox=Sandbox.workspace_write,
    )
    result = thread.run("Make a plan to diagnose and fix the CI failures")
    print(result.final_response)

    review = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
import asyncio
from openai_codex import AsyncCodex

async def main() -> None:
    async with AsyncCodex() as codex:
        thread = await codex.thread_start(model="gpt-5.6-terra")
        result = await thread.run("Implement the plan")
        print(result.final_response)

asyncio.run(main())

Sandbox presets: Sandbox.read_only, Sandbox.workspace_write, Sandbox.full_access. A sandbox passed to run() applies to that turn and every later turn on the thread.

Use the SDK for coding threads. When Codex is one specialist inside a wider orchestration, run codex mcp-server and drive it from the Agents SDK instead.

Codex Cloud

Codex cloud runs tasks in isolated OpenAI-managed containers. Setup runs first with network access to install dependencies; the agent phase then runs offline unless you enable internet access for that environment. Secrets are available only during setup and are removed before the agent phase.

codex cloud                                    # interactive picker
codex cloud exec --env <ENV_ID> "migrate the config loader" --attempts 3
codex cloud list --env <ENV_ID> --limit 20 --json
codex apply <TASK_ID>                          # apply the resulting diff locally

codex cloud list --json returns a tasks array with id, url, title, status, updated_at, environment_id, environment_label, summary, is_review, and attempt_total, plus an optional cursor. --attempts accepts 1–4 and runs best-of-N. codex apply exits non-zero when git apply fails.

Getting started: open chatgpt.com/codex, connect GitHub, create an environment for the repository, then start a task. You can also start work from GitHub pull requests, Linear issues, and Slack.

IDE Extension

Install the ChatGPT extension for VS Code, Cursor, Windsurf, or VS Code Insiders. Xcode and JetBrains IDEs have their own Codex integrations.

Command IDDefault bindingPurpose
chatgpt.openSidebarOpen the Codex sidebar
chatgpt.newChatCmd+N / Ctrl+NNew chat
chatgpt.newCodexPanelNew Codex panel
chatgpt.addToThreadAdd the selected range as context
chatgpt.addFileToThreadAdd the whole file as context
chatgpt.openCommandMenuOpen the command menu

IDE slash commands: /approve, /cloud, /cloud-environment, /compact, /fast, /feedback, /fork, /goal, /ide-context, /init, /local, /mcp, /memories, /model, /personality, /plan, /project, /reasoning, /review, /side, /status, /worktree.

On Windows, keep the agent inside WSL2 so it inherits Linux sandbox semantics:

{ "chatgpt.runCodexInWindowsSubsystemForLinux": true }

Set chatgpt.reviewDelivery to detached when /review should open its own chat instead of running in the current one.

Observability

Telemetry is off by default.

[otel]
environment = "staging"    # dev | staging | prod
exporter = "none"          # none | otlp-http | otlp-grpc
log_user_prompt = false    # keep false unless policy allows storing prompts
[otel]
exporter = { otlp-http = {
  endpoint = "https://otel.example.com/v1/logs",
  protocol = "binary",
  headers = { "x-otlp-api-key" = "${OTLP_TOKEN}" }
}}

Representative events: codex.conversation_starts, codex.api_request, codex.sse_event, codex.websocket_request, codex.websocket_event, codex.user_prompt, codex.tool_decision, codex.tool_result. Each has a matching counter and duration histogram.

Route telemetry only to collectors you control, apply retention limits, and redact tool arguments and outputs at the collector. Export cannot reach your collector when the CLI runs with network access off.

Common Issues & Solutions

IssueCauseFix
codex exec refuses to startNot inside a Git repositoryRun it in a repo, or pass --skip-git-repo-check
Sandbox fails to start in DockerContainer blocks namespaces, setuid bwrap, or seccompMake the container the boundary and run --sandbox danger-full-access inside it
Project .codex/config.toml ignoredProject is untrusted, or the key is machine-localTrust the project; move model_providers, notify, otel, and similar keys to user config
Instructions look stale or wrongAn AGENTS.override.md higher in the tree, or a truncated fileRemove the override; raise project_doc_max_bytes or split the file
Fallback instruction filenames ignoredNot listed in configAdd them to project_doc_fallback_filenames and restart
Browser login never completesHeadless host or blocked localhost callbackcodex login --device-auth, forward port 1455 over SSH, or copy auth.json
TLS errors on login or requestsCorporate TLS interceptionSet CODEX_CA_CERTIFICATE to a PEM bundle
Codex asks approval for everythingapproval_policy = "untrusted"Switch to on-request, or add a prefix_rule with decision = "allow"
A command needs the network and stallsworkspace-write blocks network by defaultSet sandbox_workspace_write.network_access = true, ideally with network_proxy
Answers cite outdated releasesWeb search is cached by defaultRun with --search or set web_search = "live"
MCP server never appearsSlow start, or disabledRaise startup_timeout_sec, check enabled, run /mcp verbose
codex exec exits over an MCP serverServer has required = true and failed to initializeFix the server or set required = false
A hook never runsNon-managed hooks need explicit trustReview and trust it with /hooks
A hook stopped running after an editTrust is recorded against the hook hashRe-trust the changed hook in /hooks
allowing git add did not allow a chained commandCodex splits safe shell chains and evaluates each partWrite a rule for the other command, or approve it once
--profile has no effect[profiles.<name>] tables stopped working in 0.134.0Move settings to ~/.codex/<name>.config.toml
Model not found or rejectedgpt-5.4, gpt-5.4-mini, gpt-5.2, or gpt-5.3-codex under ChatGPT sign-inUse gpt-5.6-terra or gpt-5.6-luna
/fast is missingThe active model advertises no Fast tierSwitch models, or check features.fast_mode
Sandbox broken on WindowsWSL1 is unsupported since 0.115Move to WSL2, or use the native Windows sandbox
Windows sandbox reported as degradedRestricted-token fallback in useRun /setup-default-sandbox and set windows.sandbox = "elevated"
fatal: '<branch>' is already used by worktree at …Git allows one checkout per branchCheck out a different branch on the worktree, or hand the chat off to Local
Secrets leak into spawned commandsDefault policy does not filter *KEY*, *SECRET*, *TOKEN*Set shell_environment_policy.ignore_default_excludes = false or use include_only
Chat degrades over a long runContext filled with intermediate output/compact, /new, or delegate noisy work to subagents
CI logs are noisyReasoning events are printedSet hide_agent_reasoning = true
Feature works in the CLI but not the desktop appThe two ship different Codex versionsCompare codex --version with /Applications/Codex.app/Contents/Resources/codex --version

Quick Tips

  • Run /status before you trust a session. It shows the model, the approval policy, and the writable roots you are actually running under.
  • Commit before and after a Codex task. A clean tree makes its patch trivial to review and revert.
  • Put durable rules in AGENTS.md, not in every prompt. Add a rule only after Codex makes the same mistake twice.
  • State the goal, the context, the constraints, and how you will judge the result. A prompt missing the last part usually produces work you have to redo.
  • Prefer --add-dir over --sandbox danger-full-access when Codex needs to write somewhere else.
  • --yolo belongs inside a disposable VM or container, nowhere else.
  • Use --sandbox read-only for anything exploratory. Most questions do not need write access.
  • codex exec writes progress to stderr and only the final message to stdout, so it pipes cleanly. Add --json when a script must read the events.
  • Use --output-schema when a downstream step needs stable fields; parsing prose is a false economy.
  • Keep one chat per outcome. Use /fork to explore an alternative and /compact before the context fills.
  • Delegate read-heavy work — exploration, triage, log analysis — to subagents so their output never lands in the main thread. Be careful with parallel writes.
  • Turn a workflow you have repeated three times into a skill, not another prompt.
  • Treat every web result and MCP tool output as untrusted input. Cached search is the default for exactly that reason.
  • Never set OPENAI_API_KEY or CODEX_API_KEY job-wide in a workflow that also runs repository-controlled code.
  • Give the CI job that runs Codex contents: read and let a separate job hold write permission.
  • Pin codex-version in CI so a new release cannot change your pipeline’s behavior overnight.
  • Run codex doctor before filing a bug; it checks installation, config, auth, Git, and terminal in one pass.
  • codex execpolicy check tests a rule before you rely on it, and match / not_match act as inline unit tests inside the rule itself.