Models
The merged model catalog and how to extend it.
--list-models and /model show the merged catalog across every provider. Built-in entries cover Claude, GPT/Codex, Gemini/Gemma, Kimi/Moonshot, DeepSeek, Groq-hosted models, OpenRouter-routed models, Bedrock and Vertex model IDs, Azure deployments, Copilot models, and more.
zot also merges live IDs discovered from GET /v1/models using stored API keys, cached for six hours in $ZOT_HOME/models-cache.json. Speculative catalog entries are included too; they start working as soon as the upstream provider enables them.
OpenRouter presets
When OpenRouter credentials are available, zot fetches the account's active presets and lists them in /model as @preset/<slug>. Presets are refreshed even while the public model cache is fresh, so account changes do not wait for the six-hour catalog refresh.
When model IDs change
Provider catalogs move quickly. zot removes built-in entries when an upstream route is stale or unavailable, but a live-discovered ID can reappear automatically if your API key can see it. If a pinned model stops resolving, run zot --list-models or open /model and pick a currently available ID.
For custom or private deployments, keep the stable deployment name in $ZOT_HOME/models.json instead of depending on a speculative public catalog entry.
Reasoning levels
Use /reasoning in the interactive TUI to set the reasoning level for subsequent model calls. The selector only shows distinct levels supported by the active model. Models without reasoning support only offer off. The current level is also shown in the model picker, and --reasoning off|minimum|low|medium|high|xhigh|max sets it from the command line.
Available levels are derived from the model's provider protocol and optional reasoningLevelMap overrides. The max tier is separate from xhigh and is available only where the active model can represent it or an explicit model override enables it. zot clamps a configured level to the nearest supported value when you switch models, so the selector and the provider request always use the same capability mapping.
Custom models
Add custom models with $ZOT_HOME/models.json. User entries take precedence over both baked-in and live-discovered models.
{
"providers": {
"openrouter": {
"models": [
{
"id": "my-custom-model",
"name": "My Custom Model",
"reasoning": true,
"reasoningLevelMap": { "minimum": "low", "max": "" },
"contextWindow": 200000,
"maxTokens": 8192
}
]
}
}
}Each top-level provider key is a zot provider id, for example openai, anthropic, ollama, openrouter, groq, amazon-bedrock, or google-vertex. Supported model fields are id (required), name, reasoning, reasoningLevelMap, contextWindow, maxTokens, baseUrl, priceInput, priceOutput, priceCacheRead, and priceCacheWrite.
reasoningLevelMap is optional. Protocol defaults apply when it is omitted. Use minimum, low, medium, high, xhigh, or max as keys for model-specific exceptions. Map a key to another level when the inputs are equivalent, use an identity mapping such as "max": "max" to enable a level beyond the protocol default, or map it to an empty string or off to remove that level. The effective mapping controls both /reasoning and provider requests.
Custom providers
A top-level provider key that is not a built-in id defines a custom provider. Give it a provider-level baseUrl and an api wire format (openai for OpenAI-compatible Chat Completions, the default, openai-responses for the OpenAI Responses API, or anthropic for the Anthropic Messages API). All models under that key are first-class: they show up in --list-models, /model, and /login.
{
"providers": {
"my-company": {
"baseUrl": "https://llm.mycompany.com/v1",
"api": "openai",
"models": [
{
"id": "company-llm-v2",
"name": "Company LLM v2",
"contextWindow": 128000,
"maxTokens": 32000
},
{
"id": "company-llm-fast",
"name": "Company LLM Fast",
"baseUrl": "https://fast-llm.mycompany.com/v1"
}
]
}
}
}A model-level baseUrl overrides the provider-level baseUrl for that model, so a single custom provider can fan out across more than one endpoint. If api is omitted it defaults to openai; an unrecognized value falls back to openai with a warning.
Credentials for custom providers
models.json never stores secrets. For a custom provider, supply its API key through /login, the --api-key flag, a provider environment variable, or a command in $ZOT_HOME/auth.json. The env var is derived from the provider id in upper snake case, so my-company reads MY_COMPANY_API_KEY and local-proxy reads LOCAL_PROXY_API_KEY.
To retrieve the key for the my-company provider above from a password manager, add a matching entry to $ZOT_HOME/auth.json:
{
"additional_api_key_creds": {
"my-company": {
"api_key_command": {
"program": "op",
"args": ["read", "op://Work/OpenAI/credential"],
"timeout_ms": 120000
}
}
}
}The provider IDs in models.json and auth.json must match. /login also lists custom providers alongside the built-in cloud providers and stores their keys in $ZOT_HOME/auth.json. Because many self-hosted gateways do not expose a model-list endpoint, custom provider keys are accepted and saved without a verification probe; an invalid key surfaces on the first model call.
# With the command-backed key above
zot --provider my-company --model company-llm-v2
# Or use an environment variable
MY_COMPANY_API_KEY=sk-... zot --provider my-company --model company-llm-v2Local and OpenAI-compatible endpoints
For Ollama and generic single-model servers that speak OpenAI chat completions (LM Studio, vLLM, LocalAI, a single-model llama.cpp server, or a private gateway), use the ollama provider and set baseUrl when the endpoint is not zot's default local Ollama URL. This provides inference only. For llama.cpp router management, configure the distinct llama.cpp provider through /login and use /llama.
{
"providers": {
"ollama": {
"models": [
{
"id": "my-local-model",
"name": "My Local Model",
"baseUrl": "http://localhost:1234/v1",
"contextWindow": 32768,
"maxTokens": 8192
}
]
}
}
}Then pick it with /model or run it directly:
zot --provider ollama --model my-local-modelAPI keys for custom local endpoints
models.json does not store credentials. It only describes models and their optional baseUrl. Credentials come from --api-key, provider environment variables, or $ZOT_HOME/auth.json written by /login.
If your local or private OpenAI-compatible endpoint requires a bearer token, pass it at launch:
zot --provider ollama \
--model my-local-model \
--base-url http://localhost:1234/v1 \
--api-key "$LOCAL_API_KEY"If a private endpoint uses a self-signed TLS certificate, add --insecure to skip certificate verification. It applies to the explicit --base-url endpoint and to a baseUrl defined for a user model in models.json, so built-in providers, /login auth, and model discovery keep normal TLS verification.
zot --provider ollama \
--model my-local-model \
--base-url https://my-llm.internal/v1 \
--api-key "$LOCAL_API_KEY" \
--insecureFor unauthenticated Ollama on the default URL, no key is needed:
ollama pull qwen3.5:4b
zot --provider ollama --model qwen3.5:4b