# Configure Codex with config.toml: model, permissions, and profiles

URL: https://developertoolkit.ai/en/codex/quick-start/configuration/
Description: Set up Codex config.toml deliberately: layer precedence, model and effort, permission profiles, secret filtering, profiles, and how to prove each setting applies.

Codex configuration lives in `config.toml` files that stack in a fixed order: built-in defaults, system config, your user file at `~/.codex/config.toml`, an optional `--profile` file, a trusted repository's `.codex/config.toml`, and finally command-line overrides. Codex ignores a mistyped key with only a startup warning.

This guide is for developers setting up Codex for themselves and tech leads writing the project config a whole team commits. The situation it prevents is familiar: you set `web_search = "live"`, searches still come from the cache, and the reason is a typo that Codex skipped without stopping. Or a colleague's run passes a test that fails for you because a repository config you never read overrode your sandbox.

## What a deliberate config.toml gives you

- A user `~/.codex/config.toml` whose every line you can explain, validated by your editor against Codex's own schema
- A committed `.codex/config.toml` that gives the whole team the same permissions and secret filtering
- Profiles for review, quick iteration, unattended runs, and local models, switched with one flag
- A four-command check (`codex doctor`, `/status`, `/debug-config`, `codex sandbox`) that proves what is in effect, instead of trusting the file
- Three copy-paste prompts that audit a configuration, explain why a setting did not apply, and draft the team config

Every key and command on this page was checked against codex-cli 0.157.1 on 2026-09-26, including a `codex exec --strict-config` run of each example file (the starter config, the project config, and the four profiles). The config keys in those files were checked again against the 0.162.1 config schema on 2026-10-12, and each is still listed; every behaviour stays stamped 0.157.1 unless its section says otherwise. The model, effort and speed statements that name GPT-6.1 Sol, codex-cli 0.159.1 or later, or 2026-10-12 come from the 0.162.1 model catalog and OpenAI's pages as read on 2026-10-12. Install Codex and sign in first: see [installing Codex](/en/codex/quick-start/installation/) and [Codex authentication](/en/codex/quick-start/authentication/).

## Where does Codex read configuration from?

Codex builds one effective configuration from several layers. A later layer overrides an earlier one, key by key:

| Order | Layer | Path | Notes |
| --- | --- | --- | --- |
| 1 | Built-in defaults | Inside Codex | What you get with no file at all |
| 2 | System | `/etc/codex/config.toml` (Unix), `%ProgramData%\OpenAI\Codex\config.toml` (Windows) | Machine-wide defaults |
| 3 | Managed config | macOS managed preferences, enterprise cloud config fragments | Set by admins; override system defaults |
| 4 | User | `$CODEX_HOME/config.toml` (`CODEX_HOME` defaults to `~/.codex`) | Your personal defaults |
| 5 | Profile | `$CODEX_HOME/<name>.config.toml` | Only when you pass `--profile <name>` |
| 6 | Project | `.codex/config.toml` from the repository root down to the working directory | Ignored while the project is untrusted |
| 7 | Session | `-c key=value`, `-m`, `-a`, `-s`, `--enable`, `--search`, the model picker | This run only |

The order comes from the configuration loader in the Codex source (`codex-rs/config/src/loader`, checked 2026-09-26). Two consequences surprise people:

- **A project config beats your profile.** If the repository sets `model_reasoning_effort = "medium"`, `codex --profile review` with `high` still runs at `medium`. Override it for one run with `-c model_reasoning_effort="high"`.
- **Administrators can also constrain values.** Managed `requirements.toml` files (`/etc/codex/requirements.toml`, or the enterprise cloud bundle) do not set values; they limit which values any layer may choose. When a value you set is refused, the constraint is there, not in your file. Policy rollout is covered in [Codex enterprise governance](/en/codex/team/enterprise-governance/).

The CLI, the desktop app, and the IDE extension read the same `CODEX_HOME`. Codex cloud tasks do not read local files; you configure [Codex cloud environments](/en/codex/automate/cloud-environments/) separately.

**Untrusted projects cannot change your settings**

The first time you open a repository, Codex asks whether to trust it. Codex loads an untrusted project's `.codex/config.toml` but disables it, and since codex-cli 0.150.0 an untrusted project does not supply `AGENTS.md` instructions either. That is deliberate: a cloned repository cannot widen your sandbox. Trust is recorded in your user config as `[projects."/abs/path"]` with `trust_level = "trusted"`.

## Write a starter config.toml

The file below is a complete user config. Each section after the steps explains one decision in it.

1. Create `~/.codex/config.toml` (or open the existing one) and paste:

   ```toml
   #:schema https://raw.githubusercontent.com/openai/codex/rust-v0.157.1/codex-rs/core/config.schema.json

   # Model: leave `model` unset to follow Codex's bundled default (GPT-6.1 Sol).
   # Tune effort first; switch model only when your own results say so.
   model_reasoning_effort = "medium"

   # Permissions: the built-in workspace profile writes only the workspace
   # and grants no network. Do not also set sandbox_mode.
   default_permissions = ":workspace"
   approval_policy = "on-request"

   # Web search: "cached" is the default; "live" fetches in real time.
   web_search = "cached"

   # Clickable file citations in your editor.
   file_opener = "vscode"

   # Keep variables named like keys, secrets and tokens out of commands.
   [shell_environment_policy]
   ignore_default_excludes = false

   [tui]
   notifications = ["agent-turn-complete", "approval-requested"]
   ```

2. Install an editor extension that reads the `#:schema` directive (Even Better TOML in VS Code or Cursor). Unknown keys now show a red underline as you type. Pin the schema URL to the tag of the Codex version you run, because keys appear and disappear between releases.

3. Validate the file with the installed binary. `--strict-config` turns an unknown key into an error instead of a warning:

   ```bash
   codex exec --strict-config --ephemeral "Reply with OK."
   ```

   Run it from inside a trusted repository (or add `--skip-git-repo-check`); it makes one short model call.

   A typo stops the run with the file, line, and key: `config.toml:14:1: unknown configuration field` followed by the key name.

4. Run `codex doctor` and read the **Configuration** block (model, config files, startup warnings with each ignored key) and the **sandbox** row below it (approval policy, filesystem and network restriction).

### Choose the model and reasoning effort

GPT-6.1 Sol is Codex's bundled default model since codex-cli 0.159.1 (2026-09-29), and its default effort in Codex is `low`; Codex labels it "Latest workhorse model for coding and everyday work". GPT-6 Astra ("Frontier intelligence for the most demanding work"), GPT-6 Sol ("Previous generation workhorse model") and GPT-6 Luna ("Fast and affordable model for easier tasks") sit below it in the picker. The older GPT-5.6 models remain selectable. OpenAI's models page (checked 2026-10-12) recommends GPT-6.1 Sol for complex coding and agentic workflows and GPT-6 Luna for focused, repeatable tasks, and says to choose Astra "when a task needs the strongest capability across steps and tools", so treat Astra as the model you pick by hand for the hardest work. Prices, context windows, and when to pick each model are on the [models hub](/en/ecosystem/models/); this page does not repeat them.

GPT-5.5, which the 0.162.1 catalog labels "Legacy coding model.", retires from ChatGPT, ChatGPT Work and Codex on 2026-10-14, on all plans (OpenAI models page, checked 2026-10-12); the OpenAI API is not affected. The 0.162.1 catalog still carries no retirement date for it, so the server enforces the date: move any `model = "gpt-5.5"` pin before then.

The rule the whole site follows: **start on the default model, tune effort before switching model, and switch only when your own results say so.** In practice:

- Leave `model` unset in your user file, so a new bundled default reaches you on upgrade. Pin `model = "gpt-6-luna"` only in a profile that exists for cost reasons.
- Set `model_reasoning_effort` to `medium` or `high` for daily work. GPT-6.1 Sol and Astra accept `low` through `max` plus Codex's `ultra` ("Maximum reasoning with automatic task delegation"); Luna has no `ultra`. Change it live with `/model`.
- Speed is a separate setting from model and effort. The Fast and Ultrafast tiers trade allowance for speed, and Ultrafast needs a Pro $500 plan or an eligible Enterprise or Edu plan in Codex; how `service_tier`, `fast_mode` and `/fast` fit together is on [Codex credits, usage limits and cost optimization](/en/codex/operate/cost-management/).
- Codex opens a 272K-token window by default for the GPT-6 models. Raise it with `model_context_window` up to the catalog ceiling of 872K when a task needs it, and read [Codex context patterns](/en/codex/build/context-patterns/) first, because a bigger window costs more per turn.

### Choose permissions: permission profiles or the legacy sandbox

Two settings decide what Codex may do, and they are separate axes. The **permissions** decide what a command can technically touch. The **approval policy** decides whether Codex may ask you to cross that boundary.

For permissions, OpenAI now prefers permission profiles (beta, codex-cli 0.138.0 and later): `default_permissions = ":workspace"` writes the workspace and grants no network, and `":read-only"` writes nothing. The legacy `sandbox_mode` key (`read-only`, `workspace-write`, `danger-full-access`) still works. Pick one system per file: OpenAI states that "the profile and legacy sandbox systems do not compose", so never set `default_permissions` and `sandbox_mode` together.

| `approval_policy` | Behaviour | Use it for |
| --- | --- | --- |
| `on-request` (default) | Works inside the permissions; asks before crossing them | Interactive work |
| `untrusted` | Removed: codex-cli 0.157.1 refuses to start with it ("no longer supported; remove this setting", checked 2026-09-26) | Nothing; use `on-request` or `granular` |
| `granular` | A table of per-category switches (shell commands, rules, skill scripts, MCP prompts); a category set to `false` is rejected instead of asked | Teams that need finer control |
| `never` | Never asks; an action outside the permissions fails and the model gets the error | Unattended runs in a profile, never your default |

On the command line, `-a` accepts only `on-request` and `never` in 0.157.1, and it applies to the interactive `codex`. `codex exec` rejects `-a` and needs none: it runs with approval `never` (`on-request` under `--approve-for-me`), and a `codex -a … exec` prefix does not change that. Setting `approvals_reviewer = "auto_review"` lets a reviewer model decide escalations instead of you; `--approve-for-me` does the same for one run, but it also switches to the legacy workspace-write sandbox, so don't combine it with `default_permissions`. The cross-tool comparison of these modes, and the risk class each fits, is in [permissions and sandboxing](/en/workflows/harness/permissions-and-sandboxing/).

### Choose the web search mode

`web_search` accepts `cached` (the default), `live`, `indexed`, and `disabled`. `cached` answers from pre-fetched results and is the safer choice for most work. Set `live` in a profile, or pass `codex --search` for one session, when you need a release that shipped this week. Set `disabled` in unattended profiles, where a fetched page is untrusted input that nobody reads.

### Keep secrets out of the commands Codex runs

By default, every command Codex spawns inherits your whole shell environment, cloud credentials included. `[shell_environment_policy]` controls that:

```toml
[shell_environment_policy]
inherit = "all"                  # "all" (default), "core" (HOME, PATH, SHELL, USER…), or "none"
ignore_default_excludes = false  # default true: set false to drop *KEY*, *SECRET*, *TOKEN* names
exclude = ["AWS_*", "AZURE_*"]   # extra patterns to drop
set = { NODE_ENV = "test" }      # injected into every command
```

The effect is observable. With `ignore_default_excludes = false` in 0.157.1, this canary printed `MY_VAR=1` and nothing else; with the default, it also printed `FAKE_API_KEY=abc`:

```bash
FAKE_API_KEY=abc MY_VAR=1 codex sandbox -- sh -c 'env | grep -E "FAKE_API_KEY|MY_VAR"'
```

`exclude` and `include_only` are the legacy array form; the canonical form is a table, `[shell_environment_policy.filters]` with `"AWS_*" = "exclude"`. Do not mix the two in one file.

### Prepare the shell before you launch Codex

Because Codex inherits the shell, launch it from a ready one. Activate the virtual environment, start the services the tests need, and export non-secret variables first. Otherwise Codex spends turns discovering that `pytest` is missing or Postgres is down:

```bash
source .venv/bin/activate
docker compose up -d postgres redis
export DATABASE_URL="postgresql://localhost:5432/myapp_test"
codex
```

A variable the tests need that matches `*KEY*`, `*SECRET*`, or `*TOKEN*` is now filtered out. Pass a test-only value with `set`, never the production one.

## Commit a project config for the whole team

A repository's `.codex/config.toml` is where a tech lead makes behaviour consistent for everyone who trusts the project. Keep it to settings that belong to the codebase, and leave model choice to each person:

```toml
# .codex/config.toml: committed; reviewed like CI config
default_permissions = ":workspace"
approval_policy = "on-request"
web_search = "cached"

[shell_environment_policy]
ignore_default_excludes = false
set = { NODE_ENV = "test", TZ = "UTC" }
```

A project file cannot choose where credentials go or which local commands run: `model_provider`, `notify`, `profile` and base-URL keys are ignored there and must live in user or system config (checked in `codex-rs/config/src/loader`, 0.157.1).

Treat a change to this file as a harness change: it alters what every developer's agent may do. Require review from the harness owner, and attach the `codex sandbox` canary output from the next section to the pull request, as described in [the evidence bundle](/en/workflows/ship/evidence-bundle/). Project instructions belong in `AGENTS.md`, not here; see [AGENTS.md for Codex](/en/codex/quick-start/agents-md/). MCP servers can go in either file as `[mcp_servers.<name>]` tables; see [Codex MCP setup](/en/codex/quick-start/mcp-setup/).

## Switch setups with profiles

A profile is a separate file, `$CODEX_HOME/<name>.config.toml`, layered on your user config when you pass `--profile <name>` (or `-p`). The older `[profiles.<name>]` tables inside `config.toml` are still parsed but superseded; use files.

**review**

```toml
# ~/.codex/review.config.toml
model_reasoning_effort = "high"
review_model = "gpt-6-astra"   # model used by /review
approval_policy = "on-request"
```

Run with `codex --profile review`, then `/review`. It inherits `default_permissions` from your user file.

**quick**

```toml
# ~/.codex/quick.config.toml
model = "gpt-6-luna"
model_reasoning_effort = "low"
```

Run with `codex -p quick "Rename getUserData to fetchUserProfile across src/"` for mechanical edits whose correctness the test suite proves.

**unattended**

```toml
# ~/.codex/unattended.config.toml
approval_policy = "never"
default_permissions = ":workspace"
web_search = "disabled"
hide_agent_reasoning = true
```

Run with `codex exec --profile unattended --ephemeral "…"` for scripted jobs on your own machine. `never` removes prompts but not the permission boundary. For CI runners, use the patterns in [non-interactive Codex](/en/codex/automate/non-interactive/), which also cover secrets and untrusted pull requests.

**local**

```toml
# ~/.codex/local.config.toml
oss_provider = "ollama"   # or "lmstudio"
```

Run with `codex --profile local --oss`. Choosing a local model is covered in [gateways and local models](/en/ecosystem/agent-tools/gateways-local-models/).

A profile applies only when you name it on the command line. To see which layers a session loaded, run `/debug-config`.

## Override one setting for one run

You do not need to edit a file to change one run:

```bash
codex -m gpt-6-sol                               # model for this session
codex -c model_reasoning_effort="high"           # any key, as TOML
codex -c shell_environment_policy.inherit=core   # nested keys use dots
codex --enable memories                          # same as -c features.memories=true
codex --search                                   # live web search for this session
codex exec --ephemeral "Run the linter and report."  # exec: approval is never
```

## Which feature flags matter

`codex features list` prints every flag with its stage and effective state; `codex features enable <name>` and `disable <name>` write the change to `config.toml` under `[features]`. Flags are read at startup, so restart Codex after a change. In 0.157.1:

| Flag | Stage | Default | What it does |
| --- | --- | --- | --- |
| `shell_snapshot` | stable | on | Snapshots the shell environment so repeated commands start faster |
| `unified_exec` | stable | on | PTY-backed command execution |
| `goals` | stable | on | Persisted goals and automatic continuation (`/goal`) |
| `multi_agent` | stable | on | Subagents |
| `memories` | stable | **off** | Memory across sessions; turn it on deliberately |

Some flags still appear in the list with stage `removed`, including `personality`, `steer`, `tool_search`, and `js_repl`. Toggling them changes nothing. The same goes for the `personality` config key: "`friendly` and `pragmatic` no longer select a style" (checked in `config_toml.rs`, 2026-09-26).

## Prove the configuration does what you think

A configuration file is a claim. These checks turn it into evidence, and none of them needs you to read the agent's output line by line:

1. **Codex parses every key.** Run `codex doctor --all`. Under **Configuration**, "startup warnings" must be 0; each ignored key is listed by name and layer.

2. **The right layer wins.** In the TUI, `/debug-config` shows the config layers and requirement sources, and `/status` shows the session's model, approvals, and sandbox. A non-interactive run prints the same header: `model:`, `approval:`, `sandbox:`.

3. **The boundary holds.** Run a canary through the same sandbox the agent gets. With `default_permissions = ":workspace"` in 0.157.1, this printed `ok`, then `Read-only file system` for `/etc/probe`:

   ```bash
   codex sandbox -- sh -c 'echo ok > probe.txt && cat probe.txt; echo x > /etc/probe'
   ```

4. **Secrets stay out.** Run the `env` canary from the secrets section. No `*KEY*`, `*SECRET*`, or `*TOKEN*` name may appear.

The developer runs these after any change to their own file. For a committed `.codex/config.toml`, the tech lead or harness owner signs off on the canary output in the pull request, not on the settings diff. Re-run all four after every Codex upgrade, because keys and defaults move between releases.

**Copy-paste prompt: audit your Codex configuration**

```text
Audit my Codex configuration without changing any file. Run `codex doctor --all` and `codex features list`, then read ~/.codex/config.toml and .codex/config.toml in this repository if it exists. Report a table with each key that is set, the layer it comes from, and whether doctor lists it as ignored. Flag explicitly: default_permissions and sandbox_mode set in the same file; approval_policy = "never" in my user config rather than a profile; shell_environment_policy leaving ignore_default_excludes at its default of true; any removed feature flag still set under [features]. Never print the value of an environment variable.
```

**Copy-paste prompt: find out why a setting does not apply**

```text
My setting web_search = "live" in ~/.codex/config.toml does not seem to take effect in this repository. Find out why without editing anything. Check `codex doctor --all` for ignored keys, check whether .codex/config.toml in this repository or any parent directory sets web_search, check whether I started this session with --profile or -c, and check whether this project is trusted. Tell me which layer wins and why, quoting the exact lines you relied on.
```

**Copy-paste prompt: draft the team's project config**

```text
Draft a .codex/config.toml for this repository that the whole team can commit. Read AGENTS.md, the package manifests, and the CI config first. Include only project settings: default_permissions = ":workspace", approval_policy = "on-request", web_search = "cached", and a [shell_environment_policy] with ignore_default_excludes = false plus a `set` table for the non-secret variables the test suite needs. Do not set model or model_reasoning_effort. Put a one-line comment above each key saying why. Do not write the file; show it to me with the `codex sandbox` canary command that proves it.
```

## When Codex configuration breaks

**A setting has no effect, and nothing errors.** Codex skips unknown keys with a startup warning, so `web_serach = "live"` or the deprecated `personality` key does nothing. Run `codex doctor --all` and read the ignored keys, or run once with `--strict-config`, then fix the spelling against the schema.

**The project config is ignored.** The project is untrusted. Reopen Codex in the repository and accept the trust prompt, or check the `[projects."<path>"]` entry in your user config. Trust the project only after you have read its `.codex/` directory.

**Your profile setting loses.** A trusted project's `.codex/config.toml` sits above profiles. Use `-c key=value` for the run, or agree a different value in the project file.

**A command fails with "invalid value" for `-a`.** Only `on-request` and `never` are accepted by `-a` in 0.157.1; `on-failure` and `untrusted` are rejected there. For finer control than `on-request`, set `granular` (a table) in `config.toml`, which `-a` cannot express; `untrusted` is refused in `config.toml` too. A `-a` after `exec` fails as an unexpected argument; move it before the subcommand.

**Codex refuses a sandbox or approval value you set.** A managed `requirements.toml` constrains it. Run `/debug-config` to see the requirement source, then take the question to whoever owns the policy.

**Tests fail inside Codex but pass in your terminal.** The environment policy removed a variable the tests need. Check with the `env` canary, then add a test-only value under `set`. Never widen `inherit` or flip `ignore_default_excludes` back to `true` to fix one variable.

**The run cannot reach the network.** `:workspace` grants no network. Install dependencies before starting Codex, or define a named `[permissions]` profile with per-domain network access; the [permissions and sandboxing guide](/en/workflows/harness/permissions-and-sandboxing/) shows how.

**A model name is rejected.** The model is not in your version's catalog, or your plan or workspace does not include it. Pick from `/model`, and update Codex with `codex update`. GPT-6 Sol and Luna need codex-cli 0.155.0 or later. GPT-5.5 stops being available in Codex on 2026-10-14 (OpenAI models page, checked 2026-10-12).

**A custom provider stops connecting.** Current Codex releases do not support `wire_api = "chat"` or a Chat Completions-only endpoint (OpenAI models page, checked 2026-10-12). Point `model_provider` at an endpoint that supports the Responses API; the provider block is shown in [advanced Codex setups](/en/codex/automate/advanced-techniques/).

**Recovery of last resort.** Move `~/.codex/config.toml` aside, start Codex, and confirm it runs on defaults. Then add your settings back one block at a time, running `codex doctor` after each block.

## Where to go next with Codex configuration

- [AGENTS.md for Codex](/en/codex/quick-start/agents-md/) — Give Codex the project conventions, commands, and verification steps that config.toml cannot express.
- [Your first Codex task](/en/codex/quick-start/first-task/) — Put the new configuration to work on a change you verify with tests and a review pass.
- [Permissions, sandboxes and approval modes](/en/workflows/harness/permissions-and-sandboxing/) — The cross-tool matrix of approval modes, sandboxes, and network egress, with a posture for each run type.
- [Codex CLI commands](/en/codex/build/cli-commands/) — Shell completions, exec flags, and the commands you will use every day with this configuration.
