Provider presets¶
How to pick a curated API provider without memorising URLs, model ids, or auth headers — and how to extend the catalogue with custom endpoints.
What a preset gives you¶
A preset bundles the three things a first-party provider needs: the wire,
the endpoint URL, and the default model id. Auth is bundled too —
every built-in preset sends Authorization: Bearer <key> instead of the
Anthropic SDK's default X-Api-Key header (the SDK default would 401
against MiniMax and Z.ai).
Use a preset when you don't want to memorise:
base_url(e.g.https://api.minimax.io/anthropic)- the right
provider(openaivsanthropic) - the default
modelid - the right auth header
A preset folds into the override chain via setdefault semantics — an
explicit CLI flag, env var, or file entry always wins over the preset's
default for the same knob. The preset never silently overwrites something
you set.
Built-in presets¶
| id | label | base_url |
default model | models | key_url |
|---|---|---|---|---|---|
minimax |
MiniMax | https://api.minimax.io/anthropic |
MiniMax-M3 (1M ctx) |
MiniMax-M3, MiniMax-M2.7, MiniMax-M2.7-highspeed, MiniMax-M2.5, MiniMax-M2.5-highspeed, MiniMax-M2.1, MiniMax-M2.1-highspeed, MiniMax-M2 |
https://api.minimax.io/usercenter/charge |
zai |
Z.ai | https://api.z.ai/api/anthropic |
glm-5.2 (1M ctx) |
glm-5.2, glm-5.1, glm-5-turbo, glm-4.7, glm-4.5-air, glm-4.5, glm-4.5-flash |
https://z.ai/manage-apikey/apikey-list |
The Anthropic-preset rows (MiniMax, Z.ai) ride the same thinking.type knob as real Anthropic — enabled / disabled / adaptive (the model-writable form). Defaults to adaptive so a vanilla install keeps the previous turn-on reasoning behavior. Change the knob with KIN_THINKING_TYPE=disabled uv run kin (env) or thinking_type = "disabled" in settings.toml; flip it live with /settings on and let kin propose the diff. The reasoning-depth preset (Z.ai's 8-value vocabulary, etc.) is the effort knob — see /effort for the live setter.
Note
Z.ai's glm-5.2 default uses the 1M-context long-context tier —
the tier is reached via context_window = 1000000 in settings, not
via the model id. MiniMax's MiniMax-M3 ships plain with 1M
context; the long-context tier is configurable on the MiniMax
side. The [1m] suffix is a Claude Code SDK convention, not a
Z.ai wire-level model id. Use plain glm-5.2 and set
context_window = 1000000 for the 1M tier; the suffix produces
model_not_found on a raw SDK call.
The /providers command¶
/providers opens a modal listing the built-ins + any [[providers]]
rows already on file. The API-key field is focused on open — just type
the key; Up/Down or a mouse click both just pick a row (they
update the description pane and refocus the key field — they don't save).
Hit Enter or click Save to actually commit. The worker writes the choice back to
~/.kin/settings.toml and switches the running session to it live — no
restart — toasting "switched to {provider}". The file write is still the
persistent baseline that feeds new sessions (see
Configuration); the live swap is
fail-closed (a backend that won't build leaves the
current one untouched). The pick is refused while a turn is running.
/providers [name] opens the modal pre-selected on the named preset
(built-in or [[providers]] id). Unknown ids refuse before opening the
modal so a typo doesn't silently no-op.
For the full key reference, see Slash commands; for the modal's row shortcuts, see Keybindings & cursor mode.
/providers vs /model vs the picker¶
The three surfaces funnel through one swap helper, but only /providers writes a key:
| Surface | When to use | Writes |
|---|---|---|
/providers |
Enter a key + set up a provider end-to-end (the canonical key-entry surface) | provider_preset + provider_keys[<id>] (read-merged) + model + (for customs) [[providers]] row |
/model <id> (inline) |
Swap to a model id you already know; silent when a key resolves, else refuses with a hint | provider_preset + model (no key write) |
/model (bare, picker) |
Browse across providers with the keyboard; the ✓ key badge shows which are ready |
provider_preset + model (no key write) |
All three flows funnel through commands_mixin._swap_to_provider → save_global_settings(...) (the human-only writer) → Session.set_provider(...) — so a swap is durable across restarts and takes effect on the running session immediately. Keys are entered only via /providers; /model never prompts for one.
Other surfaces¶
Three surfaces reach the same preset machinery, in this precedence order:
| Surface | Example | When to use |
|---|---|---|
| CLI flag | uv run kin --preset minimax |
A one-off override (highest precedence) |
| Env var | KIN_PRESET=zai uv run kin |
A shell-level override (above the file) |
| Settings key | provider_preset = "minimax" in ~/.kin/settings.toml |
Persistent baseline |
The modal writes the file layer and swaps the live backend in place.
The file is still what new sessions read; /reload re-applies an
edited settings.toml to a running session without a restart too.
A raw base_url default isn't switchable-back-to
A plain top-level base_url + model in settings.toml (e.g. a local
vLLM/llama.cpp endpoint with no provider_preset) works fine as your
launch default, but it's not a catalogue entry — /model and
/providers only list built-ins + [[providers]] rows. Swap away from it
via /providers <other> and there's nothing left pointing back at it. If
you want to swap back and forth, give it a [[providers]] row too (see
Custom endpoints below) — an auth-less local server
just omits the key (/providers treats an empty field as fine to save; no
key is ever required, only merged in when typed).
Custom endpoints¶
/providers → "Custom endpoint…" → enter name + URL + wire
(anthropic or openai) + model. The modal writes a [[providers]]
row to ~/.kin/settings.toml and sets provider_preset to the name.
Manual [[providers]] block (the modal's write target):
[[providers]]
id = "openrouter"
label = "OpenRouter"
provider = "openai"
base_url = "https://openrouter.ai/api/v1"
default_model = "anthropic/claude-3.7-sonnet"
models = ["anthropic/claude-3.7-sonnet"]
# extra_headers = { "X-Tenant-ID" = "acme" } # optional
A custom row's id can shadow a built-in (so operators can override a
built-in's URL without code changes), but the built-in lookup runs
first so the curated catalogue wins for the common case. After saving,
/providers openrouter opens the modal pre-selected on the custom row.
Row keys: model vs default_model vs models¶
The three keys do different things, and a row that confuses them renders
an empty group in /model (the header shows but there's nothing to pick):
| Key | What it does |
|---|---|
default_model |
The model id the factory pre-fills when this preset is active and no other model was set. Also seeds models if no models list was given (see below). |
models |
The catalogue the /model picker iterates for this row. Multiple ids → multiple pickable rows. |
model |
Convenience alias for default_model — same key, just shorter. Honored ONLY when default_model is unset. Useful for one-line rows like a vLLM stable-alias setup: model = "default". |
Two safety nets so the one-line shape still surfaces a pickable row:
model = "default"is accepted as an alias fordefault_model.- When neither
modelsnordefault_modelis set, butmodelis, the model id seedsmodels = (model,)too — the picker renders one row.
# Minimal: single-model / stable-alias custom endpoint.
[[providers]]
id = "vllm"
label = "vLLM (tailnet)"
provider = "anthropic"
base_url = "http://kin-one:8000/v1"
model = "default" # alias for default_model; seeds models = ["default"]
If you want the picker to show every model your server actually serves, prefer the explicit two-key form — or wire /providers's "Custom endpoint…" form, which writes both default_model and (when known) models for you.
The curated catalogue is not a silent cap¶
The built-in lists cover the verified ids from each provider's official docs. A model id not in the catalogue is still reachable:
KIN_MODEL=<id> uv run kin(overrides the preset's default)--model <id>(CLI override)- A
[[providers]]row that names it
The catalogue is the curated subset the harness is willing to ship defaults for; nothing stops you from picking another model id on the same wire.
Preset auth is Bearer, not x-api-key
Built-in presets send Authorization: Bearer <key> because MiniMax
and Z.ai both reject the Anthropic SDK's default X-Api-Key header.
The factory routes the resolved key into the SDK's auth_token=
slot (not api_key=) so only Bearer rides the wire. A non-preset
AnthropicBackend(api_key=...) still uses x-api-key as before — no
behaviour change for users who aren't using presets.
The GLOBAL_ONLY safety boundary¶
provider_preset and providers are global-only keys — honored from
the global file, the environment, or a CLI flag, but stripped (with a
warning) from any project .kin/settings.toml. A cloned repo's project
file can't silently retarget your wire to a third-party endpoint and
silently route your global api_key through it. The threat model is
identical to base_url / api_key being global-only — see
settings.toml keys for the rest of the
denylist and the rationale.