> ## 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.

# Choosing a model

> Pick and switch models, and keep the model list up to date.

o4 works with models from many providers. You choose one when you start o4, and you can switch at any time during a session. This page covers how to name a model, how o4 picks one when you don't, and where the model list comes from.

A model only answers if o4 has credentials for its provider. See [Providers and API keys](/models/providers), or use a [Claude or ChatGPT subscription](/models/subscriptions).

## Pick a model at startup

Pass `-m` (or `--model`) with a model reference:

```bash theme={null}
o4 -m anthropic:claude-sonnet-4-6
```

The model applies to that run only. If o4 can't find the model, it stops before the session starts:

```text theme={null}
Error: Model 'nope-model' not found. Use `o4 --list-models` to see available models.
```

## Model references

A model reference names a model, with or without its provider:

| Form | Example | Notes |
| - | - | - |
| `provider:model` | `openai:gpt-5.5` | Uses exactly that provider. |
| `provider/model` | `openai/gpt-5.5` | Same as the colon form. |
| `model` | `gpt-5.5` | o4 chooses the provider. |
| Display name | `"Claude Opus 5"` | Matches the model's display name, ignoring case. |

Some model IDs exist under more than one provider. Every Anthropic model also appears under `claude-code`, and several GPT models appear under both `openai` and `openai-codex`. For a bare model ID, o4 prefers providers you have credentials for, then takes the first match in the catalog. Add the provider prefix when you want to control which account pays for the request.

<Tip>
  Use the colon form for model IDs that contain a colon, such as Ollama tags: `ollama:gpt-oss:120b`. The slash form doesn't work for them, because o4 splits the reference at the first `:` before it looks for `/`.
</Tip>

## Switch models during a session

* `/model` opens the **Select Model** list. Type to filter by provider or model name, use the arrow keys to move, and press `Enter` to switch. The current model is marked `← active`. While the model is working, `/model` waits until the turn finishes, then opens the list.
* `/model <reference>` switches straight to a model, for example `/model openai:gpt-5.5`. While the model is working, it waits until the turn finishes.
* `Ctrl+M` opens the same list when the prompt is empty, even while the model is working. If you pick a model during a turn, the session switches to it at once, but the running turn keeps its old model unless the [model router](/models/router) is on. `Ctrl+P` opens **Select Provider**, which narrows the model list to the provider you pick. Many terminals send the same code for `Ctrl+M` and `Enter`; o4 tells them apart where the terminal supports it, but not inside tmux. If `Ctrl+M` doesn't open the list, use `/model`.
* `Alt+M` moves to the next model in o4's full model list and shows a notice such as `Model: gpt-5.5`. You can remap it with the `cycle_model` action (see [Keyboard shortcuts](/reference/keyboard-shortcuts)).

**Select Model** hides the models of `anthropic`, `openai`, `xai` and `deepseek` until that provider has an API key in o4's settings or the environment. It lists the other providers' models whether or not you have credentials, because o4 can't check them ahead of time: `claude-code`, `openai-codex` and `kimi-coding` can use a sign-in, `ollama` can run locally without a key, and custom providers can use any auth. A model without working credentials fails on its first request. `Alt+M` doesn't filter at all, so it can also land on a hidden model.

A switch keeps your conversation, rebuilds the system prompt for the new model, and applies to the current session only. It doesn't change the default model for new sessions, and the notice after `/model` or `Ctrl+M` says so: `Switched to <name> (<id>) for this session · /config model sets the default`.

The **Model** tab of `/config` (`/config model`) has two rows:

* **Model** shows your saved default model, or the current model if none is saved. `Enter` opens **Select Default Model**. The model you pick is saved as `model` in `~/.o4/settings.json`, and the other settings in that file stay as they are. The current session switches to it too; if a turn is running, the switch waits until the turn finishes. If a trusted project's `.o4/settings.json` sets a different `model`, that one still wins in the project, so the session stays on it, and the notice says so: `Saved <name> (<id>) as the default model, but this project's .o4/settings.json uses <model> here`.
* **Refresh catalog** downloads the latest model catalog. See [Keep the model catalog up to date](#keep-the-model-catalog-up-to-date).

## The default model

When you start o4 without `-m`, it uses the `model` setting if one is saved. o4 checks these places in order:

1. `.o4/settings.json` in the project, which o4 reads only in a [trusted workspace](/safety/workspace-trust).
2. `~/.o4/settings.json`.
3. `config.toml` (see [Configuration files](/configuration/overview)).

To change the default, pick a model from the **Model** row of `/config model`, which saves it to `~/.o4/settings.json`. The setup wizard saves its choice there too. The wizard opens on its own when o4 finds no API key or no usable default model, and `/onboard` opens it at any time. You can also set the default by hand. Both files take a model reference:

<CodeGroup>
  ```json ~/.o4/settings.json theme={null}
  {
    "model": "anthropic:claude-opus-5"
  }
  ```

  ```toml ~/.o4/config.toml theme={null}
  model = "anthropic:claude-opus-5"
  ```
</CodeGroup>

If the saved model no longer exists, for example because a catalog update removed it, o4 starts on a fallback model (chosen as described below) and opens the setup wizard so you can choose another. With `--no-onboarding`, it stops with `Configured model '...' is not selectable.` instead.

### When no default is saved

With no saved model, the interactive interface opens the setup wizard so you can choose one. In [print mode](/guides/print-mode), o4 goes ahead without asking. With `--no-onboarding`, it stops instead:

```text theme={null}
Error: No default model configured. Run without --no-onboarding to choose one, or pass `-m <model>`.
```

Until you choose, o4 uses a model picked from the credentials it finds. It takes the first rule that matches:

1. ChatGPT/Codex credentials, and no Anthropic key, OpenAI key or Claude Code token: `openai-codex:gpt-5.6-sol`.
2. A Claude Code token and no Anthropic API key: `claude-code:claude-fable-5`.
3. A default provider set with the **Provider** row under `/config` > **Providers**: that provider's default model. That is the model named in the other rules for the providers they mention, `glm-5.3` for `zai` and `zai-coding-plan`, and otherwise the provider's first model ID in alphabetical order.
4. ChatGPT/Codex credentials and no OpenAI API key: `openai-codex:gpt-5.6-sol`.
5. An Anthropic API key: `anthropic:claude-fable-5`.
6. An OpenAI API key: `openai:gpt-5.2`.
7. A Kimi key: `kimi-coding:kimi-for-coding`.
8. Otherwise: `anthropic:claude-fable-5`.

o4 reads ChatGPT/Codex credentials from `~/.codex/auth.json` automatically, so if you have signed in to the Codex CLI, rule 1 or 4 can apply even though you never configured Codex in o4. Save a default model to avoid surprises.

## List the available models

`--list-models` prints every registered model, grouped by provider, and exits. It doesn't need an API key:

```bash theme={null}
o4 --list-models
```

```text theme={null}
Provider: anthropic
  claude-fable-5 (context: 1000k, max_tokens: 128000, input: text,image, reasoning: yes)
  claude-fable-5-1 (context: 1000k, max_tokens: 128000, input: text,image, reasoning: yes)
  claude-haiku-4-5-20251001 (context: 200k, max_tokens: 64000, input: text,image, reasoning: yes)
  ...
Provider: openai-codex
  gpt-5.2 (context: 272k, max_tokens: provider default, input: text,image, reasoning: yes)
  gpt-5.5 (context: 272k, max_tokens: provider default, input: text,image, reasoning: yes)
  ...
```

Each line shows the model ID, the context window in thousands of tokens, the maximum output tokens, the accepted input types, and whether the model can reason. `provider default` means the catalog sets no output limit and the provider decides.

Unlike **Select Model**, this list includes models whose provider has no credentials yet. It also includes models you add in `~/.o4/providers.toml` or `~/.o4/models.toml`.

## Keep the model catalog up to date

The o4 binary has a built-in model catalog. o4 can also download catalog updates from Open4rena and cache them in `~/.o4/catalog/`. Downloaded entries replace built-in entries with the same provider and model ID, so new models and price changes can arrive without a new o4 release. The download covers the `anthropic`, `openai`, `amazon-bedrock`, `google`, `deepseek`, `xai` and `ollama` providers.

The catalog refreshes:

* In the background when the interactive interface starts, if the last refresh was more than 7 days ago.
* When you choose **Refresh catalog** on the **Model** tab of `/config`, or run `/models-update`, which does the same. The row shows when the catalog was last updated.

After a manual refresh, o4 reloads the model list without a restart and shows a notice such as `Model catalog updated: 7 providers refreshed, 0 failed.`. If the download fails, you see `Model catalog update failed: ... Using cached data.` and o4 keeps the models it already has.

## Add or change model entries

`~/.o4/models.toml` adds models to a built-in provider, or replaces a built-in entry with the same provider and ID. o4 loads it after the built-in and downloaded catalogs, so its entries win. For example, this adds a model to the built-in `ollama` provider that runs on a local Ollama server:

```toml ~/.o4/models.toml theme={null}
[[models]]
id = "qwen3-coder:30b"
name = "Qwen3 Coder 30B (local)"
api = "ollama-native"
provider = "ollama"
base_url = "http://localhost:11434/v1"
input = ["text"]
context_window = 32768
max_tokens = 8192

[models.cost]
input = 0.0
output = 0.0
```

Each entry needs `id`, `name`, `api`, `provider`, `base_url` and a `[models.cost]` table. For `provider`, use the name of a built-in provider.

Set `api` to the value the provider's built-in models use. `--list-models` doesn't show it:

| `provider` | `api` |
| - | - |
| `anthropic`, `claude-code`, `kimi-coding` | `anthropic-messages` |
| `amazon-bedrock` | `bedrock-converse-stream`, or `bedrock-invoke-stream` as the built-in `moonshotai.kimi-k2-thinking` and `moonshotai.kimi-k2.5` models use |
| `deepseek` | `deepseek-chat` |
| `google` | `google-generative-ai` |
| `meta`, `openai`, `openai-codex` | `openai-responses` |
| `ollama` | `ollama-native` |
| `xai` | `xai-chat` |
| `zai`, `zai-coding-plan` | `openai-completions` |

o4 doesn't check the `api` value when it loads the file. With a value it has no handler for, such as a typo, the model is still listed, but every request to it fails with `API provider '<api>' not found`.

The other fields are optional:

| Field | Default | What it does |
| - | - | - |
| `reasoning` | `false` | Whether the model can reason. |
| `input` | `["text"]` | What the model accepts: `"text"`, plus `"image"` if it takes images. |
| `context_window` | `0` | The context window, in tokens. |
| `max_tokens` | `0` | The output limit, in tokens. `--list-models` shows `0` as `provider default`. |
| `headers` | none | Extra HTTP headers to send with each request to this model, as a table of names and values. `amazon-bedrock` models don't send them. |
| `deprecated` | `false` | `true` removes the model, including a built-in model with the same provider and ID, so `-m` can't find it. |
| `compat` | none | Provider-specific settings. See below. |
| `cost_estimated` | `false` | Accepted, but has no effect in 0.2.74. |

`[models.cost]` holds the `input`, `output`, `cache_read` and `cache_write` prices, in US dollars per million tokens. Each one defaults to `0`.

Two `compat` settings are useful in your own entries:

```toml theme={null}
[models.compat]
visibility = "hide"

[models.compat.reasoning]
efforts = ["low", "medium", "high"]
```

* `visibility = "hide"` leaves the model out of `o4 --list-models`, the **Select Model** list and model mentions. You can still choose it with `-m provider:id`.
* `efforts` lists the reasoning levels the model accepts, from `minimal`, `low`, `medium`, `high`, `xhigh` and `max`. It needs `reasoning = true`. Without it, the model only offers the `default` level. See [Reasoning](/models/reasoning).

<Warning>
  If one entry is missing a required field, o4 ignores the whole file. It also ignores the file if other users can write to it. Run `o4 --list-models` after each edit to confirm your models appear.
</Warning>

To connect a server that isn't a built-in provider, use `~/.o4/providers.toml` instead. See [OpenAI-compatible endpoints](/models/openai-compatible) and [Local models](/models/local-models).

## Related

* [Model router and fallback](/models/router) switches to another model automatically when a provider is rate limited or failing.
* [Reasoning and prompt profiles](/models/reasoning) covers reasoning effort and how the model choice changes the system prompt.
* [Context and cost](/guides/context-and-cost) explains how the context window and prices affect a session.
* [CLI reference](/reference/cli) lists every flag.
