# Behavior traces — farion1231/cc-switch

> Canonical page: https://codevetter.com/unpack/cc-switch/behavior-traces

# Behavior traces — farion1231/cc-switch

Scanned commit 09c5d39d8c3cf44b1bdfd0c6432c46495e546578 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Three flows dominate daily use: process startup (DB open, crash recovery, proxy restore, then the React shell), an exclusive provider switch (backfill then atomic live write, or a proxy hot-switch), and proxy takeover (backup live config, point the CLI at localhost, route through ProviderRouter). Deep-link import and usage-script execution are the two untrusted-input paths that still end in the same database and live-file writers.
- Startup, backend: main sets Linux WebKit vars; run() installs the panic hook; setup refreshes the app-config-dir Store override, starts the log plugin at ~/.cc-switch/logs/cc-switch.log (20 MiB, KeepSome 4), installs the rustls ring provider, opens or migrates cc-switch.db from legacy config.json, and if user_version is newer than the binary records kind db_version_too_new instead of applying DDL. — [src-tauri/src/main.rs#L4-34](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/main.rs#L4-L34) [src-tauri/src/lib.rs#L462-577](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L462-L577) [src-tauri/src/database/mod.rs#L169-183](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/database/mod.rs#L169-L183)
- Startup, after the DB is up: a background task checks has_any_live_backup and detect_takeover_in_live_configs; if either is set it calls proxy_service.recover_from_crash. It then scrubs leaked Gemini common-config credentials, initialize_common_config_snippets, restore_proxy_state_on_startup, runs periodic_backup_if_needed, and arms a 24-hour backup timer plus the 60-second session sync loop. Silent startup hides the main window and, on Windows, sets skip_taskbar. — [src-tauri/src/lib.rs#L1221-1365](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L1221-L1365)
- Startup, renderer: main.tsx installs global error handlers, listens for configLoadError, then bootstrap() invokes get_init_error. kind db_version_too_new renders DatabaseUpgrade and returns. Any other path/error shows a dialog and calls plugin-process exit(1). Otherwise it mounts QueryClientProvider, ThemeProvider, UpdateProvider, and App, then fires syncModelsDevPricingOnStartup. — [src/main.tsx#L28-155](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/main.tsx#L28-L155)
- Exclusive provider switch: UI calls providersApi.switch; switch_provider spawn_blocking calls ProviderService::switch; if not taken over, switch_normal backfills via read_live_settings and save_provider, writes the target with write_live helpers, syncs MCP when not in takeover, and returns SwitchResult.warnings (for example backfill_failed:<id>). The UI may then apply Claude plugin config when enableClaudePluginIntegration is on and refresh the tray. — [src/lib/api/providers.ts#L90-139](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/lib/api/providers.ts#L90-L139) [src-tauri/src/services/provider/mod.rs#L5804-5878](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/mod.rs#L5804-L5878) [src/hooks/useProviderActions.ts#L57-81](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/hooks/useProviderActions.ts#L57-L81) [src/hooks/useProviderActions.ts#L148-166](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/hooks/useProviderActions.ts#L148-L166)
- Proxy takeover switch: set_proxy_takeover_for_app enables takeover for one app. Later switch_provider sees the backup or live placeholder, refuses unsupported official targets, and calls hot_switch_provider_inner so the proxy's current provider map changes while live files stay pointed at the local listener. Stopping the process with stop_proxy_server errors if any takeover flag remains; stop_proxy_with_restore is the path that puts the original live files back. — [src-tauri/src/commands/proxy.rs#L20-72](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/proxy.rs#L20-L72) [src-tauri/src/services/provider/mod.rs#L5739-5797](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/mod.rs#L5739-L5797)
- Normal live persistence for Codex is write_codex_live_atomic to ~/.codex/config.toml and auth.json, plus an optional model-catalog sidecar that is never inlined into those files. Claude writes settings JSON through the shared atomic writer. Gemini writes .env and patches security.auth.selectedType in ~/.gemini/settings.json without dropping other keys. Grok writes ~/.grok/config.toml. — [src-tauri/src/codex_config.rs#L471-473](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/codex_config.rs#L471-L473) [src-tauri/src/codex_config.rs#L987-994](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/codex_config.rs#L987-L994) [src-tauri/src/services/provider/live.rs#L1747-1810](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/live.rs#L1747-L1810) [src-tauri/src/gemini_config.rs#L347-368](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/gemini_config.rs#L347-L368) [src-tauri/src/grok_config.rs#L25-33](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/grok_config.rs#L25-L33)
- Deep-link flow: OS or second-instance argv hits handle_deeplink_url; parse_deeplink_url fills DeepLinkImportRequest; the webview receives deeplink-import; the user confirms in DeepLinkImportDialog; import commands (import_from_deeplink, import_from_deeplink_unified, merge_deeplink_config) write the provider, MCP, prompt, or skill through the same services as the UI. usageEnabled must be explicitly true before a carried usage script is treated as enabled. — [src-tauri/src/lib.rs#L242-275](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L242-L275) [src-tauri/src/deeplink/mod.rs#L30-139](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/deeplink/mod.rs#L30-L139) [src/App.tsx#L92-93](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/App.tsx#L92-L93) [src-tauri/src/lib.rs#L1535-1539](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L1535-L1539)
- Usage query flow: the provider card calls queryProviderUsage or testUsageScript; execute_usage_script builds a sandboxed QuickJS runtime, evals user code to a request config, Rust issues the HTTP request, then the extractor function maps the response JSON. A 5-second interrupt handler aborts runaway scripts. — [src-tauri/src/usage_script.rs#L8-65](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/usage_script.rs#L8-L65) [src-tauri/src/usage_script.rs#L79-120](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/usage_script.rs#L79-L120) [src-tauri/src/lib.rs#L1451-1454](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L1451-L1454)
- Failover flow: an upstream failure is recorded on the per-provider CircuitBreaker inside ProviderRouter. When auto_failover_enabled is set, select_providers walks the failover queue and skips open circuits. FailoverSwitchManager dedupes concurrent promotions and emits UI plus tray updates. Codex official cards stay a single route even if failover was left on. — [src-tauri/src/proxy/provider_router.rs#L15-80](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/proxy/provider_router.rs#L15-L80) [src-tauri/src/proxy/circuit_breaker.rs#L13-49](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/proxy/circuit_breaker.rs#L13-L49) [src-tauri/src/proxy/failover_switch.rs#L15-40](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/proxy/failover_switch.rs#L15-L40)
- Tray switch: update_tray_menu rebuilds the menu from AppState via tray::create_tray_menu and set_menu on tray id TRAY_ID. Menu text follows the same locale order as the renderer (zh-TW, zh, ja, en, default zh). Provider-switched events from the backend are subscribed in providersApi.onSwitched. — [src-tauri/src/lib.rs#L312-331](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L312-L331) [src-tauri/src/tray.rs#L55-80](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/tray.rs#L55-L80) [src/lib/api/providers.ts#L133-139](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/lib/api/providers.ts#L133-L139)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
