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.

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.

Custom models

Add custom models with $ZOT_HOME/models.json. User entries take precedence over both baked-in and live-discovered models.

$ZOT_HOME/models.json
{
  "providers": {
    "openrouter": {
      "models": [
        {
          "id": "my-custom-model",
          "name": "My Custom Model",
          "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, contextWindow, maxTokens, baseUrl, priceInput, priceOutput, priceCacheRead, and priceCacheWrite.

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, or anthropic for the Anthropic messages API). All models under that key are first-class: they show up in --list-models, /model, and /login.

$ZOT_HOME/models.json
{
  "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.

Built-in models stay visible

Adding a models.json no longer hides the built-in catalog. Your custom providers and models are merged on top of the baked-in and live-discovered entries.

Credentials for custom providers

models.json never stores secrets. For a custom provider, supply its API key through /login, the --api-key flag, or a provider environment variable. 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.

/login now 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.

shell
# Via environment variable
MY_COMPANY_API_KEY=sk-... zot --provider my-company --model company-llm-v2

# Or persist the key with /login, then just
zot --provider my-company --model company-llm-v2

Local and OpenAI-compatible endpoints

For local servers that speak OpenAI chat completions (Ollama, LM Studio, vLLM, LocalAI, 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.

$ZOT_HOME/models.json
{
  "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:

shell
zot --provider ollama --model my-local-model

API 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:

shell
zot --provider ollama \
  --model my-local-model \
  --base-url http://localhost:1234/v1 \
  --api-key "$LOCAL_API_KEY"

Naming a custom provider

Use the ollama provider only for OpenAI-compatible local servers without their own credentials. For an authenticated gateway, prefer a named custom provider (see above) so its key works through /login and the matching environment variable instead of requiring --api-key on every launch.

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.

shell
zot --provider ollama \
  --model my-local-model \
  --base-url https://my-llm.internal/v1 \
  --api-key "$LOCAL_API_KEY" \
  --insecure

For unauthenticated Ollama on the default URL, no key is needed:

shell
ollama pull qwen3.5:4b
zot --provider ollama --model qwen3.5:4b