# How the Kimi CLI Handles Switching Between Models and Refreshing Provider Information

> Discover how the Kimi CLI manages switching models and refreshing provider data. Learn about its efficient LLM instance rebuilding and asynchronous metadata updates via shell commands.

- Repository: [Moonshot AI/kimi-cli](https://github.com/MoonshotAI/kimi-cli)
- Tags: internals
- Published: 2026-07-21

---

**The Kimi CLI maintains a single mutable `LLM` instance in `Runtime.llm` that is rebuilt via the `create_llm()` factory function whenever users switch models or override capabilities, while provider metadata refreshes asynchronously through `refresh_managed_models()` triggered by shell commands.**

The MoonshotAI/kimi-cli repository implements a centralized runtime architecture that decouples provider configuration from model selection. Understanding how the CLI handles switching between models and refreshing provider information requires examining the mutable state in `Runtime.llm`, the configuration parsing pipeline, and the shell layer's refresh hooks.

## The Centralized Runtime Architecture

### The Single LLM Instance

At the heart of the CLI lies a singleton pattern implemented through `Runtime.llm`. According to the source code in **[`src/kimi_cli/app.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py)** (lines 216‑225), the application stores exactly one `LLM` object that serves as the source of truth for all chat operations:

```python

# Simplified representation from src/kimi_cli/app.py

runtime.llm = create_llm(
    provider_cfg=provider_config,
    model_cfg=model_config,
    oauth_token=token
)

```

Because `Runtime.llm` is a mutable reference, updates to the selected model or its capabilities propagate automatically throughout the application stack, affecting the UI rendering, tool routing logic, and token-usage calculations without requiring a process restart.

### Configuration Loading Pipeline

The CLI loads persistent settings from `~/.kimi/config.toml` through **[`src/kimi_cli/config.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/config.py)**. This configuration defines both the **provider configuration** (which backend service to use—OpenAI, Anthropic, Gemini, or Kimi) and the **model configuration** (specific model names like `gpt‑4o`, `claude‑3‑sonnet`, or `kimi‑latest`). When the CLI initializes, it resolves these values to determine the default conversational context.

## Switching Between Models

### Command-Line Overrides

Users can override the default model configuration at invocation time. The CLI parses these flags in **[`src/kimi_cli/cli/__init__.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/cli/__init__.py)** and forwards them to the application layer:

```bash

# Explicit model selection

kimi chat --model=gpt-4o-mini

# Enable thinking mode (capability override)

kimi chat --thinking

```

The `--model` flag replaces the configured default, while `--thinking` forces the addition of reasoning capabilities to the current model's feature set. These overrides are processed before the `LLM` object is instantiated.

### The create_llm() Factory

The actual construction logic resides in **[`src/kimi_cli/llm.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/llm.py)**. The `create_llm()` function accepts provider and model configuration objects, instantiates the appropriate `ChatProvider`, and calculates capabilities:

```python
from kimi_cli.llm import create_llm

# Build a new LLM instance with explicit configurations

llm = create_llm(
    provider_cfg=provider_config,
    model_cfg=model_config,
    oauth_token=current_token
)

# Store in runtime for application-wide access

runtime.llm = llm

```

The resulting `LLM` object encapsulates:
- The chat provider instance (`chat_provider`)
- Maximum context size (`max_context_size`)
- Derived capability set (`capabilities`)
- Model and provider configuration metadata

## Refreshing Provider Information

### Triggering a Refresh

When authentication tokens expire or when users explicitly request an update, the CLI must reload the available model list from the provider's API. This operation is initiated in **[`src/kimi_cli/ui/shell/slash.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/ui/shell/slash.py)** at line 194, where shell slash-commands invoke `refresh_managed_models(config)`:

```python

# Located in src/kimi_cli/ui/shell/slash.py (line 194)

await refresh_managed_models(self.runtime.config)

```

### The refresh_managed_models Implementation

The actual network operation lives in **[`src/kimi_cli/auth/platforms.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/auth/platforms.py)**. This function contacts the provider's API endpoint (OpenAI, Anthropic, Kimi, etc.) to repopulate the internal model registry with current pricing, context limits, and availability:

```python
from kimi_cli.auth.platforms import refresh_managed_models
from kimi_cli.config import load_config

async def update_provider_data():
    cfg = load_config()
    await refresh_managed_models(cfg)  # Contacts provider API

    # Subsequent LLM instantiations see updated models

```

### Capability Derivation

After refreshing provider data, the CLI recalculates what features each model supports using `derive_model_capabilities()` in **[`src/kimi_cli/web/api/config.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/web/api/config.py)** (line 10). This ensures that capability flags (such as vision support, tool use, or extended context) remain synchronized with the provider's current offerings.

## Practical Implementation Examples

Switch models dynamically within a running session by rebuilding the runtime instance:

```python
from kimi_cli.llm import create_llm
from kimi_cli.config import load_config

# Load current configuration

config = load_config()

# Switch to a different model by name

new_model_config = config.models['claude-3-opus']
provider_config = config.providers['anthropic']

# Rebuild and update the runtime singleton

import kimi_cli.app
kimi_cli.app.Runtime.llm = create_llm(
    provider_cfg=provider_config,
    model_cfg=new_model_config
)

```

Force a provider refresh programmatically:

```python
from kimi_cli.auth.platforms import refresh_managed_models
import asyncio

async def sync_models():
    cfg = load_config()
    await refresh_managed_models(cfg)
    print("Provider model list updated")

asyncio.run(sync_models())

```

## Summary

- **Single Instance Architecture**: The CLI uses one mutable `LLM` object stored in `Runtime.llm` (**[`src/kimi_cli/app.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py)**, lines 216‑225) to maintain consistent state across the application.
- **Factory Pattern**: `create_llm()` in **[`src/kimi_cli/llm.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/llm.py)** constructs provider instances and derives capabilities, accepting configuration overrides from the CLI.
- **Configuration Sources**: Default models and providers load from `~/.kimi/config.toml` via **[`src/kimi_cli/config.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/config.py)**, but can be overridden with `--model` and `--thinking` flags parsed in **[`src/kimi_cli/cli/__init__.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/cli/__init__.py)**.
- **Provider Refresh**: The `refresh_managed_models()` function in **[`src/kimi_cli/auth/platforms.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/auth/platforms.py)** updates the internal registry when called from **[`src/kimi_cli/ui/shell/slash.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/ui/shell/slash.py)** (line 194).
- **Capability Calculation**: Model features are determined dynamically by `derive_model_capabilities()` in **[`src/kimi_cli/web/api/config.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/web/api/config.py)** (line 10) using refreshed provider metadata.

## Frequently Asked Questions

### How does the Kimi CLI store the active model configuration?

The CLI stores the active configuration in a singleton `LLM` instance attached to `Runtime.llm` (**[`src/kimi_cli/app.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py)**). This object contains both the `provider_config` and `model_config`, allowing all UI components and API handlers to reference the current settings through a single centralized accessor.

### What triggers a provider information refresh?

Provider refreshes occur when the shell layer detects authentication changes or token expiry, explicitly calling `refresh_managed_models(config)` in **[`src/kimi_cli/ui/shell/slash.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/ui/shell/slash.py)** (line 194). This function contacts the provider's API to update available models and their capabilities without requiring a CLI restart.

### Can I switch models without restarting the CLI?

Yes. Since `Runtime.llm` is a mutable reference, you can call `create_llm()` with new configuration parameters and assign the result to `Runtime.llm` at runtime. The next chat interaction will use the new model's context window and capabilities immediately.

### Where does the CLI calculate model capabilities?

Capabilities are calculated in **[`src/kimi_cli/web/api/config.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/web/api/config.py)** at line 10 via `derive_model_capabilities()`, which examines the provider's metadata and model configuration to determine support for features like tool use, vision, and extended thinking modes.