Files
KimiCodeSwitch/README_EN.md
KimiSwitch Dev 0ce89b09d9 docs: add English README and cross-link both language versions
- New README_EN.md with full English documentation mirroring the Chinese README
- Add language switcher links (English | 中文) at the top of both files
2026-07-22 14:50:55 +08:00

16 KiB

Pi Switch

A Windows desktop LLM provider config manager that lets you switch between multiple LLM providers and models across the Kimi Code CLI and Pi agents.

English | 中文

Tauri React TypeScript Rust License


Table of Contents


What Is This

Pi Switch is a Windows desktop configuration tool built for LLM CLI users. It solves two pain points:

  1. Tedious multi-provider management: switching between Kimi / Anthropic / OpenAI / Google GenAI / self-hosted proxies requires repeatedly hand-editing TOML/JSON, which is error-prone.
  2. Fragmented multi-agent configs: developers using both Kimi Code CLI and Pi have to maintain two independent config formats, duplicating every change.

Pi Switch provides a unified GUI:

  • One unified interface to manage two separate agent configs (Kimi Code and Pi), switched via a top tab
  • One-click provider switching that writes the active provider into the target agent's native config
  • One-click model-list fetching (OpenAI / Anthropic / Google GenAI)
  • A /reload hint after switching so Kimi Code sessions take effect immediately

Key Features

Category Feature
Multi-agent Manage Kimi Code and Pi configs independently without interference, via a top tab
Multi-provider Kimi / Anthropic / OpenAI / OpenAI Responses / Google GenAI / Vertex AI
Model mapping Alias ↔ real model ID, with display name, context size, role (Sonnet/Opus/Fable/Haiku), and 1M-context declaration
One-click discovery Auto-fetch available model lists from the provider API
Managed providers Flag OAuth/managed providers to skip credential validation and preserve the oauth section in Kimi Code config
Env credentials Supports both the api_key field and env-table keys (e.g. OPENAI_API_KEY)
Global settings Thinking toggle/level, loop retries, background tasks, permission rules, lifecycle hooks (Kimi Code only)
Raw JSON editing Power users can hand-edit the full config JSON (unknown fields are preserved, never dropped)
i18n Simplified Chinese / English, switched at runtime
Auto backup Before writing the Kimi Code / Pi native configs, back up with timestamp-based names and keep the last 7 days (see src-tauri/src/config_io.rs)
Shortcuts Ctrl+S save, Ctrl+R reload, Ctrl+O open config dir
Validation (reserved) i18n error strings are defined (duplicate names, missing credentials, missing Vertex fields, etc.), but the backend validators.rs is a stub and not yet wired
Unsaved-changes prompt Detects unsaved edits before closing the window and prefixes the title bar with *

Architecture Overview

┌────────────────────────────────────────────────────────────────────┐
│                       Pi Switch (Tauri v2)                         │
│                                                                    │
│   ┌──────────────────────────┐    ┌──────────────────────────┐    │
│   │   React Frontend (TS)    │    │   Rust Backend (lib.rs)  │    │
│   │                          │    │                          │    │
│   │   src/App.tsx            │◄──►│   src-tauri/src/         │    │
│   │   src/components/        │ Tauri    ├── commands.rs    │    │
│   │     ProviderList         │  invoke  ├── db.rs          │    │
│   │     ProviderEdit         │          ├── kimi_code_io   │    │
│   │     AgentSettingsPanel   │          ├── pi_io.rs       │    │
│   │   src/hooks/useConfig    │          ├── config_io.rs   │    │
│   │   src/i18n/{zh,en}.ts    │          ├── validators.rs  │    │
│   │   src/types/index.ts     │          └── profile_manager│    │
│   └──────────────────────────┘    └──────────────────────────┘    │
│                  │                              │                  │
└──────────────────┼──────────────────────────────┼──────────────────┘
                   │                              │
                   ▼                              ▼
       ┌──────────────────────┐      ┌──────────────────────────┐
       │  SQLite              │      │  Agent native configs    │
       │  ~/.pi-switch/       │      │  ├─ ~/.kimi-code/        │
       │    pi-switch.db      │      │  │  └─ config.toml       │
       │                      │      │  └─ ~/.pi/agent/         │
       │  (Pi Switch internal)│      │     ├─ models.json      │
       └──────────────────────┘      │     └─ settings.json     │
                                     └──────────────────────────┘

Key design points:

  • Pi Switch keeps its own SQLite database for the full config (all providers + all models, including inactive ones)
  • Clicking "Switch to" writes only the active provider into the agent's native config; the others are not written
  • This way Kimi Code / Pi always see exactly one active provider and are never confused by managed/OAuth defaults
  • The raw_other field passes unknown keys through untouched, so round-trips never lose fields

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: the api_key field wins over the same-named key in the env table.

Data Storage Locations

File Purpose Backup
%USERPROFILE%\.pi-switch\pi-switch.db Pi Switch's own SQLite database holding the full config
%USERPROFILE%\.kimi-code\config.toml Kimi Code CLI's TOML config (written on switch) backups/config.toml.bak.{YYYYMMDD_HHMMSS} next to it, kept 7 days
%USERPROFILE%\.pi\agent\models.json Pi's provider+model config (written on switch) backups/models.json.bak.{YYYYMMDD_HHMMSS} next to it, kept 7 days
%USERPROFILE%\.pi\agent\settings.json Pi's default provider/model (written on switch) backups/settings.json.bak.{YYYYMMDD_HHMMSS} next to it, kept 7 days
localStorage[pi-switch-agent] Frontend remembers the last selected agent (kimi_code / pi)

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)

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

npm install

Dev mode (hot reload)

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)

npm run dev

Good for pure UI debugging.

Development Guide

Project structure

.
├── src/                          # React frontend
│   ├── App.tsx                   # Root component routing ProviderList/ProviderEdit
│   ├── main.tsx                  # React entry + ErrorBoundary + I18nProvider
│   ├── components/
│   │   ├── ProviderList.tsx      # Provider list + switch button
│   │   ├── ProviderEdit.tsx      # Edit provider + model mapping + raw JSON
│   │   └── AgentSettingsPanel.tsx# Global settings (thinking/loop/permissions/hooks)
│   ├── hooks/
│   │   └── useConfig.ts          # Config load/save hook
│   ├── lib/
│   │   ├── agent-settings.ts     # AgentSettings parse/serialize
│   │   └── model-defaults.ts     # Default model context sizes
│   ├── types/index.ts            # Provider/Model/Config type definitions
│   ├── i18n/
│   │   ├── zh.ts                 # Chinese translations (143 keys)
│   │   ├── en.ts                 # English translations
│   │   └── index.tsx             # useTranslation hook + Provider
│   └── index.css                 # Tailwind entry
│
├── src-tauri/                    # Rust backend
│   ├── src/
│   │   ├── lib.rs                # Tauri Builder + invoke_handler registration
│   │   ├── main.rs               # Binary entry
│   │   ├── commands.rs           # 7 Tauri commands
│   │   ├── db.rs                 # SQLite persistence
│   │   ├── kimi_code_io.rs       # ~/.kimi-code/config.toml read/write
│   │   ├── pi_io.rs              # ~/.pi/agent/*.json read/write
│   │   ├── config_io.rs          # File backup utilities
│   │   ├── models.rs             # Config/Provider/Model data structures
│   │   ├── profile_manager.rs    # Multi-profile management (stub)
│   │   └── validators.rs         # Config validation
│   ├── capabilities/             # Tauri permission declarations
│   ├── icons/                    # App icons (script-generated)
│   └── tauri.conf.json           # Tauri config (window/bundle/CSP)
│
├── scripts/generate-icons.py     # Generate all icon sizes from SVG
├── public/pi.svg                 # App icon source (blue-purple gradient π)
└── docs/superpowers/             # Design specs & implementation plans

Tauri commands (frontend ↔ backend)

Command Description
load_agent_config_command(agent) Load config: SQLite first, falling back to the agent's native config on first use
save_agent_config_command(agent, config) Save the full config to SQLite
activate_agent_config_command(agent) Write the active provider into the agent's native config
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 model list from the provider API (async)
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 mappings in kimi_code_io.rs::provider_type_for_kimi_type and pi_io.rs::provider_type_for_pi_api
  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 the tauri::generate_handler![...] list 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 access is needed)

Keyboard Shortcuts

Shortcut Action
Ctrl + S Save current changes to SQLite
Ctrl + R Reload config (prompts if unsaved)
Ctrl + O Open the current agent's config dir

Internationalization

  • Translation sources: src/i18n/zh.ts (source) and 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 any missing entry at compile time
  • Language is switched at runtime via the top-right dropdown and held in component state (not persisted to SQLite)

Testing

Rust unit tests

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)

Frontend

No automated tests yet. Suggested manual checklist:

  • Switching agents doesn't cross-contaminate configs
  • Deleting a provider also deletes its models
  • The default model restores correctly after switching providers
  • Renaming a provider updates models that reference it
  • Raw-JSON editing preserves raw_other fields

Build & Release

npm run tauri-build

Output:

  • src-tauri/target/release/bundle/msi/Pi Switch_0.1.0_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

FAQ

Q: Kimi Code didn't pick up the change after switching providers? A: Run /reload inside the Kimi Code session (the CLI only re-reads ~/.kimi-code/config.toml on reload). The app shows this hint in the UI.

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: Back up %USERPROFILE%\.pi-switch\pi-switch.db; it holds the full config (including inactive providers).

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.

Security Notes

  • API keys are stored in plaintext in the local SQLite database and agent native configs — do not store them on shared computers
  • Do not commit pi-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

  • Kimi Code CLI — one of the compatible agents
  • Tauri — the desktop app framework
  • Design specs in docs/superpowers/specs/, implementation plans in docs/superpowers/plans/

License: MIT, see LICENSE. Copyright (c) 2026 CodingPlan.site