- 中文/英文 README 各加一段"下载"/"Downloads"段落 - 三平台链接: Windows .msi / macOS .dmg (注明未签名) / Linux 多格式 - 历史版本指向 git.codingplan.site - 加 GH Actions Release workflow 徽章
627 lines
39 KiB
Markdown
627 lines
39 KiB
Markdown
# Kimi Switch
|
||
|
||
> A Windows desktop **Kimi Code CLI** configuration manager — unify multi-provider LLM setup, models, icons, connectivity testing, usage analytics, and update checks in one place.
|
||
|
||
**English** | [中文](./README.md)
|
||
|
||
[](https://tauri.app)
|
||
[](https://react.dev)
|
||
[](https://www.typescriptlang.org)
|
||
[](https://www.rust-lang.org)
|
||
[](https://github.com/billowliu2/KimiSwitch/releases/tag/v0.6.0)
|
||
[](./LICENSE)
|
||
[](https://github.com/billowliu2/KimiSwitch/releases/latest)
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [What Is This](#what-is-this)
|
||
- [Key Features](#key-features)
|
||
- [Screenshots](#screenshots)
|
||
- [Architecture Overview](#architecture-overview)
|
||
- [Feature Details](#feature-details)
|
||
- [Supported Provider Types](#supported-provider-types)
|
||
- [Data Storage Locations](#data-storage-locations)
|
||
- [Getting Started](#getting-started)
|
||
- [Development Guide](#development-guide)
|
||
- [Keyboard Shortcuts](#keyboard-shortcuts)
|
||
- [Internationalization](#internationalization)
|
||
- [Testing](#testing)
|
||
- [Build & Release](#build--release)
|
||
- [Release History](#release-history)
|
||
- [FAQ](#faq)
|
||
- [Known Limitations & Next Steps](#known-limitations--next-steps)
|
||
- [Security Notes](#security-notes)
|
||
- [Credits](#credits)
|
||
|
||
---
|
||
|
||
## What Is This
|
||
|
||
**Kimi Switch** is a Windows desktop configuration tool built for [Kimi Code CLI](https://github.com/MoonshotAI/kimi-code) users. It pulls the hand-editing of `~/.kimi-code/config.toml` into a GUI and adds a pile of conveniences the CLI itself doesn't ship:
|
||
|
||
- **Unified multi-provider management** — Kimi / Anthropic / OpenAI / OpenAI Responses / Google GenAI / Vertex AI in one view; newly added providers are **automatically promoted to the top of the list**, and switching never overwrites or loses them
|
||
- **One-click model discovery** — fetch the available model list from the provider API; display names, context size, and capabilities **prefer the models.dev cache** (backend/UI fallback for missing fields)
|
||
- **Connectivity testing** — GET `base_url` (cc-switch semantics), with a coloured latency bubble (green / orange / red) that auto-dismisses in 6 seconds
|
||
- **Duplicate provider** — deep-copy an existing provider along with all its models in one click; the key becomes `xxx-copy`
|
||
- **Icon system** — 100+ first-party provider brand icons, adapted from cc-switch; unmatched providers get a deterministic initial-letter placeholder
|
||
- **Usage dashboard** — ported from kimicode-dashboard: KPIs / heatmap / per-model daily trend stacked bars / paginated recent requests
|
||
- **Session manager** — per-workspace browsing, preview, archive, and bulk delete for Kimi Code sessions
|
||
- **Update check** — auto-check on launch (toggleable) and one-click download + install
|
||
- **Theme / language** — dark / light / follow-system themes; Simplified Chinese / English
|
||
- **Windows polish** — single instance; minimize keeps the taskbar button; close hides to tray
|
||
|
||
## Downloads
|
||
|
||
- **Windows**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.msi`
|
||
- **macOS**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.dmg` (**unsigned** — first launch needs right-click → Open to bypass Gatekeeper)
|
||
- **Linux**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.deb` / `.AppImage` / `.rpm`
|
||
|
||
Historical versions (v0.5.x and earlier) live on the [git.codingplan.site repository](https://git.codingplan.site/admin/KimiCodeSwitch/releases).
|
||
|
||
Build instructions: [`docs/BUILD.md`](./docs/BUILD.md).
|
||
|
||
## Key Features
|
||
|
||
| Category | Feature |
|
||
| --- | --- |
|
||
| **Multi-provider** | Kimi / Anthropic / OpenAI / OpenAI Responses / Google GenAI / Vertex AI |
|
||
| **Multi-agent** | Primary target is Kimi Code; Pi code is preserved but hidden from the UI |
|
||
| **Icon system** | 100+ first-party icons + initial-letter fallback; picker grouped by brands / inference |
|
||
| **Quick switch** | Added/activated providers move to the top of the list; switching only changes `default_model` and never drops other providers |
|
||
| **Connectivity test** | Real `base_url` latency, coloured bubble (green / orange / red), auto-dismiss in 6 seconds |
|
||
| **Duplicate provider** | Deep-copy a provider + all its models; key auto-suffixed to `xxx-copy` |
|
||
| **Iconified actions** | Activate / Edit / Duplicate / Test Connectivity / Delete via lucide-react |
|
||
| **Model mapping** | Alias (`"provider/model"`) ↔ real model ID, with display name, context size, 1M-context flag, and capabilities |
|
||
| **Auto context size** | On model fetch: **API response > models.dev ref > regex fallback** — three-tier priority |
|
||
| **Auto capabilities** | `image_in / video_in / tool_use` all derived from models.dev; UI only exposes `thinking` as a manual toggle |
|
||
| **Global settings** | Full `[thinking]` table (enabled / effort / keep); Kimi Code only |
|
||
| **Raw JSON editing** | Power users can hand-edit the full config; unknown fields pass through `raw_other` and never get dropped |
|
||
| **i18n / Theme** | Simplified Chinese / English; dark / light / follow-system; persisted |
|
||
| **Auto backup** | Before writing `config.toml`, backup with timestamp-based names kept 7 days |
|
||
| **Shortcuts** | `Ctrl+S` save, `Ctrl+R` reload, `Ctrl+O` open config dir |
|
||
| **Usage dashboard** | 8 KPIs, per-model stacked daily trend, full-year heatmap, paginated recent requests, double-click bars for per-model breakdown modal |
|
||
| **Session manager** | Per-workspace browsing, archive/unarchive, bulk delete; streaming line-by-line preview (20MB cap + 500-char collapse) |
|
||
| **Update check** | Auto-check on launch + every 8h periodic + manual; download progress bar; guided install after download |
|
||
| **Unsaved-changes prompt** | Native `beforeunload` warning + `*` prefix in title bar |
|
||
| **Window / tray** | Minimize keeps the taskbar button; close X hides to tray; tray left-click always shows + focuses |
|
||
|
||
## Screenshots
|
||
|
||
**Provider list** (light theme)
|
||
|
||

|
||
|
||
Active provider, default model, latency bubble, model count, and brand icons at a glance. Quick switch, copy, test connectivity, open website, edit, delete.
|
||
|
||
**Edit provider — basic info**
|
||
|
||

|
||
|
||
Provider name, notes, official URL, managed-provider toggle, API format, API key, and base URL.
|
||
|
||
**Edit provider — model mapping**
|
||
|
||

|
||
|
||
A single table for all model mappings: display name, real model ID, context length, 1M-context flag, capability (thinking only), default toggle, delete.
|
||
|
||
**Usage dashboard**
|
||
|
||

|
||
|
||
8 KPIs (requests, non-cached input, output, cache read / write / hit, total tokens, estimated cost) + full-year heatmap + per-model stacked daily trend (bottom-aligned) + per-model usage table + paginated recent requests.
|
||
|
||
**Session manager**
|
||
|
||

|
||
|
||
Per-workspace Kimi Code session browsing, active / archived / all filters; streaming line-by-line preview (20MB cap, 500-char collapse); archive/unarchive/bulk delete.
|
||
|
||
## Architecture Overview
|
||
|
||
```
|
||
┌────────────────────────────────────────────────────────────────────────┐
|
||
│ Kimi Switch (Tauri v2) │
|
||
│ │
|
||
│ ┌──────────────────────────┐ ┌──────────────────────────────┐ │
|
||
│ │ React Frontend (TS) │ │ Rust Backend (lib.rs) │ │
|
||
│ │ │ │ │ │
|
||
│ │ src/App.tsx │ │ src-tauri/src/ │ │
|
||
│ │ src/components/ │◄──►│ ├── lib.rs │ │
|
||
│ │ ProviderList │ │ ├── main.rs │ │
|
||
│ │ ProviderEdit │ │ ├── commands.rs │ │
|
||
│ │ AgentSettingsPanel │ │ ├── db.rs │ │
|
||
│ │ SettingsModal │ │ ├── kimi_code_io.rs │ │
|
||
│ │ ProviderIcon / │ │ ├── pi_io.rs (legacy) │ │
|
||
│ │ IconPicker │ │ ├── config_io.rs │ │
|
||
│ │ dashboard/ │ │ ├── models.rs │ │
|
||
│ │ sessions/ │ │ ├── validators.rs │ │
|
||
│ │ src/hooks/ │ │ ├── dashboard.rs │ │
|
||
│ │ useConfig / Dashboard│ │ └── profile_manager.rs │ │
|
||
│ │ / Sessions / Theme │ │ │ │
|
||
│ │ / UpdateCheck │ │ │ │
|
||
│ │ src/lib/ │ │ │ │
|
||
│ │ src/icons/ │ │ │ │
|
||
│ │ src/i18n/{zh,en}.ts │ │ │ │
|
||
│ │ src/types/{...} │ │ │ │
|
||
│ └──────────────────────────┘ └──────────────────────────────┘ │
|
||
│ │ │ │
|
||
└──────────────────┼──────────────────────────────────┼──────────────────┘
|
||
│ │
|
||
▼ ▼
|
||
┌──────────────────────┐ ┌──────────────────────────┐
|
||
│ SQLite │ │ Agent native configs │
|
||
│ ~/.kimi-switch/ │ │ ├─ ~/.kimi-code/ │
|
||
│ kimi-switch.db │ │ │ └─ config.toml │
|
||
│ (metadata + fallback)│ │ └─ ~/.pi/agent/ │
|
||
│ + localStorage │ │ ├─ models.json │
|
||
│ (theme / lang / │ │ └─ settings.json │
|
||
│ update-check) │ │ │
|
||
└──────────────────────┘ └──────────────────────────┘
|
||
▲
|
||
│
|
||
┌──────────────────────────────┐
|
||
│ models.dev snapshot (FE) │
|
||
│ src/lib/models-dev.json │
|
||
│ + scripts/fetch-models- │
|
||
│ dev.mjs (optional refresh) │
|
||
└──────────────────────────────┘
|
||
```
|
||
|
||
**Key design points**:
|
||
|
||
- **`config.toml` is the authoritative source for Kimi Code**: all providers and models are always written in full; `default_model` selects the active one (matching the CLI's native `/provider` behaviour). Switching only changes `default_model`; newly added providers are auto-promoted to the top of the list and never get overwritten
|
||
- **SQLite holds Kimi Switch-private metadata only**: notes, official URLs, per-agent remembered default model (the `settings` table), ordering. Theme / language / last-update-check live in frontend `localStorage` (WebView2), not under `~/.kimi-switch`. It acts as a fallback when `config.toml` is incomplete
|
||
- **`raw_other` passes unknown fields through untouched**, including `[oauth]` blocks — round-trips never drop fields
|
||
- **models.dev snapshot**: derived from `https://models.dev/api.json`, cached to a local JSON; `capabilitiesFromRef` derives `thinking / image_in / video_in / tool_use`, `getModelRef` derives `max_context_size / display_name`
|
||
- **Override env vars**: `KIMI_CODE_HOME` / `PI_CODING_AGENT_DIR` override the Kimi Code / Pi dirs; Kimi Switch's own data dir is fixed at `~/.kimi-switch` (no env override yet). See [Data Storage Locations](#data-storage-locations)
|
||
|
||
## Feature Details
|
||
|
||
### Provider priority & switching
|
||
|
||
- **Auto-promote to top on add/activate**: when you add or switch a provider, it moves to the first position in `db.providers`; the UI renders the freshest order immediately
|
||
- **Switching only changes `default_model`**: all providers are written to `config.toml`, only the switched one becomes `default_model` — consistent with Kimi Code CLI's `/provider`
|
||
- **Never overwrites**: providers added/edited/deleted via the CLI's `/provider` are correctly reflected on load (config.toml wins), and fully persisted on next save
|
||
|
||
### Icon system
|
||
|
||
- Library adapted from cc-switch (`src/icons/extracted/`, 100+ first-party brand icons)
|
||
- Providers without an exact match get a deterministic **initial-letter placeholder** (e.g. `kimi-code` → `K`, `deepseek-v4` → `D`)
|
||
- `IconPicker` has brands / inference groups; the chosen icon is saved to `provider.icon`
|
||
|
||
### Connectivity test
|
||
|
||
- Backend `test_connectivity` command: GET `provider.base_url`; any HTTP response = reachable
|
||
- Returns `{ ok, latency_ms, status_code, error }`
|
||
- Frontend renders a **coloured bubble** (green / orange / red + ms) inline; auto-dismisses in 6 seconds
|
||
- The bubble sits before the "active / switch" button so it doesn't block the sight
|
||
|
||
### Duplicate provider
|
||
|
||
- Click the duplicate icon → deep-copy the provider + all its models
|
||
- `provider.name` gets a `-copy` suffix; model keys auto-suffix to `xxx-copy`
|
||
- Immediately persisted to SQLite + `config.toml`; toast confirmation
|
||
|
||
### Auto context size & capabilities
|
||
|
||
- On fetch, `max_context_size` priority: **API response > models.dev ref > regex fallback**
|
||
- models.dev ref → `capabilities = ["thinking","image_in","video_in","tool_use"]` (filtered by truthy fields)
|
||
- UI exposes **only the `thinking` checkbox**. Other capabilities are still auto-written but not manually editable — this matches Kimi Code's semantics: capabilities can only be added, never removed
|
||
- `always_thinking` can only be set manually (models.dev can't derive it). The UI hides it; edit `config.toml` directly when needed
|
||
|
||
### Capability vs thinking switch
|
||
|
||
- **Model capability** (`capabilities`) = "can it": declares whether the model supports thinking. Without `thinking`, the global switch has no effect on this model
|
||
- **Global `[thinking]`** (settings panel) = "do we want": new sessions default on/off, effort level (low/medium/high/max), and whether to keep thinking content
|
||
- `always_thinking` forces thinking on, ignoring the global switch
|
||
- Global settings apply to Kimi Code only
|
||
|
||
### Usage dashboard
|
||
|
||
- 8 KPIs, per-model stacked daily trend (**bottom-aligned layout**), full-year heatmap (5-level token colouring), paginated recent requests (30/page)
|
||
- Double-click a daily bar → `DailyDetailModal` with per-model breakdown
|
||
- Data source: `src-tauri/src/dashboard.rs` + `src/hooks/useDashboard.ts`
|
||
|
||
### Session manager
|
||
|
||
- Per-workspace Kimi Code session browsing, active / archived / all filters
|
||
- Streaming line-by-line preview (20MB cap, 500-char collapse with expand)
|
||
- Archive / unarchive / bulk delete
|
||
- Earlier "instant crash" issues fixed via streaming reads + size limits
|
||
|
||
### Settings modal
|
||
|
||
- **Theme**: dark / light / follow-system (`useTheme`, persisted to frontend `localStorage`)
|
||
- **Language**: Simplified Chinese / English
|
||
- **Version**: current version + last-checked timestamp
|
||
- **Update check**: launch auto + every 8h periodic + manual; download with progress bar; guided install after completion
|
||
|
||
### Window & tray
|
||
|
||
- **Minimize**: keeps the taskbar button (no longer hijacked to tray)
|
||
- **Close (X)**: `prevent_close` + `hide` → hides to tray instead of quitting
|
||
- **Tray menu**: Show / Quit
|
||
- **Tray left-click**: always `show + unminimize + focus` (no toggle hide)
|
||
- **Second launch**: `single_instance` plugin catches it, brings window to front and focuses
|
||
|
||
## Supported Provider Types
|
||
|
||
| Type | Identifier | Default base_url | Model discovery | Credentials |
|
||
| --- | --- | --- | --- | --- |
|
||
| Kimi | `kimi` | `https://api.openai.com/v1` | ✅ OpenAI protocol | `KIMI_API_KEY` or `env.KIMI_API_KEY` |
|
||
| Anthropic | `anthropic` | — | ✅ `/v1/models` | `ANTHROPIC_API_KEY` or `env` |
|
||
| OpenAI | `openai` | `https://api.openai.com/v1` | ✅ `/models` | `OPENAI_API_KEY` or `env` |
|
||
| OpenAI Responses | `openai_responses` | `https://api.openai.com/v1` | ✅ `/models` | `OPENAI_API_KEY` or `env` |
|
||
| Google GenAI | `google-genai` | `https://generativelanguage.googleapis.com` | ✅ `/v1beta/models` | `GOOGLE_API_KEY` or `env` |
|
||
| Vertex AI | `vertexai` | — | ⚠️ Not yet implemented | `VERTEXAI_API_KEY` + `GOOGLE_CLOUD_PROJECT` + `GOOGLE_CLOUD_LOCATION` |
|
||
|
||
Credential precedence: `api_key` field > same-named key in `env` table.
|
||
|
||
## Data Storage Locations
|
||
|
||
| File | Purpose | Backup |
|
||
| --- | --- | --- |
|
||
| `%USERPROFILE%\.kimi-switch\kimi-switch.db` | Kimi Switch's own SQLite — metadata (notes / official URLs / remembered default model + ordering) + fallback | — |
|
||
| `%USERPROFILE%\.kimi-code\config.toml` | Kimi Code CLI TOML config (**authoritative source, written on switch/save**) | `backups/config.toml.bak.{YYYYMMDD_HHMMSS}` next to it, kept 7 days |
|
||
| `%USERPROFILE%\.pi\agent\models.json` | Pi provider + model config (**written on switch**) | `backups/models.json.bak.{YYYYMMDD_HHMMSS}` next to it, kept 7 days |
|
||
| `%USERPROFILE%\.pi\agent\settings.json` | Pi default provider/model (**written on switch**) | `backups/settings.json.bak.{YYYYMMDD_HHMMSS}` next to it, kept 7 days |
|
||
| WebView2 `localStorage` | Frontend state: `kimi-switch-theme` / `kimi-switch-lang` / `kimi-switch-last-update-check` / `kimi-switch-agent` / `kimi-switch-dashboard-range` (theme / language / last-update-check / last-selected agent / dashboard range) | — |
|
||
| `src/lib/models-dev.json` | models.dev `api.json` snapshot (bundled with the frontend) | — |
|
||
|
||
Environment-variable overrides:
|
||
|
||
- `KIMI_CODE_HOME` overrides the Kimi Code config dir (default `~/.kimi-code`)
|
||
- `PI_CODING_AGENT_DIR` overrides the Pi agent config dir (default `~/.pi/agent`)
|
||
- Kimi Switch's own data dir is fixed at `~/.kimi-switch` (**no env override yet**)
|
||
|
||
## Getting Started
|
||
|
||
### Prerequisites
|
||
|
||
| Tool | Version | Purpose |
|
||
| --- | --- | --- |
|
||
| Node.js | ≥ 18 | Frontend build |
|
||
| Rust | Latest stable (edition 2021) | Tauri backend compilation |
|
||
| WebView2 Runtime | Bundled with Windows 10/11 | Tauri v2 runtime |
|
||
| Microsoft C++ Build Tools | Latest | Rust compile dependency |
|
||
| WiX Toolset 3.14 | `src-tauri/wix314-binaries/` | MSI bundling (auto-downloaded on first build) |
|
||
|
||
### Install
|
||
|
||
```bash
|
||
npm install
|
||
```
|
||
|
||
### Dev mode (hot reload)
|
||
|
||
```bash
|
||
npm run tauri-dev
|
||
```
|
||
|
||
Starts both the Vite dev server (port 1420) and the Tauri window. Frontend edits hot-reload; Rust edits trigger a recompile.
|
||
|
||
### Frontend-only dev (no Tauri window)
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
Good for pure UI debugging.
|
||
|
||
## Development Guide
|
||
|
||
### Project structure
|
||
|
||
```
|
||
.
|
||
├── src/ # React frontend
|
||
│ ├── App.tsx # Root component routing provider list / edit / dashboard / sessions
|
||
│ ├── main.tsx # React entry + ErrorBoundary + I18nProvider
|
||
│ ├── components/
|
||
│ │ ├── ProviderList.tsx # Provider list + switch / duplicate / test / edit / delete
|
||
│ │ ├── ProviderEdit.tsx # Edit provider + model mapping + raw JSON + capabilities
|
||
│ │ ├── AgentSettingsPanel.tsx # Kimi Code global settings (thinking / loop / permissions / hooks)
|
||
│ │ ├── SettingsModal.tsx # Settings modal (theme / language / version / update check)
|
||
│ │ ├── ProviderIcon.tsx # Provider brand icons (with initial-letter fallback)
|
||
│ │ ├── IconPicker.tsx # Icon picker (brands / inference groups)
|
||
│ │ ├── dashboard/ # Usage dashboard
|
||
│ │ │ ├── DashboardPage.tsx
|
||
│ │ │ ├── DailyBars.tsx
|
||
│ │ │ ├── DailyDetailModal.tsx
|
||
│ │ │ └── Heatmap.tsx
|
||
│ │ └── sessions/ # Session manager
|
||
│ │ └── SessionsPage.tsx
|
||
│ ├── hooks/
|
||
│ │ ├── useConfig.ts # Config load/save
|
||
│ │ ├── useDashboard.ts # Dashboard data
|
||
│ │ ├── useSessions.ts # Session data
|
||
│ │ ├── useTheme.ts # Theme switch
|
||
│ │ └── useUpdateCheck.ts # Update check + download
|
||
│ ├── lib/
|
||
│ │ ├── agent-settings.ts # AgentSettings parse/serialize
|
||
│ │ ├── model-defaults.ts # Default model context sizes
|
||
│ │ ├── models-dev.ts # models.dev snapshot lookup + capability mapping
|
||
│ │ ├── models-dev.json # Bundled snapshot
|
||
│ │ └── dashboard-format.ts # Dashboard formatting
|
||
│ ├── icons/
|
||
│ │ ├── brands.ts # Brand icon entry
|
||
│ │ ├── inference.ts # Inference-service icons
|
||
│ │ └── extracted/ # Icon library adapted from cc-switch
|
||
│ │ ├── index.ts
|
||
│ │ └── metadata.ts
|
||
│ ├── types/
|
||
│ │ ├── index.ts # Provider / Model / Config
|
||
│ │ ├── dashboard.ts
|
||
│ │ ├── sessions.ts
|
||
│ │ └── icon.ts
|
||
│ ├── i18n/
|
||
│ │ ├── zh.ts # Chinese translations (source)
|
||
│ │ ├── en.ts # English translations
|
||
│ │ └── index.tsx # useTranslation hook + Provider
|
||
│ └── index.css # Tailwind entry
|
||
│
|
||
├── src-tauri/ # Rust backend
|
||
│ ├── src/
|
||
│ │ ├── lib.rs # Tauri Builder + tray + window events + invoke_handler
|
||
│ │ ├── main.rs # Binary entry
|
||
│ │ ├── commands.rs # ~14 Tauri commands
|
||
│ │ ├── db.rs # SQLite persistence
|
||
│ │ ├── kimi_code_io.rs # ~/.kimi-code/config.toml read/write
|
||
│ │ ├── pi_io.rs # ~/.pi/agent/*.json read/write (preserved)
|
||
│ │ ├── config_io.rs # File backup utilities
|
||
│ │ ├── models.rs # Config / Provider / Model data structures
|
||
│ │ ├── profile_manager.rs # Multi-profile management (stub)
|
||
│ │ ├── validators.rs # Config validation
|
||
│ │ └── dashboard.rs # Session / usage data aggregation
|
||
│ ├── capabilities/ # Tauri permission declarations
|
||
│ ├── icons/ # App icons (script-generated)
|
||
│ └── tauri.conf.json # Tauri config (window / bundle / CSP)
|
||
│
|
||
├── scripts/
|
||
│ ├── fetch-models-dev.mjs # Refresh models-dev.json snapshot
|
||
│ └── generate-icons.py # Generate all icon sizes from SVG
|
||
├── public/kimi.svg # App icon source (blue-purple gradient π)
|
||
└── docs/
|
||
├── screenshots/ # Screenshots referenced by the README
|
||
└── superpowers/ # Design specs & implementation plans
|
||
```
|
||
|
||
### Tauri commands (frontend ↔ backend)
|
||
|
||
| Command | Description |
|
||
| --- | --- |
|
||
| `load_agent_config_command(agent)` | Load config: Kimi Code reads `config.toml` as authoritative + SQLite metadata; Pi reads SQLite first |
|
||
| `save_agent_config_command(agent, config)` | Save to SQLite; for Kimi Code also writes `config.toml` |
|
||
| `activate_agent_config_command(agent)` | Write to the agent's native config (Kimi Code writes all providers — `default_model` picks the active one; Pi writes only the active provider) |
|
||
| `open_agent_config_dir(agent)` | Open the agent's config dir in the system file manager |
|
||
| `get_app_version()` | Return the `Cargo.toml` version |
|
||
| `list_provider_models(provider)` | Fetch the model list from the provider API (async, paginated) |
|
||
| `test_connectivity(provider)` | GET `base_url` connectivity test, returns `{ ok, latency_ms, status_code, error }` |
|
||
| `get_app_setting(key)` | Read an app setting (theme / language / last-update-check) |
|
||
| `set_app_setting(key, value)` | Write an app setting |
|
||
| `check_for_update()` | Check GitHub releases; returns version + asset URL |
|
||
| `download_update(url, path)` | Stream-download the update; emits `download-progress` / `download-complete` events |
|
||
| `open_installer(path)` | Open the downloaded installer via the system shell |
|
||
| `dashboard::get_paths()` / `get_prices()` / `get_summary()` / `list_sessions()` / `archive_session()` / `unarchive_session()` / `delete_session()` / `delete_workspace()` / `get_session_preview()` | Dashboard & session commands |
|
||
| `debug_log(message)` | Forward frontend logs to stderr (dev use) |
|
||
|
||
### Adding a new provider type
|
||
|
||
1. Add a new variant to the `ProviderType` enum in `src-tauri/src/models.rs`
|
||
2. Add a default in `default_base_url()`
|
||
3. Add a dispatch arm in `commands.rs::list_provider_models`
|
||
4. Add a mapping in `kimi_code_io.rs::provider_type_for_kimi_type`
|
||
5. Add an option to the API-format dropdown in `src/components/ProviderEdit.tsx`
|
||
6. Add new i18n keys in `src/i18n/{zh,en}.ts`
|
||
|
||
### Adding a new Tauri command
|
||
|
||
1. Add a `#[tauri::command]` in `src-tauri/src/commands.rs`
|
||
2. Register it in `tauri::generate_handler![...]` in `src-tauri/src/lib.rs`
|
||
3. Call it from the frontend with `import { invoke } from "@tauri-apps/api/core"`
|
||
4. Add a permission in `src-tauri/capabilities/default.json` (if filesystem/network is needed)
|
||
|
||
### Adding a new model capability
|
||
|
||
1. Add a new key to `KNOWN_CAPABILITIES` in `src/components/ProviderEdit.tsx`
|
||
2. Add an i18n mapping in `CAPABILITY_LABELS`
|
||
3. Add translations in `src/i18n/{zh,en}.ts`
|
||
4. Add derivation in `capabilitiesFromRef` in `src/lib/models-dev.ts` (if it can be derived from models.dev)
|
||
|
||
## Keyboard Shortcuts
|
||
|
||
| Shortcut | Action |
|
||
| --- | --- |
|
||
| `Ctrl + S` | Save current changes to SQLite + `config.toml` (Kimi Code) |
|
||
| `Ctrl + R` | Reload config (prompts if unsaved) |
|
||
| `Ctrl + O` | Open the current agent's config dir |
|
||
|
||
## Internationalization
|
||
|
||
- Sources: `src/i18n/zh.ts` (source) + `src/i18n/en.ts` (target)
|
||
- When adding a key, **add it to `zh.ts` first** — the `Record<TranslationKey, string>` type in `en.ts` will flag missing entries at compile time
|
||
- `useTranslation` hook exposes `{ t, lang, setLang }`
|
||
- Runtime switch is provided by `SettingsModal`; persisted to frontend `localStorage` (`kimi-switch-lang`)
|
||
|
||
## Testing
|
||
|
||
### Rust unit tests
|
||
|
||
```bash
|
||
cd src-tauri
|
||
cargo test
|
||
```
|
||
|
||
Currently covered:
|
||
|
||
- `kimi_code_io::tests` — TOML import/export round-trips
|
||
- `pi_io::tests` — JSON round-trips, including advanced fields (headers / compat / cost / extra)
|
||
- `validators::tests` — Config validation
|
||
- `dashboard::tests` — Usage aggregation and timezone handling
|
||
|
||
### Frontend
|
||
|
||
No automated tests yet. Suggested manual checklist:
|
||
|
||
- [ ] Default model restores correctly after switching providers
|
||
- [ ] Newly added providers auto-promote to the top of the list
|
||
- [ ] Duplicate provider generates non-conflicting keys
|
||
- [ ] Connectivity test bubble auto-dismisses after 6 seconds
|
||
- [ ] Close X hides to tray; minimize keeps taskbar button
|
||
- [ ] Theme switch (dark / light / follow-system) takes effect immediately
|
||
- [ ] Language switch updates UI text in place
|
||
- [ ] Update check → download → guided install
|
||
- [ ] `max_context_size` auto-fills on model fetch
|
||
- [ ] New default model takes effect after `/reload` + `/model` (or after `/exit` and restart)
|
||
|
||
## Build & Release
|
||
|
||
```bash
|
||
npm run tauri-build
|
||
```
|
||
|
||
Output:
|
||
|
||
```
|
||
src-tauri/target/release/bundle/msi/Kimi Switch_<version>_x64_en-US.msi
|
||
```
|
||
|
||
A Windows installer (MSI) with the WebView2 bootstrapper embedded for auto-download. `nsis` is disabled; only MSI is produced.
|
||
|
||
### First build
|
||
|
||
The first run downloads:
|
||
|
||
- WiX Toolset 3.14 binaries → `src-tauri/wix314-binaries/`
|
||
- WebView2 bootstrapper → embedded into the MSI
|
||
|
||
### Common build issues
|
||
|
||
- **`os error 5`** (WiX light step): kill the process first with `taskkill //F //IM kimiswitch.exe`, then retry
|
||
- **prebuild times out pulling models.dev**: expected; the local snapshot keeps the build going
|
||
|
||
## Release History
|
||
|
||
### v0.6.0 (latest)
|
||
|
||
- **15 mainstream provider presets**: Kimi Coding / Moonshot / Anthropic / DeepSeek / Zhipu GLM / z.ai / Alibaba Bailian / MiniMax / StepFun / SiliconFlow / Novita / OpenRouter / OpenAI / Google AI Studio / Volcengine Ark — one-click form fill via `PresetPickerModal`
|
||
- **Provider balance / plan usage query** (per-card `UsageFooter`):
|
||
- Balance: DeepSeek / SiliconFlow / OpenRouter / StepFun / Novita
|
||
- Plan: Kimi For Coding / Zhipu GLM / MiniMax
|
||
- 5-min stale TTL + `force_refresh` + concurrency ≤ 3
|
||
- **Rust `services/` module** (`balance` / `coding_plan` / `usage_types`), adapted from cc-switch (MIT, © Jason Young)
|
||
- `query_provider_usage` command: loads API key from config in Rust, never serialized over IPC
|
||
- `usageKinds` persisted in SQLite `settings` (JSON array), merged back into config on load, omitted from `config.toml` export
|
||
- `detect_provider` heuristic: existing users automatically gain balance/plan support after upgrade
|
||
- Save-time validation: incomplete providers (missing `api_key` / `base_url` / models) trigger a confirm dialog listing the reasons; uncommitted `add` is silently dropped on back
|
||
- Fixes: `handleDuplicateProvider` `alias.slice` bug; `handleSelectPreset` no longer auto-saves; `handleSwitchProvider` auto-refresh rollback when validation is cancelled
|
||
- New docs: [`docs/PROPOSAL-presets-and-usage.md`](./docs/PROPOSAL-presets-and-usage.md) (v0.4-draft implementation), [`docs/VERIFICATION-CHECKLIST.md`](./docs/VERIFICATION-CHECKLIST.md) (70+ manual checks)
|
||
|
||
### Historical versions
|
||
|
||
Versions v0.5.x and earlier (v0.5.1 / v0.5.0 / v0.4.1 / v0.4.0 / v0.3.0) live on the [git.codingplan.site repository](https://git.codingplan.site/admin/KimiCodeSwitch/releases). The GitHub repo is the release channel from v0.6.0 onward.
|
||
|
||
## FAQ
|
||
|
||
**Q: Switching providers didn't take effect in Kimi Code?**
|
||
A: Two steps are required:
|
||
1. Run `/reload` inside the Kimi Code session so the CLI re-reads `~/.kimi-code/config.toml` (this refreshes the model **dropdown list**);
|
||
2. **Then run `/model` to pick the new default**, or simply `/exit` and restart the session.
|
||
|
||
Running `/reload` alone **does not** apply the new `default_model` to the current session — this is a known Kimi Code behaviour, see [Known Limitations & Next Steps](#known-limitations--next-steps) below. The app surfaces both steps in its UI.
|
||
|
||
**Q: Does switching overwrite other providers?**
|
||
A: No. Kimi Code's `config.toml` is always written with all providers, only `default_model` decides which one is active. This matches the CLI's native `/provider` behaviour.
|
||
|
||
**Q: Where do new / activated providers go?**
|
||
A: They auto-promote to the top of the list; the UI reflects it immediately.
|
||
|
||
**Q: Why does the capability editor only show "thinking"?**
|
||
A: Kimi Code's `capabilities` field can only be added to, not removed. models.dev already auto-derives the rest; exposing more manually would just invite mistakes. Edit `config.toml` directly when you need to set `always_thinking` or other special values.
|
||
|
||
**Q: I edited the config but closed the window without saving?**
|
||
A: A native `beforeunload` prompt appears before closing, and the title bar shows a `*` prefix.
|
||
|
||
**Q: How do I back up / migrate my config?**
|
||
A: For Kimi Code, `config.toml` itself is the authoritative full config — back it up directly. SQLite holds notes / official URLs / ordering, back it up too if you need that. Theme / language / last-update-check live in frontend `localStorage` (WebView2), not a standalone file, so they usually don't need separate handling on migration.
|
||
|
||
**Q: Why can't Vertex AI fetch the model list?**
|
||
A: Vertex requires GCP project / location credentials. The current implementation leaves a TODO pending GCP SDK integration.
|
||
|
||
**Q: macOS / Linux support?**
|
||
A: The code doesn't depend on Windows-only APIs, but `tauri.conf.json` only targets `msi` for bundling. In theory, changing `bundle.targets` to `["app", "dmg"]` etc. would enable cross-platform builds, but this is unverified.
|
||
|
||
**Q: How do I change the theme / language?**
|
||
A: Top-right gear → Settings modal → Theme / Language. Saved to frontend `localStorage` (WebView2), persists across restarts.
|
||
|
||
**Q: I closed the window — how do I get it back?**
|
||
A: The close X hides to the tray. Click the tray icon (menu bar / system tray) to bring it back; clicking the taskbar icon toggles minimize/restore normally.
|
||
|
||
**Q: How is the update check triggered?**
|
||
A: It silently checks once on launch, then automatically every 8 hours (silent failure with no network, no error popup). You can also trigger it manually: Settings modal → Version → Update check. Downloads have a progress bar; once done, an "Open installer" button appears.
|
||
|
||
## Known Limitations & Next Steps
|
||
|
||
### `/reload` does not switch the active session's default model (Kimi Code upstream limitation)
|
||
|
||
**Symptom**: After switching a provider in Kimi Switch, `default_model` at the top level of `config.toml` is correctly updated. Back in Kimi Code CLI you run `/reload`: the model **dropdown** now lists the new default, but the **current session still uses the old model** (status-bar model and the actual outgoing requests haven't changed).
|
||
|
||
**Root cause** (verified against the Kimi Code source — **not** a Kimi Switch bug):
|
||
|
||
- The `/reload` command (`apps/kimi-code/src/tui/commands/reload.ts`) refreshes `availableModels / availableProviders` but **never** re-applies `config.defaultModel` to the active session's agent.
|
||
- The session's current model (`agent.config.modelAlias`) comes from `options.model ?? config.defaultModel` at session-create time (`packages/agent-core/src/rpc/core-impl.ts:438-440`) and is persisted to the session log via `records.logRecord`. `Agent.resume()` then calls `records.replay()`, which **replays those records** — so the model snaps back to "what was last picked", not to `config.defaultModel`.
|
||
- The unit test (`apps/kimi-code/test/tui/commands/reload.test.ts:87-89`) only asserts "the model list refreshed"; there is **no** assertion that "the active session switched to the new default" — because the implementation never does that step.
|
||
- A repo-wide search for `FOLLOW_DEFAULT / reloadDefault / KIMI_CODE_RELOAD` yields **zero** hits, so Kimi Code has **no** "follow default on reload" toggle today.
|
||
|
||
**Workaround (works today)**:
|
||
|
||
1. After `/reload`, run `/model` and pick the new default manually; or
|
||
2. `/exit` and restart the session (the `createSession` path re-applies `config.defaultModel` to the fresh session).
|
||
|
||
**Suggested upstream fix for Kimi Code**:
|
||
|
||
- File: `apps/kimi-code/src/tui/commands/reload.ts`, in `handleReloadCommand`.
|
||
- Spot: right after `applyRuntimeConfig(host, config)`, add a sync of `config.defaultModel` to the active session's agent, e.g.:
|
||
```ts
|
||
const newDefault = config.defaultModel;
|
||
const current = /* host.session's current agent modelAlias */;
|
||
if (newDefault && newDefault !== current) {
|
||
await host.session.mainAgent.config.update({ modelAlias: newDefault });
|
||
}
|
||
```
|
||
- Matching test: add an assertion in `reload.test.ts` that "after reload, the session's active model == new `defaultModel`" to guard against regressions.
|
||
- Optional enhancement: expose a session-level "follow default on reload" toggle, or auto-fall-back to `default_model` when the session's previous alias has been deleted.
|
||
|
||
> Note: this suggestion has **not** been filed upstream yet; it's recorded here for follow-up. Kimi Switch can only guarantee `config.toml` is written correctly — it cannot work around Kimi Code's own `/reload` semantics.
|
||
|
||
### Other next-step suggestions (by priority)
|
||
|
||
- **P1 — Model alias convention**: early bare-name or `-1/-2` suffixed aliases (e.g. `kimi-k3`, `glm-5-2-1`) have been bulk-renamed to the `provider/model` form; when adding a new provider, **force** this convention to prevent re-introducing suffixed fallbacks. Add a save-time lint.
|
||
- **P1 — Multi-dimensional usage trends**: the usage trend already supports two tabs ("model trend" / "provider×model trend"); a future third dimension (per-workspace, or switch the Y axis between tokens and cost) is worth considering.
|
||
- **P2 — Periodic update check**: currently launch + every 8h; consider making the cadence configurable (set period / disable in the settings modal).
|
||
- **P2 — Cross-platform**: only MSI is produced today, but the code has no Windows-only dependencies; once Tauri v2 macOS/Linux bundling is configured, it can be verified.
|
||
- **P3 — Stronger config validation**: `validators.rs` is fairly minimal today; worth adding: `base_url` validity, `env` vs `api_key` mutual-exclusivity, `oauth` block completeness.
|
||
|
||
## Security Notes
|
||
|
||
- API keys are stored in plaintext in local SQLite and agent native configs — **do not store them on shared computers**
|
||
- Do not commit `kimi-switch.db`, `config.toml`, or `models.json` to Git
|
||
- The app CSP is tightened (`default-src 'self'`), but WebView2 may still cache form content — log out when finished on public machines
|
||
|
||
---
|
||
|
||
## Credits
|
||
|
||
The usage dashboard and session manager are ported from [kimicode-dashboard](https://github.com/JochenYang/kimicode-dashboard) (MIT License, © JochenYang). The Rust backend (`src-tauri/src/dashboard.rs`), dashboard UI (`src/components/dashboard/`), and sessions page (`src/components/sessions/`) in this project are derived from that work. Many thanks to the original author.
|
||
|
||
The provider brand icon library (`src/icons/extracted/`) and the icon picker (`src/components/IconPicker.tsx`) are adapted from [cc-switch](https://github.com/farion1231/cc-switch) (MIT License, © Jason Young). Many thanks to the original author.
|
||
|
||
The provider presets structure (`src/config/providerPresets.ts`) and the balance/plan usage query implementation (`src-tauri/src/services/`) are likewise adapted from [cc-switch](https://github.com/farion1231/cc-switch) (MIT License, © Jason Young).
|
||
|
||
---
|
||
|
||
License: MIT, see [LICENSE](./LICENSE). Copyright (c) 2026 CodingPlan.site
|