04. Models and Effort

Custom endpoints

Point Matcha CLI at an OpenAI-compatible gateway or a local Ollama daemon, store the key in the vault or an environment variable, and keep model ids exactly as that server names them.

You can attach extra models in ~/.matcha/config.toml under [model.<name>], share gateway settings under [model_providers.<id>], or override the catalog/inference base URL with [endpoints].models_base_url / MATCHA_MODELS_BASE_URL.

API backends

api_backend chooses the wire protocol for a custom [model.*] row:

ValueProtocolWhen you need it
chat_completionsOpenAI Chat Completions (/v1/chat/completions)Default if you omit the field
responsesOpenAI Responses (/v1/responses)Newer OpenAI-style gateways; built-in xAI uses this
messagesAnthropic Messages (/v1/messages)Direct Anthropic

Omitting api_backend on a [model.*] row defaults to chat_completions. That is a custom-row default, not a claim that every built-in Provider uses Chat Completions. The built-in xAI descriptor uses responses; Anthropic uses messages.

Credential resolution

For each request Matcha CLI resolves the API key in this order:

  1. api_key on the [model.*] row
  2. env_key — a string or an array of names; first set, non-empty value wins (useful for SSH LC_* forwarding)
  3. The Credential Vault secret for the selected Provider (matcha login --provider …)
  4. That Provider's official environment variable (XAI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, …)

Catalog vs inference URL

The catalog fetch uses {base_url}/models (or MATCHA_MODELS_LIST_URL / [endpoints].models_list_url when the list URL differs). Inference uses the same base unless a [model.*] row sets its own base_url. If the live list fails, a local disk cache may serve an origin-and-auth-matched copy labeled (cached).

Setting models_base_url selects a custom OpenAI-compatible slot and uses API-key auth. There is no browser login.

OpenAI-compatible gateway

matcha login --provider openai_compatible

Then add a model row (the Provider id has no default URL):

[model.together-mixtral]
model = "mistralai/Mixtral-8x7B-Instruct-v0.1"
base_url = "https://api.together.xyz/v1"
name = "Mixtral 8x7B"
env_key = "TOGETHER_API_KEY"

Or share the gateway once and point models at it:

[model_providers.gateway]
base_url = "https://gateway.example/v1"
# extra_headers / query_params / env_http_headers inherit onto models
# that set model_provider = "gateway" and omit their own copies

A key that also appears in the base_url query string is overridden (last value wins), not duplicated.

Ollama (local)

ollama serve
ollama pull codellama
matcha login --provider ollama
[model.ollama-codellama]
model = "codellama"
base_url = "http://127.0.0.1:11434/v1"
name = "CodeLlama (Ollama)"

Official Providers with an explicit row

You can also write a [model.*] row that talks to Anthropic or OpenAI directly. This is useful when you need extra headers, a context-window override, or the Responses API:

[model.claude-opus]
model = "claude-opus-4-6"
base_url = "https://api.anthropic.com/v1"
name = "Claude Opus 4.6"
api_backend = "messages"
context_window = 200000
env_key = "ANTHROPIC_API_KEY"
extra_headers = { "anthropic-version" = "2023-06-01" }
[model.gpt-4o]
model = "gpt-4o"
base_url = "https://api.openai.com/v1"
name = "GPT-4o"
env_key = "OPENAI_API_KEY"
[model.gpt-4o-responses]
model = "gpt-4o"
base_url = "https://api.openai.com/v1"
name = "GPT-4o (Responses)"
api_backend = "responses"
env_key = "OPENAI_API_KEY"

Or store the key in the vault and skip env_key:

matcha login --provider anthropic
matcha login --provider openai --from-env

Custom `/models` base URL

When every request should hit one gateway:

export MATCHA_MODELS_BASE_URL="https://api.acme.com/v1"
# Provider key as that gateway expects, for example:
export XAI_API_KEY="xai-..."
matcha

GROK_MODELS_BASE_URL is read only when the Matcha name is unset. Optional MATCHA_MODELS_LIST_URL overrides {base_url}/models.

Config equivalent:

[endpoints]
models_base_url = "https://api.acme.com/v1"

[model.grok-4.5]
env_key = "XAI_API_KEY"

With [endpoints].models_base_url set, partial [model.*] overrides inherit that base URL. Using XAI_API_KEY here is an example of whatever key that gateway expects — not a claim that inference defaults to xAI.

Common `[model.*]` fields

[model.my-model]
model = "model-id"
base_url = "https://api.example.com/v1"
name = "Display Name"
description = "Optional description"
env_key = "GATEWAY_API_KEY"
api_backend = "chat_completions"
temperature = 0.7
top_p = 0.95
max_completion_tokens = 8192
context_window = 128000
extra_headers = { "X-Request-Tags" = "team=example" }
query_params = { api-version = "2026-07-22" }
env_http_headers = { "X-Tenant-Token" = "GATEWAY_TENANT_TOKEN" }

context_window drives auto-compaction. A new model that omits it defaults to 200,000 tokens — set it to match the server.

Global defaults that apply to every catalog row (built-in, prefetched, or custom) live under [models]. A per-model value always wins:

[models]
default = "my-model"
temperature = 0.7
top_p = 0.95
max_completion_tokens = 8192
max_retries = 8
inference_idle_timeout_secs = 600
stream_tool_calls = true
extra_headers = { "X-Request-Tags" = "team=example,env=prod" }

stream_tool_calls changes request shape. If a BYOK gateway rejects a global true, set stream_tool_calls = false on that [model.<id>].

Settings that identify a specific model (model, base_url, api_key, context_window, …) cannot be defaulted under [models]. Reasoning effort stays at [models].default_reasoning_effort.

Override a catalog id by writing only the fields you want to change. Priority: your [model.*] > prefetched /v1/models > hardcoded Provider defaults.

Use the custom id

matcha models
/model my-model
matcha -p "Hello" -m my-model

If the list is empty or a call fails

matcha models

Confirm the selected Provider actually serves that id. Check [model.*] typos. Probe the gateway with the Provider's header scheme (Bearer vs x-api-key); do not paste keys into tickets.

RUST_LOG=debug MATCHA_LOG_FILE=/tmp/matcha.log matcha

Look for model / sampling lines. Logs must not contain API keys.

What Matcha CLI does not do

  • No MatchaCode product inference URL, no browser OAuth, no device-code login.
  • Product web search, image generation, and video generation are unavailable. [models] web_search does not enable them. Use a local MCP server if you need search-like tools.
  • Ollama is not a remote GPU marketplace; the built-in Provider requires loopback.