# Models and providers (/models-and-providers)


Tidebreak has no model of its own and no hosted inference. You bring
credentials for the providers you want, and the app talks to them directly
from your machine.

## Add a credential

Open **Settings → Providers**. Each provider is its own section: turn on
**Enabled**, fill in the credential, and press **Save configuration**.

| Provider | What it takes |
| --- | --- |
| Anthropic | API key |
| OpenAI | A ChatGPT subscription (**Sign in with ChatGPT**) or a platform API key |
| Google Gemini | Gemini Developer API key |
| xAI | API key, plus the model IDs you want to use |
| Fireworks AI | API key; Tidebreak uses `https://api.fireworks.ai/inference/v1` |
| Together AI | API key; Tidebreak uses `https://api.together.ai/v1` |
| OpenRouter | API key; Tidebreak uses `https://openrouter.ai/api/v1`, plus the model IDs you want to use |
| Ollama | No key for a local daemon. Defaults to `http://127.0.0.1:11434/v1`, plus the model IDs you have already pulled |
| OpenAI-compatible | Base URL, optional key, plus the model IDs you want to use |

**Google Gemini** is the direct Gemini Developer API path and accepts a Gemini
API key.

The panel never shows a saved key back to you. It shows a status —
**API key set**, **Signed in with ChatGPT**, **Credential set**, or
**No credential**. **Clear** removes the stored credential after a
confirmation.

API keys go to your operating system's credential store, not to the database
and not to a config file. Base URLs and configured model rows are non-secret
settings.

<Callout>
If you would rather not store anything, the server also reads
`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `XAI_API_KEY`, `GEMINI_API_KEY`,
`FIREWORKS_API_KEY`, `TOGETHER_API_KEY`, and `OPENROUTER_API_KEY` from the
environment as fallbacks when no credential is saved.
</Callout>

## Curated models

Anthropic, OpenAI, Gemini, Fireworks, and Together ship with a curated list of
models. Fireworks and Together keep their host-specific model IDs and
capabilities. Nothing to configure — once the provider has a credential, its
models appear in the picker. The list is versioned with the app and refreshed
as providers ship new models.

Each entry carries what the app actually knows about it: context window,
maximum output, whether it accepts images, whether it produces a reasoning
stream, and which reasoning-effort levels it accepts. Those flags gate
behavior, not just labels — a model is only offered an image attachment if the
path that carries images is wired for it.

Hosted Kimi K3, K2.7, and K2.6 rows preserve their native
`reasoning_content` only when history returns to the same provider and model,
including tool continuations. A provider or model switch drops that native
field under the same flatten-on-switch rule used for other reasoning artifacts.
Kimi K3 exposes its documented **Low**, **High**, and **Max** effort choices.

Models the project has not exercised end to end are marked in the picker as
unverified. They still run; the badge says tool calling and streaming have not
been confirmed on that exact provider/model pair.

## Custom models

**xAI**, **OpenRouter**, **Ollama**, and **OpenAI-compatible** do not come with
a curated list. Add rows under the provider's **Models** section: a model ID,
an optional display name, and context and max-output token counts. For xAI,
you also declare whether the model takes image input, whether it is a
reasoning model, and which reasoning-effort levels it accepts.

**OpenRouter** is a hosted aggregator on the same OpenAI-compatible
chat-completions path. Enable it, paste an API key, and add each model id
you want to use (`anthropic/claude-sonnet-4` is the usual `vendor/model`
shape). Requests always go to `https://openrouter.ai/api/v1`.

**Ollama** talks to a local daemon over the same OpenAI-compatible
chat-completions path. Enable it, add a model you have already pulled
(`ollama pull qwen3:0.6b` is a small tool-calling option for a first test),
and leave the base URL at `http://127.0.0.1:11434/v1` unless the daemon is
somewhere else. A key is optional — only remote or locked-down Ollama
installs need one.

The generic OpenAI-compatible slot still points at any other endpoint that
speaks the same API, including LM Studio or vLLM:

```text
base URL: http://127.0.0.1:1234/v1
```

For configurable capability fields, you are asserting the provider contract
yourself. Get it wrong and turns fail at the provider rather than being caught
locally.

## Choose the default model

**Settings → Models** sets the model for two roles:

- **Chat** — what new conversations start on. Each chat can still override it.
- **Background work** — the model used for the app's own internal work
  (titling a chat, and similar short tasks). Cheaper, faster models suit this.

Either role can be left automatic, in which case it resolves against whatever
you have credentialed at the moment you use it, rather than being frozen at
the time you set it.

## Change the model for one chat

The composer has a model pill next to the send button. It names the model
the chat will run against. Until a provider is configured, it reads **No
model**. After that it shows the current model — the one from Settings if
you have not pinned one, or the pin if you have. The menu lets you switch
providers and models, and a **Default** switch returns the chat to following
your global setting.

The same menu carries **Reasoning** effort for models that expose it:
**Default**, **Off**, **Low**, **Medium**, **High**, **X-high**, **Max**.
Levels a model does not accept are not offered.

## Switching models mid-conversation

You can change the model in the middle of a chat and keep the thread. The
conversation is stored in a provider-neutral form, so history replays to
whichever provider you switch to.

Provider-specific artifacts do not survive the crossing. A reasoning trace
produced by one vendor, or a search block that vendor executed on its own
servers, is replayed to a different vendor as ordinary text — or dropped —
rather than being translated into that vendor's equivalent. Switch back and
new turns produce native artifacts again, but the ones already flattened stay
flattened.

This is deliberate. The alternative is a translator per pair of providers, and
those degrade in ways that are hard to see. Expect a small loss of fidelity
across a switch, not a silent re-interpretation.
