Files
Kigi-CLI/crates/codegen/kigi-tui/docs/user-guide/11-custom-models.md
T
ZacharyZhang-NY d6c20fc13f M0: compilable skeleton — Kigi 0.1.0 fork surgery
Hard fork of xai-org/grok-build (Apache-2.0) re-targeted as Kigi, an
unofficial Kimi Code CLI community build.

Rename & identity
- 72 xai-*/xai-grok-* crates -> kigi-* (explicit: xai-grok-pager-bin ->
  kigi-bin [binary `kigi`], xai-grok-pager -> kigi-tui; rest mechanical);
  ptyctl, ptyctl-cli, third_party/ unchanged; proto package
  xai.grok.tools.v1 -> kigi.tools.v1
- Config home ~/.kigi (KIGI_SHARE_DIR override), env prefix GROK_* ->
  KIGI_*, `kigi --version` carries the unofficial-community-build notice
- clap identity, help text, startup banner, prompt templates rebranded
  (templates re-encrypted)

Deletions (PRD removal list #5/#6/#7/#9/#10)
- voice input (xai-grok-voice) and all TUI wiring
- telemetry: Mixpanel client, external OTel stream, Sentry, OTLP layers,
  trace/GCS/S3 upload queues (kigi-file-utils halved), workspace upload
  module & dc_log, heap-profile uploader, auth-diagnostics uploader,
  session-analytics halves of feedback; local zero-egress observability
  preserved in new kigi-log crate (unified log, --debug firehose,
  subsystem file logs, opt-in instrumentation)
- announcements (crate, remote-settings fields, TUI surfaces)
- plugin marketplace (crate, sources/browse/CTA/extensions-modal tab);
  direct plugin install/uninstall/update via kigi-agent git_install kept
- relay/gateway/assets endpoints and features (agent relay, headless
  relay transport, gateway bridge, LeaderEnvUrls); leader IPC socket now
  ~/.kigi/leader.sock + KIGI_LEADER_SOCKET, no ws-url derivation
- functional types rehomed instead of deleted: PermissionMode ->
  kigi-config-types, McpInitStrategy -> kigi-mcp, PrCreationSource ->
  session signals, TerminalDiagnostics -> kigi-pager-render, agent_id ->
  shell util

Endpoints
- kigi-env rewritten: single production KigiEndpoints {coding_api_base_url
  https://api.kimi.com/coding/v1 (KIGI_CODE_BASE_URL), oauth_host
  https://auth.kimi.com (KIGI_OAUTH_HOST), update_base_url (GitHub
  Releases API), upgrade_page_url}; GrokBuildEnvironment enum deleted

Toolchain & workspace hygiene
- Rust 1.97.0 pinned; edition 2024; full cargo update; git2 hoisted to
  workspace at 0.21 (Option->Result API migration), quick-xml 0.41
- Root Cargo.toml hand-maintained (PRD §8.1): version 0.1.0 inherited by
  all members, members sorted, unused deps pruned
- cargo-deny advisories gate (deny.toml with documented transitive
  exceptions); CI workflow (check/clippy/fmt/deny/test, macOS+Linux)
- cross-crate test seams re-gated behind `test-support` cargo feature;
  insta snapshot baselines renamed to the kigi_tui prefix
- clippy --workspace --all-targets: zero warnings; fmt clean

Fixes surfaced by the port
- updater probe/installer divergence (bin/kigi vs bin/grok symlink set)
- idle model-metadata refresh dead under KIGI_CODE_BASE_URL override
  (new is_effective_coding_endpoint_url, loopback+override aware)
- macOS symlinked-TMPDIR fixture canonicalization (foreign_sessions,
  fast-worktree); RSS measurement tests serialized via serial_test

Docs & legal (Apache §4)
- NOTICE added (upstream attribution + change statement); THIRD-PARTY
  notices sustained; kigi-tools ported-code notices extended; README,
  CONTRIBUTING, SECURITY, AGENTS.md rewritten

Out of scope for M0 (tracked): Kimi auth/inference (M1), search/fetch,
command parity, config import (M2), Computer Hub excision & final
brand-token sweep (M2), distribution & self-update rewrite (M3).
2026-07-17 05:31:01 -04:00

11 KiB

Custom Models

Grok connects to custom model endpoints for alternative providers, self-hosted models, and overriding built-in settings. This guide explains how to select models, configure endpoints, and integrate third-party providers.


Default Models

By default, Grok uses models hosted by SpaceXAI, and new sessions start with grok-build. Default models require no configuration. Authenticate with grok login or an API key, then start a session.

List all available models:

grok models

Selecting a Model

CLI Flag

grok -p "Hello" -m grok-build

Slash Command

In the TUI, switch models during a session:

/model grok-build

Or use the alias:

/m grok-build

Model Picker (Ctrl+M)

Press Ctrl+M from the scrollback pane to open the model picker. It lists all available models, both built-in and custom, and lets you switch with a single keystroke. With the prompt focused, Ctrl+M toggles multiline input instead -- use /model to switch without leaving the prompt.

Config Default

Set a persistent default in ~/.kigi/config.toml:

[models]
default = "grok-build"

Supported API Backends

Grok supports three API backends. Set api_backend in your [model.*] config to choose which protocol the model uses:

Value API Default
"chat_completions" OpenAI Chat Completions (/v1/chat/completions) Yes
"responses" OpenAI Responses (/v1/responses)
"messages" Anthropic Messages (/v1/messages)

When you omit api_backend, Grok uses chat_completions.

To send provider-specific authentication or version headers -- for example, Anthropic's x-api-key -- use the extra_headers field described below. Grok sends those headers verbatim with every request to the endpoint.


Configuring Custom Models

Add custom model endpoints in ~/.kigi/config.toml under [model.<name>] sections:

[model.my-model]
model = "model-id"                        # Model identifier sent to the API
base_url = "https://api.example.com/v1"   # OpenAI-compatible endpoint
name = "Display Name"                     # Shown in the model picker
description = "Model description"          # Optional description
api_key = "sk-..."                        # API key for this provider (optional)
env_key = "XAI_API_KEY"                   # Env var holding the API key (optional; string or array)
api_backend = "chat_completions"          # "chat_completions", "responses", or "messages"
temperature = 0.7                         # Sampling temperature
top_p = 0.95                              # Nucleus sampling parameter
max_completion_tokens = 8192              # Maximum tokens per response
context_window = 128000                   # Total context window in tokens
extra_headers = { "x-api-key" = "sk-..." } # Extra request headers, sent verbatim (optional)

Credential Resolution

Grok resolves the API key in this order:

  1. The api_key field in the model config
  2. The environment variable(s) named by env_key — a single string or an array of names. The first set, non-empty value wins (for example env_key = ["ANTHROPIC_AUTH_TOKEN", "LC_ANTHROPIC_AUTH_TOKEN"] for SSH LC_* forwarding)
  3. Your signed-in session token (from grok login), for a model with no api_key/env_key of its own
  4. The XAI_API_KEY environment variable (global fallback; Grok also accepts KIGI_CODE_XAI_API_KEY for backward compatibility)

Context Window

The context_window value tells Grok when to trigger auto-compaction. When you override a known model, Grok inherits that model's context window. When you define a new model and omit context_window, Grok defaults to 200,000 tokens, so set it explicitly to match your provider.

Global Default Headers

To apply the same headers to every model in the catalog -- built-in, prefetched from /v1/models, or custom -- set them once under the global [models] section instead of repeating them per model:

[models]
extra_headers = { "X-Request-Tags" = "team=example,env=prod" }

These act as a base for each model's inference requests. A per-model [model.<id>].extra_headers entry overrides the global default per key (matched case-insensitively): a key set on the model wins, while any global-only keys are still inherited by that model. Like the per-model field, they ride on that model's inference calls -- not on separate services such as image generation or video generation -- which makes them handy for attribution tags (for example, cost tracking) without re-declaring them whenever a new model appears.

Global Default Values

A few common per-model settings can also be set once under [models] as a default for every model. A per-model [model.<id>] value always wins; the global only fills in where a model (or the server's model list) left the field unset:

[models]
temperature                 = 0.7
top_p                       = 0.95
max_completion_tokens       = 8192
max_retries                 = 8
inference_idle_timeout_secs = 600
stream_tool_calls           = true

This is a small, fixed set of environment-wide knobs. Settings that identify a specific model (model, base_url, api_key, context_window, ...) cannot be defaulted this way, and a few settings with their own dedicated configuration -- auto-compaction ([session]), the system-prompt label ([agent]), and reasoning effort ([models].default_reasoning_effort) -- keep their existing homes.

Note on stream_tool_calls: this one affects request shape, not just sampling. A few endpoints (some BYOK providers) expect it left unset; if a global stream_tool_calls = true causes problems for such a model, opt that model out with stream_tool_calls = false in its [model.<id>] block.


Overriding Built-in Models

You can override specific fields of built-in models without redefining everything. Only specify the fields you want to change:

# Override only the API key for a default model
[model.kigi-build]
api_key = "my-api-key"

# Override temperature and add a custom API key
[model.kigi-build]
temperature = 0.5
api_key = "sk-custom"

When you override a built-in model, Grok starts with the default configuration (including the correct base_url), then applies only the fields you specify. Unspecified fields inherit from the default.

Priority Order

  1. Your config ([model.*]) -- highest priority
  2. Prefetched models from remote /v1/models
  3. Hardcoded defaults -- lowest priority

Provider Examples

Anthropic (Claude)

Use Claude models directly via the Anthropic Messages 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
extra_headers = { "x-api-key" = "sk-ant-...", "anthropic-version" = "2023-06-01" }

The messages backend uses the Anthropic Messages protocol. Anthropic authenticates with an x-api-key header rather than Authorization: Bearer, so pass your key through extra_headers, which Grok sends verbatim.

OpenAI (Chat Completions)

[model.gpt-4o]
model = "gpt-4o"
base_url = "https://api.openai.com/v1"
name = "GPT-4o"
env_key = "OPENAI_API_KEY"

api_backend defaults to "chat_completions", so you don't need to set it explicitly for OpenAI.

OpenAI (Responses API)

If your provider supports the newer Responses API:

[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"

Ollama (Local Models)

Run models locally with Ollama:

[model.ollama-codellama]
model = "codellama"
base_url = "http://localhost:11434/v1"
name = "CodeLlama (Ollama)"

Make sure Ollama is running (ollama serve) and the model is pulled (ollama pull codellama).

Together AI

[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"

Local OpenAI-Compatible Server

Any server that implements the OpenAI Chat Completions or Responses API:

[model.local-llama]
model = "llama-3.1-70b"
base_url = "http://localhost:8080/v1"
name = "Local Llama"
temperature = 0.8

Custom Models Endpoint

Point Grok at a custom OpenAI-compatible /v1/models endpoint instead of the default. Use this when your models sit behind a corporate gateway or a self-hosted inference service.

Environment Variables

Variable Required Description
KIGI_MODELS_BASE_URL Yes Base URL for inference. Grok fetches the model list from {base_url}/models.
XAI_API_KEY Yes API key sent as Authorization: Bearer. Grok also accepts KIGI_CODE_XAI_API_KEY.
KIGI_MODELS_LIST_URL No Override the model-list URL when it differs from {base_url}/models.

Setup

export KIGI_MODELS_BASE_URL="https://api.acme.com/v1"
export XAI_API_KEY="xai-..."
grok

Config File Alternative

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

# Override only the API key for a specific model
[model.kigi-build]
api_key = "my-api-key"

When you use [endpoints] with partial model overrides, Grok inherits the base_url from the endpoints config, so you do not need to specify it in each [model.*] section.

Auth Behavior

When you set models_base_url, Grok uses API key auth (Authorization: Bearer) instead of session auth. You do not need grok login -- the API key is enough.


Web Search Model

The web_search tool uses a separate model. Configure it with:

[models]
web_search = "grok-4.20-multi-agent"

Or via environment variable:

export KIGI_WEB_SEARCH_MODEL="grok-4.20-multi-agent"

If you point web search at a custom model, you also need a [model.*] entry so Grok can reach it. Server-side ("backend") web search runs only when the model sets supports_backend_search = true (and the build enables backend search); it does not depend on api_backend:

[models]
web_search = "my-custom-model"

[model.my-custom-model]
model = "my-custom-model"
supports_backend_search = true

Using Custom Models

# List available models (including custom)
grok models

# Use in the TUI via slash command
/model my-model

# Use in headless mode
grok -p "Hello" -m my-model

# Set as default in config.toml:
[models]
default = "my-model"

Enterprise Deployment

A complete config for an enterprise deployment with custom models:

[cli]
auto_update = false

[auth]
auth_provider_command = "/usr/local/bin/my-company-auth-provider"
auth_provider_label = "Acme Corp"
auth_token_ttl = 3600

[models]
default = "company-grok"

[model.company-grok]
model = "grok-build"
base_url = "https://grok-proxy.acme.com/"
name = "Grok Build Latest (Proxy)"
context_window = 128000

[features]
telemetry = false

Troubleshooting

Model Not Found

# List available models
grok models

# Check config.toml for typos in [model.*] sections

Connection Errors

Verify the endpoint is reachable:

curl -s https://api.example.com/v1/models \
  -H "Authorization: Bearer $XAI_API_KEY"

Debug Logging

RUST_LOG=debug KIGI_LOG_FILE=/tmp/grok.log grok
tail -f /tmp/grok.log

Look for log entries containing model or sampling to trace model selection and API calls.