CodeVetter · Repo Unpack · Extension points
farion1231/cc-switch
New coding tools plug in through AppType plus a live-config module and a frontend preset file. New proxy vendors plug in through ProviderAdapter and a route on the Axum router. New UI features plug in as a Tauri command in commands/, a line in invoke_handler, and a wrapper in src/lib/api. Deep links, MCP/Skill app flags, and the settings KV table are the other registries. Schema changes must bump SCHEMA_VERSION and add a migration.
- Adding a tool requires a new AppType variant, as_str, FromStr, all(), is_additive_mode or supports_local_proxy, and the matching frontend AppId in APP_IDS. MCP and Skills need a new bool on McpApps and SkillApps plus an enabled_* column. VisibleApps on both the Rust settings struct and the TypeScript default must be updated together.
- Live IO for each tool is a dedicated module: claude via config.rs, claude_desktop_config.rs, codex_config.rs, gemini_config.rs, grok_config.rs, opencode_config.rs, openclaw_config.rs, hermes_config.rs, mcode_config.rs, and pi_config/mod.rs. read_live_settings and the write path in services/provider/live.rs are the dispatch tables a new app must join.
- ProviderAdapter in proxy/providers/adapter.rs is the proxy plugin trait: name, extract_base_url, extract_auth, build_url, get_auth_headers, and optional transform_request/transform_response. Concrete adapters live under proxy/providers (claude, codex, gemini, copilot, xAI OAuth, streaming transforms). auth_header_value rejects CR/LF in credentials instead of panicking.
- New proxy endpoints are registered in ProxyServer::build_router. App-specific prefixes already used are /claude, /claude-desktop, /codex, and /grokbuild. A fifth proxied app would also need a proxy_config CHECK constraint change, a seed row, supports_local_proxy, and PROXY_APP_IDS.
- The command table is tauri::generate_handler! in lib.rs. Each command module is declared and star-exported from commands/mod.rs. Frontend call sites must use the Rust function name; several parameters are intentionally camelCase (addToLive, originalId, providerId) under allow(non_snake_case).
- Provider presets are plain TypeScript arrays in src/config/*ProviderPresets.ts, not a runtime plugin loader. Universal providers are a second registry: UniversalProviderPreset in universalProviderPresets.ts and the universal_providers JSON blob in the settings table, with sync_universal_provider pushing one record into Claude, Codex, and Gemini.
- Deep link resources are a string discriminant on DeepLinkImportRequest (provider, prompt, mcp, skill) parsed in deeplink/parser.rs and imported by per-resource modules. New resource types need a parser arm, an import function, and a frontend confirm dialog branch.
- Schema evolution is SCHEMA_VERSION in database/mod.rs, currently 19, with migrations in database/schema.rs. New databases get CREATE TABLE IF NOT EXISTS; existing databases run apply_schema_migrations only when the stored user_version is lower. A higher on-disk version aborts into the upgrade UI instead of writing DDL.
- i18n resources are four JSON files registered in src/i18n/index.ts. getInitialLanguage reads localStorage language, then navigator, with default zh. Tray locale mapping in tray.rs is documented to mirror that order. User-facing Rust errors use AppError::localized(key, zh, en).
- OMO is an OpenCode category pair (omo and omo-slim) handled inside switch_normal by OmoService::write_config_to_file and delete_config_file, not by the generic provider writer. A similar exclusive sidecar should follow that branch rather than is_additive_mode.
- Per-app config directory overrides are fields on AppSettings (claude_config_dir, codex_config_dir, gemini_config_dir, grok_config_dir, opencode_config_dir, openclaw_config_dir, hermes_config_dir, pi_config_dir) resolved by the matching get_*_dir helpers. The whole ~/.cc-switch directory can be moved via the Tauri Store override read in app_store::refresh_app_config_dir_override before the database opens.