# Stop fighting Codex CLI's approval prompts

URL: https://www.thedeepfeed.ai/posts/2026-06-10-stop-fighting-codex-cli-approval-prompts/
Category: Tools
Published: 2026-06-10
Author: the-deep-feed
Tags: codex, openai, coding-agents, claude-code, developer-workflow
Kind: deep

> The Codex CLI config that ends the permission nagging — config.toml profiles, sandbox and approval modes, AGENTS.md, reasoning effort, MCP servers, and the codex exec setup for CI.

## TL;DR

- Codex CLI is **OpenAI's open-source, Rust-based terminal agent** (Apache-2.0, ~89K stars). It is **sandbox-first**: approval friction is the default, and most people fight it instead of configuring it away.
- The fix is two orthogonal dials, not one: **`sandbox_mode`** (what it *can* do) and **`approval_policy`** (when it *asks*). Set `workspace-write` + `on-request` for daily work and the nagging stops.
- Config lives in **`~/.codex/config.toml`** — TOML, with `mcp_servers` not `mcpServers`. Use **profiles** to keep a high-reasoning model, a fast model, and a zero-data-retention model one `--profile` flag apart.
- Memory is **`AGENTS.md`**, merged root-to-leaf up to 32 KiB. A tight one is the single best cure for Codex's tendency to over-engineer simple changes.
- For CI, **`codex exec`** runs headless with `--json` event output and `--sandbox read-only`. The official `openai/codex-action@v1` wraps it with privilege controls.

![A terminal running Codex CLI with a calm, unobstructed flow of edits — the result of configured sandbox and approval modes rather than constant prompts](/post-images/2026-06-10-stop-fighting-codex-cli-approval-prompts/01-hero-approval-flow.jpg)
*The difference between fighting Codex and flowing with it is two TOML keys.*

The most common thing a new Codex CLI user does is rage-quit over approval prompts. They install it, ask it to run the test suite, and watch it stop to ask permission before every single command — read this file, run that test, read the next file. The GitHub issue tracker has the receipts: ["asking permission for every single file read"](https://github.com/openai/codex/issues/13117), ["Approval prompt shown for almost every command"](https://github.com/openai/codex/issues/14936), thread after thread of people hitting the same wall. The reaction is almost always to blame the tool. The actual problem is that **Codex CLI is sandbox-first by design**, and nobody read the two config keys that turn the friction off.

Codex CLI is OpenAI's open-source coding agent — a single Rust binary, Apache-2.0 licensed, that as of June 2026 sits at roughly [89,000 GitHub stars](https://github.com/openai/codex) on release `rust-v0.137.0`. It was rewritten from TypeScript to Rust in mid-2025 precisely so it could enforce OS-level sandboxing without a Node runtime in the way. That sandbox is the whole personality of the tool: secure by default, and noisy until you tell it what you trust. This guide is about telling it.

Every config block below is copy-pasteable and traces to the [official Codex docs](https://developers.openai.com/codex/), the [config schema](https://developers.openai.com/codex/config-schema.json) (92 documented keys), or the repository. Where the community argues about Codex versus Claude Code, and that argument is the loudest in the field right now, the quotes are real and sourced.

## TL;DR

- **Two dials, not one.** `sandbox_mode` controls capability; `approval_policy` controls how often it asks. `workspace-write` + `on-request` is the daily-driver combo.
- **Config is `~/.codex/config.toml`.** TOML, not JSON. The MCP key is `mcp_servers` in snake_case; `mcpServers` silently does nothing.
- **Profiles are the killer feature.** Define a high-reasoning profile, a fast one, and a zero-retention one; switch with `--profile`.
- **Tune reasoning per task.** `model_reasoning_effort` runs `minimal` to `xhigh`. Low for plumbing, high for architecture. Wrong setting is half the "it's too slow" complaints.
- **`AGENTS.md` is the memory.** Merged root-to-leaf, 32 KiB cap. A tight one stops Codex from over-engineering.
- **`codex exec` is the CI mode.** Headless, `--json` events, read-only sandbox by default. Wrap it with `openai/codex-action@v1`.
- **Reach for a model that fits.** GPT-5.5 for most work, the `*-codex` variants for long coding runs. The picker depends on your plan.

## The 5-minute setup

Install, authenticate, and drop in a config that ends the prompt-nagging on day one.

```bash
# 1. Install (any of these)
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# or: npm install -g @openai/codex   |   brew install --cask codex

# 2. Authenticate — sign in with ChatGPT (uses your plan) or an API key
codex                       # first run walks you through sign-in

# 3. Scaffold project memory
cd my-project
codex                       # launch the TUI
/init                       # writes AGENTS.md from your codebase

# 4. Drop in a real ~/.codex/config.toml (full version below)
$EDITOR ~/.codex/config.toml
```

A starter `~/.codex/config.toml` that picks a sane model, sets the two dials so Codex stops asking about every read, and tunes reasoning for real work:

```toml
# ~/.codex/config.toml
model = "gpt-5.5"
approval_policy = "on-request"      # ask only when it needs to escalate
sandbox_mode    = "workspace-write" # edit + run inside the project freely
model_reasoning_effort = "medium"   # raise to "high" for hard problems
```

That single change, `workspace-write` plus `on-request`, is the difference between an agent that interrupts you forty times and one that works through a task and only stops when it genuinely needs to touch something outside the project or reach the network.

## The mental model: two dials, not one

Almost everyone misunderstands Codex's permission system because they think it is one setting. It is two, and they are orthogonal:

- **`sandbox_mode`** decides what Codex is *technically capable* of doing. It is enforced by the operating system — Apple Seatbelt on macOS, Landlock plus seccomp on Linux. Even if the model decides to delete your home directory, the sandbox physically prevents it.
- **`approval_policy`** decides *when Codex pauses to ask you*. It is a workflow choice layered on top of the sandbox.

The reason this matters: cranking one does not fix the other. People set `approval_policy = "never"` to stop the prompts, then wonder why the agent can't write files — because the sandbox is still `read-only`. Or they open the sandbox to `danger-full-access` and leave approvals on `untrusted`, and get prompted constantly anyway. You configure both, deliberately.

The values, exactly:

| `sandbox_mode` | What it allows |
|---|---|
| `read-only` | Read and reason only. Every edit or command needs approval. (Default.) |
| `workspace-write` | Edit files and run commands inside the project. Network off by default. `.git/` stays read-only. |
| `danger-full-access` | Full disk and network, no walls. For trusted containers only. |

| `approval_policy` | When Codex asks |
|---|---|
| `untrusted` | Asks for anything not on a known-safe list. |
| `on-request` | The model asks only when it wants to escalate. |
| `on-failure` | Runs in the sandbox; asks only if a command fails. (Deprecated.) |
| `never` | Never asks. `codex exec` always uses this. |

The presets in the TUI map onto these: **Read Only** (read-only + ask), **Auto** (workspace-write + on-request, the default inside a git repo), and **Full Access** (danger-full-access + never, labeled "extremely risky" for good reason).

![Two labeled dials side by side: SANDBOX MODE with positions read-only, workspace-write, danger-full-access; and APPROVAL POLICY with positions untrusted, on-request, never; an arrow shows the daily-driver setting on each](/post-images/2026-06-10-stop-fighting-codex-cli-approval-prompts/02-two-dials.jpg)
*The two orthogonal dials. Setting one without the other is why people fight Codex.*

## config.toml: the keys that matter

Codex reads `~/.codex/config.toml` (the `CODEX_HOME` env var relocates it). A project-local `.codex/config.toml` is loaded only for trusted projects, and it ignores a handful of keys for safety (`model_provider`, `model_providers`, `profile`, `profiles`, `notify`) that must be set at the user level. Precedence runs: CLI flag beats profile beats `config.toml` beats the built-in default.

The full sandbox configuration, with the workspace-write sub-table that most people never discover:

```toml
model = "gpt-5.5"
approval_policy = "on-request"
sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = false                 # flip to true if the task needs the internet
exclude_tmpdir_env_var = false
exclude_slash_tmp = false
writable_roots = ["/Users/you/.pyenv/shims"]   # extra paths to allow writes
```

Network access being off by default inside `workspace-write` is the source of the second-most-common confusion, right after approvals: `npm install` or `pip install` will stall until you either approve it or set `network_access = true`. That is a feature, since it stops a compromised package's install script from phoning home, but you have to know it's there.

Reasoning and verbosity, the dials that fix "Codex is too slow" and "Codex writes a novel":

```toml
model_reasoning_effort  = "high"    # none | minimal | low | medium | high | xhigh
model_reasoning_summary = "auto"    # auto | concise | detailed | none
model_verbosity         = "low"     # low | medium | high (GPT-5 family)
```

One commenter's complaint captures why this matters: ["If you use the low or medium reasoning it's garbage. If you use high, it'll think for up to five minutes on something dead simple."](https://news.ycombinator.com/item?id=45252301) That is not a flaw, it's an un-tuned tool. Set `minimal` or `low` for mechanical edits, `high` or `xhigh` for genuine design work, and stop asking one setting to serve both jobs.

## Profiles: a model loadout one flag away

Profiles are the most underused feature in Codex, and they are the cleanest answer to "I need different settings for different jobs." Each profile is a named bundle of config; you switch with `--profile`.

```toml
model = "gpt-5.5"
profile = "fast"          # the default profile when none is passed

[profiles.fast]
model = "gpt-5.5"
model_reasoning_effort = "low"
approval_policy = "on-request"
sandbox_mode = "workspace-write"

[profiles.deep]
model = "gpt-5.1-codex-max"
model_reasoning_effort = "xhigh"
model_reasoning_summary = "detailed"
approval_policy = "on-request"
sandbox_mode = "workspace-write"

[profiles.zdr]
model = "gpt-5.5"
disable_response_storage = true      # zero data retention
approval_policy = "untrusted"
sandbox_mode = "read-only"
```

Now `codex --profile deep "redesign the auth layer"` gives you a max-reasoning coding model, `codex --profile fast "rename this variable everywhere"` keeps plumbing cheap and quick, and `codex --profile zdr` runs locked down for sensitive code. One config file, three working postures, zero re-typing of flags.

## AGENTS.md: the memory, and the cure for over-engineering

Codex's project memory is `AGENTS.md` — the same open convention several agents now share. Codex builds its instruction set at startup by discovering these files and **merging them root-to-leaf**: a global `~/.codex/AGENTS.md`, then the project root, then deeper directories, with closer files overriding and a default cap of 32 KiB. `/init` scaffolds one from your codebase.

```markdown
# AGENTS.md

## Conventions
- TypeScript strict mode. No `any`. Run `pnpm typecheck` before done.
- Prefer the smallest change that solves the problem. Do not refactor
  adjacent code unless asked.

## Commands
- Test: `pnpm test`
- Lint: `pnpm lint --fix`

## Boundaries
- Never edit `db/migrations/` — generated.
- Never add a dependency without flagging it first.
```

That "prefer the smallest change" line is doing real work. The single most-cited criticism of GPT-5-class models in coding is a tendency to over-build. As one developer put it on Hacker News: ["GPT-5 is very prone to a style that would for most codebases be overengineering"](https://news.ycombinator.com/item?id=45648422). A tight `AGENTS.md` with explicit scope discipline is the most effective counter — far more than fighting it turn by turn. You can also point Codex at fallback filenames if your team already standardized on something else:

```toml
project_doc_fallback_filenames = ["CONTRIBUTING.md", ".agents.md"]
project_doc_max_bytes = 65536
```

## MCP servers: TOML, and the key name that bites everyone

Codex is an MCP client. Servers go in `config.toml` under `mcp_servers` — and the single most common config mistake is writing `mcpServers` (camelCase, the way other tools spell it), which Codex silently ignores.

```toml
# Correct: snake_case, mcp_servers
[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp@latest"]

[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "ghp_..." }
startup_timeout_sec = 20

[mcp_servers.grep]
url = "https://mcp.grep.app"        # url = streaming HTTP; command/args = stdio
required = false                     # true makes `codex exec` fail hard if it can't start
```

A server with `command`/`args` runs over stdio; one with `url` is a remote HTTP server. The `required` flag is the one to know for CI: set it `true` and a `codex exec` run aborts with a non-zero exit if the server can't initialize, which is exactly what you want in a pipeline and exactly what you don't want interactively. As with any agent, restraint pays — every server's tool list is context the model carries every turn, so install the few that earn their keep and lean on `bash`-callable CLIs (`gh`, `psql`) for the rest.

## codex exec: the headless mode built for CI

The interactive TUI is for you. `codex exec` is for everything automated. It runs non-interactively, streams progress to stderr and the final answer to stdout (so it pipes cleanly), and defaults to a read-only sandbox and `approval_policy = "never"`.

```bash
# One-shot, read-only, pipe the result
codex exec "summarize what changed in the last 10 commits" > summary.md

# Let it actually fix things in a controlled sandbox
codex exec --sandbox workspace-write "fix the failing tests in src/auth"

# Machine-readable event stream for tooling
codex exec --json "audit deps for known CVEs" | jq 'select(.type=="item.completed")'

# Resume the previous run
codex exec resume --last "now open a PR with those fixes"
```

Authentication for headless runs uses `CODEX_API_KEY` (note: this variable is read only in `codex exec`, and as of v0.36.0 plain `OPENAI_API_KEY` is no longer picked up implicitly — a breaking change that surprised a lot of CI pipelines). The `--json` event stream emits structured objects (`thread.started`, `turn.completed`, `item.*`, `error`) that you can drive a dashboard or a gate off.

For GitHub specifically, the official [`openai/codex-action@v1`](https://github.com/openai/codex-action) wraps `codex exec` with privilege controls:

```yaml
- uses: openai/codex-action@v1
  with:
    openai-api-key: ${{ secrets.OPENAI_API_KEY }}
    prompt: "Review this PR's diff for security regressions and comment."
    safety-strategy: drop-sudo      # drop-sudo (default) | unprivileged-user | unsafe
```

## Codex versus Claude Code: what the switchers actually say

No tool guide written in 2026 can ignore the rivalry, because it is the most active migration in developer tooling. The short version: after GPT-5 and the `gpt-5-codex` models landed, a wave of heavy Claude Code users moved to Codex, and the reasons they give are consistent and specific.

The headline claim, from a team that tracked its spend:

> We were heavy users of Claude Code ($70K+ spend per year) and have almost completely switched to codex CLI. I'm doing massive lifts with it on software that would never before have been feasible for me personally, or any team I've ever run.
>
> — [mmaunder](https://news.ycombinator.com/item?id=45648422), Hacker News

The mechanism, repeatedly, is instruction-following — Codex does what you said, where Claude Code is more eager to expand on the request:

> Not suddenly, it's been better since GPT-5 launched... With Claude Code, you can use less prompting, and Claude will get token happy and expand on your request. Great for greenfield/vibing, bad for iterating on existing projects. With Codex CLI, GPT-5 seems to handle instructions much more precisely. It won't just go off on its own.
>
> — [jumploops](https://news.ycombinator.com/item?id=45252301), Hacker News

But the honest picture includes the counter-case, and it lands on exactly the friction this guide opened with — plus a UX gap Claude Code genuinely still wins:

> the Claude Code UI is still so much better, and the permissioning policy system is much better... sick of Codex asking for approval to run tests for each test instance.
>
> — maherbeg, [Hacker News](https://news.ycombinator.com/item?id=45648422)

That complaint is real, and it is also, mostly, a configuration problem — the approval nagging is precisely what `workspace-write` plus `on-request` fixes. The fair summary is that Codex rewards precise instructions and tight scope, Claude Code rewards loose greenfield prompting, and the pendulum between them flips with every model release. Pick the one whose defaults match how you work, then configure away the friction. Do not pick based on last week's benchmark; both teams ship monthly.

## Practical workflows that compound

- **Plan before full-auto.** Use `/plan` or a read-only first pass to get an approach, approve it, then switch the sandbox to `workspace-write` and let it execute. Cold-starting an agent in full-auto on a vague prompt is how you get over-engineering.
- **Esc-Esc to backtrack.** In the TUI, double-Escape forks the conversation from an earlier message — cheaper than re-explaining when the agent went down the wrong path.
- **`/review` before you commit.** Codex's built-in review runs with no side effects and follows your `AGENTS.md`. Set `review_model` to a stronger model than your daily driver if you want a tougher reviewer.
- **Lower reasoning for mechanical work.** Renames, formatting, mechanical refactors: `--profile fast` with `low` effort. Save `xhigh` for design.
- **Use the ChatGPT plan for cost.** Signing in with a ChatGPT subscription instead of metered API keys is a large part of why the cost-conscious switchers moved; for heavy daily use the math is very different from per-token billing.

## Anti-patterns: stop doing these

- **Setting `approval_policy = "never"` to stop prompts while leaving `sandbox_mode = "read-only"`.** Now it can't edit anything. Set the sandbox too.
- **Expecting `npm install` to work in `workspace-write`.** Network is off by default. Set `network_access = true` for that task or approve it.
- **Writing `mcpServers`.** It's `mcp_servers`. The camelCase version is ignored without error.
- **Running everything at `xhigh`.** You'll wait five minutes for a variable rename. Match effort to the task.
- **Skipping `AGENTS.md`.** Without scope discipline written down, GPT-5-class models over-build. The file is the cheapest fix.
- **Relying on implicit `OPENAI_API_KEY` in CI.** Since v0.36.0, `codex exec` wants `CODEX_API_KEY`. Update your pipelines.

## Troubleshooting and gotchas

- **Approval prompt for every command.** You're in `read-only` or `untrusted`. Move to `workspace-write` + `on-request`. This is [issue #14936](https://github.com/openai/codex/issues/14936) and friends: overwhelmingly a config issue, not a bug.
- **Commands fail silently in the sandbox.** A command needs network or a write outside the workspace. Check `network_access` and `writable_roots`.
- **`git commit` keeps prompting.** `.git/` is read-only under `workspace-write` by design, so commits escalate. Approve them, or commit yourself.
- **Tests fail only under Codex.** The sandbox blocks something the tests need (a socket, a temp path). Add the path to `writable_roots` or enable network for that run.
- **Config edits seem ignored in a project.** Project-local `.codex/config.toml` ignores `model_provider`, `profiles`, `notify`, and similar — set those in `~/.codex/config.toml`.
- **CI auth broke after an upgrade.** v0.36.0 stopped reading `OPENAI_API_KEY` implicitly in `codex exec`. Use `CODEX_API_KEY`.
- **Linux container can't sandbox.** Landlock/seccomp may be unavailable in some containers; run in a hardened container with `--dangerously-bypass-approvals-and-sandbox`, never on a real machine.
- **Inspect what's happening.** `codex debug seatbelt` (macOS) and `codex debug landlock` (Linux) show exactly what the sandbox is enforcing.

## The drop-in starter pack

A complete `~/.codex/config.toml` that combines everything above — a default fast profile, a deep-reasoning profile, a locked-down profile, sane sandbox defaults, and two MCP servers that earn their place:

```toml
# ~/.codex/config.toml
model = "gpt-5.5"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
model_reasoning_effort = "medium"
model_verbosity = "low"
profile = "fast"

[sandbox_workspace_write]
network_access = false

[profiles.fast]
model = "gpt-5.5"
model_reasoning_effort = "low"

[profiles.deep]
model = "gpt-5.1-codex-max"
model_reasoning_effort = "xhigh"
model_reasoning_summary = "detailed"

[profiles.zdr]
model = "gpt-5.5"
disable_response_storage = true
approval_policy = "untrusted"
sandbox_mode = "read-only"

[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp@latest"]

[mcp_servers.grep]
url = "https://mcp.grep.app"
required = false
```

Pair it with a tight `AGENTS.md`, start hard tasks in `--profile deep`, keep plumbing in `--profile fast`, and run CI through `codex exec --json`. The approval prompts that make people quit Codex in the first hour are not the tool being broken. They are the tool asking you to tell it what you trust. Answer once, in TOML, and it stops asking.

## Sources & credits

Configuration synthesized from the [official Codex CLI docs](https://developers.openai.com/codex/cli/), the [config reference](https://developers.openai.com/codex/config/) and [schema](https://developers.openai.com/codex/config-schema.json), and the [openai/codex](https://github.com/openai/codex) repository at release `rust-v0.137.0`. Timeline from OpenAI's [Codex announcements](https://openai.com/index/introducing-codex/) and the [Rust rewrite discussion](https://github.com/openai/codex/discussions/1174). Community sentiment from the linked Hacker News threads; approval-friction reports from the cited GitHub issues. Model names reflect the lineup as of June 2026; the picker's contents vary by plan and change often.

## Sources

- [OpenAI — Codex CLI docs](https://developers.openai.com/codex/cli/)
- [OpenAI — Codex config reference](https://developers.openai.com/codex/config/)
- [openai/codex (GitHub)](https://github.com/openai/codex)
- [Codex config schema (JSON)](https://developers.openai.com/codex/config-schema.json)
- [Codex CLI is Going Native — Rust rewrite announcement](https://github.com/openai/codex/discussions/1174)
- [OpenAI — Introducing Codex](https://openai.com/index/introducing-codex/)
- [OpenAI — Codex now generally available](https://openai.com/index/codex-now-generally-available/)
- [OpenAI — GPT-5.1-Codex-Max](https://openai.com/index/gpt-5-1-codex-max/)
- [AGENTS.md guide (Codex docs)](https://developers.openai.com/codex/agents-md/)
- [openai/codex-action (GitHub)](https://github.com/openai/codex-action)
- [HN — GPT-5-Codex discussion (Sep 2025)](https://news.ycombinator.com/item?id=45252301)
- [HN — switching to Codex CLI thread](https://news.ycombinator.com/item?id=45648422)

---

Canonical: https://www.thedeepfeed.ai/posts/2026-06-10-stop-fighting-codex-cli-approval-prompts/
Site: https://www.thedeepfeed.ai
Full corpus: https://www.thedeepfeed.ai/llms-full.txt