Docs

Mistral Vibe CLI

Vibe CLI reaches a third-party endpoint through a hand-edited TOML block, and Mistral's own documentation uses a gateway as the worked example. Five lines under [[providers]] and the agent is running Claude or GPT on your key.

A five-line [[providers]] block in .vibe/config.toml — api_base, api_key_env_var, api_style — points Vibe CLI at Kunavo, with the key living in an environment variable rather than the file.

.vibe/config.toml
# ./.vibe/config.toml (project) or ~/.vibe/config.toml (user).
# "Project-level configuration takes precedence over user-level
# configuration", and the project file loads only in a trusted folder.
active_model = "sonnet-kunavo"

[[providers]]
name = "kunavo"
api_base = "https://api.kunavo.com/v1"
api_key_env_var = "KUNAVO_API_KEY"
api_style = "openai"
backend = "generic"

[[models]]
name = "claude-sonnet-5"
provider = "kunavo"
alias = "sonnet-kunavo"
# Optional, and documented on the api-keys-profiles page:
#   temperature   sampling temperature
#   input_price   indicative per-input cost, fed to --max-price
#   output_price  indicative per-output cost, fed to --max-price
# Take the two prices from the table further down this page if you want
# --max-price to mean anything.

# The key never goes in config.toml. api_key_env_var names the variable:
#   export KUNAVO_API_KEY="sk-kn-..."
api_base keeps the /v1. Mistral's reference describes the field only as “Base URL for the provider's API” and states no rule about the suffix — what settles it is the value its own worked example uses on both documentation pages, api_base = "https://openrouter.ai/api/v1", and the reason behind it in the v2.25.5 source: the openai adapter appends /chat/completions to api_base and nothing else, and the CLI's built-in Mistral provider defaults to a /v1 base for the same reason. Drop the suffix and you ask for /chat/completions at the root, which is a 404 rather than an authentication error.
This configuration was read off Mistral's own documentation and Vibe's own source on the date below. Kunavo has not run Vibe CLI against its endpoint — not a session, not a streamed turn, not a tool round-trip. A published setup page is not a runtime test and nothing here should be read as one. The curl below is the part you can settle in ten seconds; everything the client does after that is between you and Vibe.
Kunavo serves no embedding, text-to-speech or speech-to-text model, so this endpoint answers chat completions and nothing else — a provider block pointed here covers the model turns and moves nothing else.
One thing that happens to work in your favour, and it is worth knowing why. Vibe's OpenAI path builds every payload with a temperature field, while several Claude ids — claude-sonnet-5 and claude-opus-5 among them — answer 400 upstream to the whole sampling trio. Kunavo strips those parameters before dispatch for exactly the ids that reject them, so the client's unconditional field does not turn into a hard rejection. The temperature key on a [[models]] preset is therefore harmless here, and also without effect on those ids.

Step by step

  1. Create a key at /app/keys and copy it — it is shown once.
  2. Open ~/.vibe/config.toml (or create ./.vibe/config.toml in the repository you want this to apply to) and paste the block above. There is no provider-add flow to click through: Mistral documents this file as hand-edited, and /config and /model only switch between presets that already exist.
  3. Export the variable you named in api_key_env_var export KUNAVO_API_KEY="sk-kn-...". Mistral's credential page documents ~/.vibe/.env as the file the CLI loads at startup for credentials, and its own third-party example uses a shell export for the non-Mistral key.
  4. Add a [[models]] preset per id you want, each with its own alias, then point active_model at one of those aliases. The alias is local — it is what /model lists, and name is the id that actually travels to the endpoint.
  5. Run vibe in a trusted folder and give it something that touches a file, not a greeting. A first turn that reads and edits exercises tool calling, which is where a misconfigured provider usually shows itself.

Checked against Mistral's Vibe Code CLI configuration page on September 21, 2026. Third-party settings move; if a field name here no longer matches what you see, that page is the authority, not this one.

This is the short version. The full walkthrough — model choice, what a real session costs, and the failure modes — is in the Vibe CLI vs Claude Code comparison.

Verify before you debug the client

One request settles whether a failure is the endpoint, the key, or the configuration file. If this returns JSON, the same base URL and key work in Mistral Vibe CLI.

# Settles whether a failure is the endpoint, the key, or the client.
curl -sS https://api.kunavo.com/v1/models \
  -H "Authorization: Bearer sk-kn-..."

Which model id to put in the field

Every text model is reachable as a model id — the live list is GET /v1/models, and the catalog with prices is on the models page. Rates are USD per 1M tokens, input / output.

Model idKunavo in / outWhere it fits in Mistral Vibe CLI
claude-sonnet-5$2.00 / $10.00the working alias — the one active_model points at most days
claude-opus-5$2.00 / $10.00a second preset for plan mode, where a wrong plan is the expensive part
claude-haiku-4-5$0.40 / $2.00cheap turns and quick file triage, as its own alias to switch to
gpt-5-6-sol$2.00 / $12.00a different family behind the same provider block, same key
Billing is per token from a prepaid balance with no monthly fee — see billing. On repeated context — which is most of what an editor or a chat client sends — prompt caching moves the bill more than the model choice does.

Not all of your traffic goes to this provider

This is the part a config block cannot tell you, and it is specific to Vibe rather than to Kunavo. At v2.25.5 the CLI routes background “utility” completions — the small calls that name conversations and worktrees — to Mistral's own mistral-vibe-cli-fast model whenever a Mistral provider is usable, and the shipped defaults always configure one, even when the session's active model is yours. The source is explicit about both the preference and the fallback: when no Mistral provider is usable, the utility call goes to the session's active model instead.

So if you want every request in the session to land on the provider you configured, one of these has to be true:

  • MISTRAL_API_KEY is unset, so the fast model's credential does not resolve and the utility call falls back; or
  • the fast model's alias is excluded through allowed_models, which has the same effect by the allowlist rather than by the key.

The Smart Approve classifier goes further — its 2.25.1 changelog entry says it runs on the fast Mistral model regardless of the session's active model — so a Kunavo-only session realistically lives in accept-edits or plan rather than in Smart Approve. None of this breaks the configuration above; it just means the provider block is about your model turns, not about every packet the binary sends.

The other api_style values

The documentation lists one value for api_style and describes it as an example: "openai". The v2.25.5 source carries four more — "anthropic", "openai-responses", "reasoning" and "vertex-anthropic" — in a plain dictionary with no validation, which is why a typo surfaces at request time rather than when the file loads. Treat them as source-verified and undocumented, and note one trap if you try the Anthropic one: its adapter's endpoint is /v1/messages, so that api_base must be the bare origin, https://api.kunavo.com, with no /v1 — the opposite of the block above. Kunavo does answer /v1/messages, for ids beginning claude-. This page shows the openai style because that is the one Mistral documents.

FAQ

How do I add a custom provider to Mistral Vibe CLI?

By hand, in config.toml — there is no provider-add UI. Mistral's configuration page documents ./.vibe/config.toml in the working directory and ~/.vibe/config.toml in your home directory, with the project file taking precedence, and its worked example is a [[providers]] table carrying name, api_base, api_key_env_var, api_style and backend, plus a [[models]] table carrying name, provider and alias, and an active_model pointing at that alias. The key itself is never in the file: api_key_env_var names the environment variable that holds it.

Does Vibe CLI's api_base need /v1 at the end?

For api_style “openai”, yes. Mistral's configuration reference describes api_base only as the base URL for the provider's API and states no rule about the suffix, but the worked example on both of its pages uses a value ending in /v1, and the v2.25.5 source shows why: the OpenAI-style adapter appends /chat/completions to api_base and nothing more, and the CLI's own built-in Mistral provider defaults to a /v1 base. So for Kunavo the value is https://api.kunavo.com/v1. Omitting the suffix produces a 404, not an authentication failure. The undocumented “anthropic” style is the opposite case — its endpoint is /v1/messages, so that api_base must not carry /v1.

Can Mistral Vibe CLI run Claude models?

Yes, through a provider preset rather than a switch. api_style names the wire protocol, not the vendor, and the model preset's name field travels to the endpoint as written, so a Claude id resolves at the endpoint you configured instead of inside the CLI. Mistral's own documentation demonstrates the pattern with a third-party gateway, which is what makes this a documented path rather than a workaround.

Why does Vibe CLI still call Mistral after I configure my own provider?

Because background utility completions are routed separately. At v2.25.5 the CLI prefers Mistral's own mistral-vibe-cli-fast model for small background calls — naming conversations and worktrees — whenever a Mistral provider is usable, and the shipped defaults always configure one, even while your session's active model is something else. It falls back to the active model when no Mistral provider is usable, which in practice means an unset MISTRAL_API_KEY or excluding that alias through allowed_models. The Smart Approve classifier is stricter still: its changelog says it runs on the fast Mistral model regardless of the session's active model.

Has Kunavo tested Mistral Vibe CLI?

No. What was checked, on September 21 2026, is Mistral's own documentation — the field names, their order and the /v1 question are taken from it, with the base-URL reasoning confirmed against the v2.25.5 source of the mistral-vibe package. Kunavo has not run a Vibe session against its endpoint and makes no claim about streaming, tool round-trips or how the client behaves over a long task. The endpoint and key can be settled on their own with the curl on this page; the rest is between you and the client.

Where does Vibe CLI read the API key from?

From the environment variable named in api_key_env_var — for a Kunavo provider block, whatever you called it, for example KUNAVO_API_KEY. Mistral's credential page documents three sources in precedence order for its own key: the interactive setup flow, which writes ~/.vibe/.env; an exported environment variable, which takes precedence over that file; and editing ~/.vibe/.env directly, which the CLI loads on startup. Its third-party example uses a shell export. The same page notes that .env is for credentials only and that general configuration belongs in config.toml.