> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open4rena.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration files

> Where o4 keeps its settings, and which file wins.

o4 reads its settings from three kinds of file, and each kind holds different settings:

| File | Format | What goes in it | Who writes it |
| - | - | - | - |
| `config.toml` | TOML | Policy and behavior: `[[permissions.rules]]`, `[sandbox]`, `[[hooks]]`, `[keybindings]`, `[router]`, `[watch]`, `[scout]`, `[daemon]`, `[resume]`, `[codemode]`, and the top-level `model` and `auto_approve_plans`. | You, by hand. Some actions in o4 also write to it, such as saving a permission pattern, changing the sandbox tier, always allowing a domain, `/router setup --yes` and `/scout`. |
| `settings.json` | JSON | Preferences: the default model, provider and reasoning level, API keys, the permission default, theme and other appearance options, memory, suggestions, notifications, telemetry, compaction and background-task limits, language servers and formatters. | `/config` and the setup wizard. You can also edit it. |
| `display.json` | JSON | Four display switches: timestamps, the thinking display, animations and screen reader output. | `/config`. |

The default model is the one setting both kinds can hold: `model` in `settings.json` wins over `model` in `config.toml`, and `-m` overrides both. `config.toml` can exist in four places and `settings.json` in two, as described below. `display.json` exists only as `~/.o4/display.json`. Every file is optional. o4 runs with its defaults when none exist.

## Config files and precedence

o4 reads `config.toml` from these places. When two files set the same single value, such as `default_tier` or `[watch]`, the one higher in the list wins:

| Precedence | File | Scope |
| - | - | - |
| 1 (highest) | `~/.o4/managed/config.toml` | Managed policy, set by an administrator. |
| 2 | `.o4/config.local.toml` | This project, on this machine. Keep it out of version control. |
| 3 | `.o4/config.toml` | This project. Can be committed and shared. |
| 4 (lowest) | `~/.o4/config.toml` | You, in every project. |

Command-line flags apply on top of the merged files for that run. For example, `-m` picks the model whatever the files say, and `--sandbox` fixes the sandbox for the run and ignores `default_tier` (see [Sandbox](/safety/sandbox)).

The project files are read from the directory you start o4 in (or the one given with `-C`), and only after you have [trusted](/safety/workspace-trust) that workspace. Until then, o4 doesn't open them. The same goes for the project's `.o4/settings.json`, `.o4/.mcp.json`, hooks in `.o4.md`, and the project's plugins, skills and sub-agents. Your own files in `~/.o4` and the managed file always load, and project instructions such as `AGENTS.md` are read either way.

Some values combine across files instead of one file winning:

* `[[permissions.rules]]` and `[[hooks]]` entries from all files add up, together with hooks from the project's `.o4.md`.
* The `[sandbox]` lists `allowedDomains`, `allowedPaths` and `escape_hatch_binaries` add up. `default_tier` and `[sandbox.proxy]` come from the highest file that sets them.
* `[keybindings]` combines per action, with the higher file winning for an action both files set.
* `[router]` combines per key, and `[router.capacity]` per provider.
* `auto_approve_plans` is on if any file turns it on.

Other sections, such as `[watch]` and `[scout]`, come whole from the highest file that has them.

A few sections are read only from your own files, so a repository can't set them: `[daemon]` and `[codemode]` come from `~/.o4/config.toml` and `~/.o4/managed/config.toml`, and `[resume]` only from `~/.o4/config.toml`. o4 ignores these sections in project files and logs a warning.

Here's a small `~/.o4/config.toml`:

```toml theme={null}
model = "anthropic:claude-opus-5"

[[permissions.rules]]
pattern = "Bash(cargo test *)"
action = "allow"

[sandbox]
default_tier = "guarded"
allowedDomains = ["docs.rs"]

[keybindings]
cycle_reasoning = "f2"
```

The [configuration reference](/reference/configuration) lists every key.

### Managed policy

`~/.o4/managed/config.toml` is for an administrator, for example to add `deny` rules or hooks that users can't override. o4 never writes to it, and commands in the sandbox can't read or change it. Because deny rules from any file win over allow rules, a managed `deny` rule can't be undone by a user or project `allow` rule.

### When a file is broken

If a config file exists but can't be read or parsed, o4 stops with an error that names the file instead of starting without its rules. Files larger than 1 MiB are rejected. o4 also refuses symlinked config files, and project config files that resolve outside the project.

## settings.json

`~/.o4/settings.json` holds your preferences. `/config` and the first-run setup wizard write it; you can also edit it by hand. It includes:

* the default model (`model`), reasoning level (`reasoning`) and default provider (`default_provider`)
* API keys you entered in o4 (`api_keys`)
* the permission default (`permission_default`)
* appearance: `theme`, `nerd_fonts`, `scrollbar`, `reduce_motion` and similar
* memory, suggestions, notifications and telemetry switches
* compaction thresholds and background-task limits
* language servers (`lsp_servers`) and formatters (`formatters`)

```json theme={null}
{
  "model": "anthropic:claude-opus-5",
  "permission_default": "accept-edits",
  "theme": "dark",
  "auto_compact_threshold": 75,
  "notifications": ["approval-requested"]
}
```

o4 writes `settings.json` with `0600` permissions because it can contain API keys. Commands in the [sandbox](/safety/sandbox) can't read it.

A project can have its own `.o4/settings.json`. In a [trusted workspace](/safety/workspace-trust), each key set there overrides your own, with these exceptions:

* `api_keys`, `lsp_servers` and `formatters` combine per entry. An entry for the same provider, language server or file extension comes from the project file.
* `plugin_grants` always come from your own file, so a repository can't grant capabilities to plugins.

In an untrusted workspace o4 ignores the project's `settings.json` entirely. `/config` shows `· project` next to a value the project file overrides. `/config` itself always saves to `~/.o4/settings.json`.

If `settings.json` isn't valid JSON, or is larger than 1 MiB, o4 ignores the whole file and uses its defaults. See the [configuration reference](/reference/configuration#settings-json) for every key.

## The /config screen

Run `/config` to open the settings screen. To open a tab directly, pass its name, for example `/config appearance`. The tab names are `general`, `model`, `reasoning`, `providers`, `appearance`, `keys`, `mcp`, `plugins`, `agents`, `skills` and `tools`. `/config providers add` opens the form for adding a custom provider.

### Keys

| Key | Action |
| - | - |
| `Tab` or `Right` | Next tab. |
| `Shift+Tab` or `Left` | Previous tab. |
| `Down` or `j`, `Up` or `k` | Move between rows. |
| `Enter` | Act on the selected row. The footer names the action: **Toggle**, **Edit**, **Details** or **Open**. |
| `a` | On the Providers tab, open the form for adding a custom provider. |
| `Esc` or `q` | Close `/config`. |

Rows work in one of three ways:

* **Change in place.** `Enter` toggles an on/off setting or moves to the next value, and o4 saves the change to `~/.o4/settings.json` (or `~/.o4/display.json`) right away. **API key** is the only row you type into: `Enter` opens a text field, `Enter` again saves it, and `Esc` cancels.
* **Open another screen.** `Enter` opens a picker, browser or list, or runs a command such as `/router status`. Most of these close `/config` first.
* **Show details.** `Enter` opens a read-only details view. Press `Backspace` to go back to the list. The sample rows under **Preview** on the Appearance tab work this way too; see [Themes](/configuration/appearance#themes) for what they show.

A value that comes from the project's `.o4/settings.json` is marked `· project`.

You can open `/config` while the model is working. Changes are saved right away. Appearance and display changes, notifications and the permission default also take effect at once. Other changes, such as the reasoning level, the default provider or auto memory, take effect when the turn finishes, and o4 shows `Settings saved; model and reasoning changes apply when the current turn finishes.` A model you pick from the **Model** row is saved as your default right away, and any switch to it waits until the turn finishes. **Import Codex auth** and **Import Claude Code auth** are refused until the turn finishes.

### Tabs and rows

| Tab | Row | What `Enter` does |
| - | - | - |
| General | **Auto memory** | Turns automatic [memory](/guides/memory) on or off (`memory_enabled`). |
| General | **Suggestions** | Turns suggestions on or off (`suggestions_enabled`, off by default). See below. |
| General | **Permission default** | Moves to the next permission mode for new sessions and switches the current session to it. See [Permissions](/safety/permissions#the-default-mode). |
| General | **Permission rules** | Opens the project's rule list. See [Permissions](/safety/permissions#manage-rules-in-the-tui). |
| General | **Sandbox tier** | Moves to the next sandbox tier, like `Alt+S`. See [Sandbox](/safety/sandbox#change-the-tier). |
| General | **Sandbox policy** | Shows the current tier, the paths commands can write to, and how your platform enforces the sandbox. Read-only. |
| General | **Notifications** | Turns terminal notifications on or off. See below. |
| General | **Notification condition** | Switches between `unfocused` and `always`. See below. |
| Model | **Model** | Opens **Select Default Model**. The model you pick is saved as `model` in `~/.o4/settings.json`, so new sessions start with it, and the current session switches to it, after the running turn if there is one. A `model` in a trusted project's `.o4/settings.json` still wins in that project. See [Choosing a model](/models/overview#the-default-model). |
| Model | **Refresh catalog** | Closes `/config` and downloads the model catalog again. |
| Reasoning | **Reasoning** | Moves to the next reasoning level. See [Reasoning and prompt profiles](/models/reasoning). |
| Reasoning | **Thinking display** | Shows or hides the model's thinking (saved in `display.json`). |
| Providers | **Router setup** or **Router disable** | Shows the `/router setup` preview, or runs `/router disable` while the router is on. See [Model router and fallback](/models/router). |
| Providers | **Router status** | Runs `/router status`. |
| Providers | **Provider** | Moves to the next provider as your default and picks whose key the **API key** row edits. It doesn't change the current session's model; the **Model** row sets the default model. See [Providers](/models/providers#in-settings). |
| Providers | **API key** | Lets you type the API key for the selected provider. |
| Providers | **Add custom provider** | Opens the form for adding an [OpenAI-compatible endpoint](/models/openai-compatible). |
| Providers | **Import Codex auth**, **Import Claude Code auth** | Import a login from those tools. See [Subscriptions](/models/subscriptions). |
| Appearance | **Timestamps**, **Theme**, the preview rows, **Nerd fonts**, **Scrollbar**, **Syntax highlight**, **Action chips**, **File watcher**, **Animations**, **Reduce motion**, **Screen reader** | See [Themes and display](/configuration/appearance). |
| Keys | **Vim mode** | Turns Vim editing in the prompt on or off. |
| Keys | **Current keybindings** | Opens the list of active key bindings. |
| MCP | **Open MCP browser** | Opens the `/mcp` browser. See [MCP servers](/extend/mcp). |
| Plugins | **Open plugin browser** | Opens the `/plugins` browser. See [Plugins and marketplaces](/extend/plugins). |
| Agents | **Open agent browser** | Opens the agent definitions browser, the same one `/sub-agents` opens, where you can view, create, edit and delete sub-agent definitions. See [Subagents](/guides/subagents). |
| Skills | **Open skill browser**, **Install skill packs** | Open the `/skills` browser, or the plugin browser. See [Skills](/extend/skills). |
| Tools | **LSP servers**, **Formatters** | Show the configured commands. Read-only. See [Language servers and formatters](/extend/lsp-and-formatters). |

### Suggestions and notifications

**Suggestions** is off by default. When it's on, o4 shows suggested prompts above the input: when a session starts, based on uncommitted changes in git and on failures from the last `test_run`, and after each turn, based on the reply. Up to two show at a time. Press `1` or `2` to pick one, then `Enter` or `Tab` on an empty prompt to send it. Typing or `Esc` dismisses them. After a turn, o4 can also show a dimmed hint ending in `[Tab]` in the empty prompt: `Enter` sends it, `Tab` puts it in the prompt box for editing. See [Writing prompts](/guides/prompting).

**Notifications** is on by default. o4 sends a terminal notification when a turn finishes and when a tool call needs your approval. It uses the OSC 9 escape sequence in Ghostty, iTerm2, kitty, WezTerm and Warp, and the terminal bell in other terminals. The row switches all notifications on or off. To choose events, set `notifications` in `settings.json` to a list of `agent-turn-complete` and `approval-requested`.

**Notification condition** decides when notifications are sent: `unfocused` (the default) sends them only while the terminal window isn't focused, and `always` sends them every time.

## Display preferences

Timestamps, the thinking display, animations and screen reader output are saved in `~/.o4/display.json`, separate from `settings.json`. Change them in `/config` (the Appearance and Reasoning tabs); see [Themes and display](/configuration/appearance). There is no project `display.json`, so these four apply in every project. If the file is missing or isn't valid JSON, o4 uses the defaults.

## The \~/.o4 directory

o4 keeps everything it stores for you under `~/.o4`. The most useful entries:

| Path | Contents |
| - | - |
| `config.toml` | Your config. |
| `settings.json` | Your preferences and stored API keys. |
| `display.json` | Display preferences. |
| `managed/config.toml` | Managed policy. |
| `trusted_workspaces.json` | Workspaces you trusted with `o4 trust`. |
| `instructions.md` | Your own instructions for every project; see [Project instructions](/configuration/project-instructions). |
| `.mcp.json` | Your MCP servers; see [MCP servers](/extend/mcp). |
| `skills/`, `agents/`, `plugins/` | Your skills, sub-agent definitions and installed plugins. |
| `marketplaces/` | Plugin marketplaces you added. |
| `models.toml`, `providers.toml` | Your model overrides and custom providers; see [Choosing a model](/models/overview) and [OpenAI-compatible endpoints](/models/openai-compatible). |
| `catalog/` | The cached model catalog. |
| `theme.toml` | Custom theme colors. |
| `sessions/`, `sessions.db` | Saved sessions; see [Sessions](/guides/sessions). |
| `prompt_history.json` | Your prompt history. |
| `projects/` | Per-project data, including memory; see [Memory](/guides/memory). |
| `memory/` | Global memory. |
| `telemetry/` | The local telemetry event log; see [Telemetry and privacy](/help/telemetry-and-privacy). |
| `o4.log` | o4's log file. |

The location is always `~/.o4` in your home directory; there is no setting or environment variable to move it.

Inside a project, o4 uses a `.o4/` folder for project-level files: `config.toml`, `config.local.toml`, `settings.json`, `instructions.md`, `.mcp.json`, and `skills/`, `agents/` and `plugins/`. It also keeps per-project caches there, such as the code index in `.o4/index/`.
