CC Switch v3.8.0 持久化架构升级解析:从单一 config.json 到 SQLite + JSON 双层存储
CC Switch v3.8.0(2025-11-28 发布)是一次以「数据持久化层重构」为主线的重大架构升级版本:它把全部可同步数据从单一 config.json 迁移到 SQLite,将设备级状态留在 JSON,为后续云同步与本地代理功能打下地基。本文基于仓库内 v3.8.0 中文发布说明 展开,并结合 数据库模块、迁移引擎 与 备份实现 等源码,完整梳理这一版本的双层架构设计、自动迁移机制、关键 Bug 的根因与修复,以及日语支持、递归扫描 Skills、开机自启等全部功能细节,帮助开发者在升级部署时准确理解数据去向与潜在风险点。
版本概览
| 项目 | 内容 |
|---|---|
| 发布日期 | 2025-11-28 |
| 提交数量 | 自 v3.7.1 起 51 个提交 |
| 代码变更 | 207 个文件,+17,297 / -6,870 行(净增 +10,427 行) |
| 核心主题 | 持久化架构升级,为云同步奠定基础 |
按提交类型分布:fix 25 个、refactor 11 个、feat 9 个、test 1 个、其他 5 个;改动区域上前端源码 112 个文件、Rust 后端 63 个文件、测试文件 20 个文件、国际化文件 3 个文件。这是一个典型的「先修稳定性、再动存储层」的重构版本。
持久化架构升级:SQLite + JSON 双层设计
架构变更全景
v3.7.x 时代,CC Switch 的全部数据(供应商、MCP、提示词、设置等)都存放在一个 config.json 文件中。v3.8.0 将其拆分为两层:
v3.7.x (旧) v3.8.0 (新)
┌─────────────────┐ ┌─────────────────────────────────┐
│ config.json │ │ SQLite (可同步数据) │
│ ┌───────────┐ │ │ ├─ providers 供应商配置 │
│ │ providers │ │ │ ├─ mcp_servers MCP 服务器 │
│ │ mcp │ │ ──> │ ├─ prompts 提示词 │
│ │ prompts │ │ │ ├─ skills 技能 │
│ │ settings │ │ │ └─ settings 通用设置 │
│ └───────────┘ │ ├─────────────────────────────────┤
└─────────────────┘ │ JSON (设备级数据) │
│ └─ settings.json 本地设置 │
│ ├─ 窗口位置 │
│ ├─ 路径覆盖 │
│ └─ 当前选中供应商 ID │
└─────────────────────────────────┘
双层结构的划分逻辑是:
| 层级 | 存储方式 | 数据类型 | 同步策略 |
|---|---|---|---|
| 云同步层 | SQLite | 供应商、MCP、Prompts、Skills | 未来可同步 |
| 设备层 | JSON | 窗口状态、本地路径、当前选择 | 保持本地 |
判断标准很清晰:跨设备应当一致的数据进 SQLite,与具体机器/窗口绑定的数据留在 JSON——窗口位置、本机路径覆盖这类信息同步到另一台设备没有意义,反而会造成困惑。
源码印证:database/ 模块结构
发布说明描述的模块化结构在仓库中可以直接对应到 src-tauri/src/database 目录:
database/
├── mod.rs 核心 Database 结构体和初始化
├── schema.rs 表结构定义、Schema 版本迁移
├── backup.rs SQL 导入导出、二进制快照备份
├── migration.rs JSON → SQLite 数据迁移引擎
└── dao/ 数据访问对象层
├── providers.rs 供应商 CRUD
├── mcp.rs MCP 服务器 CRUD
├── prompts.rs 提示词 CRUD
├── skills.rs Skills CRUD
└── settings.rs 键值对设置存储
(仓库当前版本的 dao 目录 还随后续版本扩展了 profiles.rs、failover.rs、proxy.rs 等 DAO,印证了这一模块化设计确实可持续扩展。)
几个关键实现细节:
- 数据库文件位置:从 mod.rs 的
Database::init()可以看到,SQLite 文件落在~/.cc-switch/cc-switch.db(通过get_app_config_dir()拼接),而非各客户端(Claude/Codex 等)的目录中。 - 连接封装:
rusqlite::Connection本身不是Sync的,源码用Mutex<Connection>包装(见Database { conn: Mutex<Connection> }),以支持在 Tauri State 多线程环境下共享;配套的lock_conn!宏统一处理加锁错误,避免unwrappanic。 - PRAGMA 配置:初始化时显式开启
PRAGMA foreign_keys = ON(这是本次「自定义端点丢失」Bug 的根源,后文详述);新建数据库还会设置PRAGMA auto_vacuum = INCREMENTAL,配合启动时的incremental_vacuum回收磁盘空间。 - Schema 版本管理:模块顶部定义了
SCHEMA_VERSION常量,当前仓库中已是 17——说明自 v3.8.0 引入该机制以来,表结构经历了十余次受控演进,每次变更都走schema.rs中的版本迁移逻辑,这正是发布说明中「支持数据库结构升级迁移」的落地形式。
表结构:providers 表与外键级联
database/schema.rs 中的建表语句揭示了 v3.8.0 之后架构的重要组成。以供应商为核心的两张表:
CREATE TABLE IF NOT EXISTS providers (
id TEXT NOT NULL,
app_type TEXT NOT NULL, -- 区分 Claude/Codex 等不同客户端
name TEXT NOT NULL,
settings_config TEXT NOT NULL, -- 供应商完整配置(JSON)
website_url TEXT,
category TEXT,
created_at INTEGER,
sort_index INTEGER,
notes TEXT,
icon TEXT, -- 供应商图标(本版本新增)
icon_color TEXT,
meta TEXT NOT NULL DEFAULT '{}',
is_current BOOLEAN NOT NULL DEFAULT 0,
in_failover_queue BOOLEAN NOT NULL DEFAULT 0,
PRIMARY KEY (id, app_type)
);
CREATE TABLE IF NOT EXISTS provider_endpoints (
id INTEGER PRIMARY KEY AUTOINCREMENT,
provider_id TEXT NOT NULL,
app_type TEXT NOT NULL,
url TEXT NOT NULL,
added_at INTEGER,
FOREIGN KEY (provider_id, app_type)
REFERENCES providers(id, app_type) ON DELETE CASCADE
);
要点:
- 复合主键
(id, app_type):同一供应商配置可以分属不同客户端(Claude Code、Codex、OpenCode、Grok Build、Hermes),主键组合保证命名隔离; provider_endpoints表外键级联删除:ON DELETE CASCADE意味着删除供应商行会自动清掉其自定义端点——这正是下文「INSERT OR REPLACE 丢端点」Bug 的引爆点;- 此外还有
mcp_servers(按客户端记录 enabled 开关)、prompts、skills、settings(键值对)等表,与发布说明中「云同步层」的数据类型一一对应。
技术实现四件套
发布说明总结的四个技术特性,都能在源码中验证:
| 特性 | 源码依据 |
|---|---|
| Schema 版本管理 | mod.rs 中 SCHEMA_VERSION 常量与 apply_schema_migrations() |
| SQL 导入导出 | backup.rs 的 dump_sql / SQL 导入,支持二进制快照备份 |
| 事务支持 | migration.rs 中迁移全程包裹在 rusqlite::Transaction 中,失败即整体回滚 |
| 自动迁移 | 首次启动检测旧 config.json,调用 migrate_from_json() 完成 JSON → SQLite 转换 |
值得一提的是 backup.rs 在后续版本中被显著加固:SQL 导出文件带 -- CC Switch SQLite 导出 头注释校验;导入外部 SQL 时挂了一个 authorizer 钩子,拒绝 ATTACH DATABASE、VACUUM INTO、文件型虚拟表以及白名单(foreign_keys、user_version)之外的 PRAGMA——因为这些导入路径会被 WebDAV/S3 云同步复用,输入不可信。这体现了「SQL dump 便于云端存储」这一设计目标下对安全边界的持续打磨。
从 v3.7.x 升级:自动迁移与数据安全
自动迁移在首次启动时执行,migration.rs 中的 migrate_from_json() 实现如下流程:
- 检测旧
config.json是否存在; - 在单个事务中依次迁移五类数据:Providers → MCP Servers → Prompts → Skills → Common Config(见
migrate_from_json_tx的 5 步调用); - 设备级设置(窗口位置、路径覆盖、当前选中供应商)分流写入
settings.json; - 全部成功后显示迁移通知。
数据安全策略有三条,全部可从源码确认:
- 原文件保留:迁移成功后
config.json不被删除,用户可随时回退; - 失败可诊断:迁移失败弹出错误对话框并保留
config.json,因事务未提交,SQLite 中不会留下半成品数据; - Dry-run 验证:
migrate_from_json_dry_run()在内存数据库上执行完整迁移流程但不落盘,供部署前回归验证迁移逻辑正确性——这是一个很少见但很值得称道的工程习惯。
全新用户界面
v3.8.0 同步完成了 UI 的整体重构,发布说明将其归为三类改进:
视觉改进
- 重新设计的界面布局;
- 统一的组件样式;
- 更流畅的过渡动画;
- 优化的视觉层次。
交互优化
- Header toolbar 重新设计;
- ConfirmDialog 样式统一(对应仓库中的 ConfirmDialog 组件);
- 禁用主视图 overscroll 弹跳效果,减少桌面端「假滚动」观感;
- 改进的表单验证反馈。
兼容性调整
- Tailwind CSS 从 v4 降级到 v3.4,以提升浏览器/WebView 兼容性——从仓库根目录的 tailwind.config.cjs 与 package.json 可以确认项目确实运行在 Tailwind v3.4 体系下。这是一次「牺牲版本号换兼容性」的务实决策,对 Tauri 这类依赖系统 WebView 的桌面应用尤其重要。
日语支持:国际化扩展到三种语言
本版本新增日语(日本語)界面,国际化语言从两种扩展到三种:简体中文、English、日本語。从仓库可确认三个语言文件并列存在且体量相当:en.json、ja.json(3250 行)、zh.json 与 zh-TW.json,配合 i18n 入口 加载。这也与「国际化文件:3 个文件变更」的技术统计吻合。
新增功能
Skills 递归扫描
Skills 管理系统支持递归扫描仓库目录,自动发现嵌套的技能文件:
- 支持多层目录结构;
- 自动发现所有
SKILL.md文件; - 允许不同仓库的同名技能(使用完整路径去重)。
实现位于 src-tauri/src/services/skill.rs,其中技能元数据(显示名称、描述等)均从 SKILL.md 解析,扫描时按完整目录路径作为技能唯一标识,从而解决「两个仓库都有 git-commit 技能」这类同名冲突问题。
供应商图标配置
供应商预设支持自定义图标配置,与上文的 providers 表 icon / icon_color 两个新字段直接对应:
- 预设供应商包含默认图标;
- 复制供应商时保留图标设置(本版本修复了复制时图标字段丢失的 Bug);
- 图标颜色可自定义。
前端侧由 ProviderIcon 组件 与 providerIcon 工具 负责渲染。
表单验证增强
供应商表单新增必填字段验证:
- 必填字段实时校验;
- 统一使用 Toast 通知显示验证错误;
- 更清晰的错误信息。
开机自启
新增跨三平台(Windows / macOS / Linux)的开机自动启动,在设置中一键开关。源码 auto_launch.rs 展示了具体实现:
- 基于
auto_launchcrate 的AutoLaunchBuilder统一抽象平台差异; - Windows:注册表启动项;
- macOS:注意源码中专门处理了
.app bundle路径(/path/CC Switch.app/Contents/MacOS/CC Switch→/path/CC Switch.app)——因为 AppleScript login item 直接指向可执行文件会弹出终端窗口,指向 bundle 才不会; - Linux:XDG autostart(
.desktop文件)。
新增供应商预设
- MiniMax —— 官方合作伙伴,官方 Coding Plan 预设。
Bug 修复:根因级讲解
关键修复:自定义端点丢失
这是本版本最重要的一次修复,根因极具教学价值:
- 现象:更新供应商时自定义请求地址(custom endpoints)意外丢失;
- 根因:旧实现用
INSERT OR REPLACE更新供应商。SQLite 中当REPLACE触发主键冲突时,底层实际执行DELETE旧行 +INSERT新行;而provider_endpoints表对providers声明了ON DELETE CASCADE,于是旧行被删的瞬间,其全部自定义端点随行被级联删除; - 修复:对已存在的供应商改用显式
UPDATE语句。
这一修复在当前 dao/providers.rs 中可以验证——更新路径全部是 UPDATE providers SET ... WHERE id = ? AND app_type = ? 形式(如第 203、419、485 行附近),is_current 切换、settings_config 覆盖均走 UPDATE,不再有 DELETE 语义介入。这个案例也说明:SQLite 的 REPLACE 是「冲突即删插」而非「就地更新」,配合外键级联时会产生隐式数据丢失。
Gemini 配置问题
- 修复自定义供应商环境变量未正确写入
.env文件; - 修复安全认证配置错误写入到其他配置文件(Gemini 的
security.auth.selectedType应写入~/.gemini/settings.json,相关逻辑见 gemini_config.rs 与 gemini_auth.rs)。
供应商验证问题
- 修复当前供应商 ID 不存在时的验证错误(迁移后
current指针悬空会导致校验误报); - 修复供应商复制时图标字段丢失。
平台兼容性(Linux)
- 解决 WebKitGTK 的 DMA-BUF 渲染问题(Linux 下 Tauri 基于 WebKitGTK,DMA-BUF 故障会表现为白屏/黑屏);
- 保留用户已有的
.desktop文件自定义(覆盖前不抹掉用户手工修改)。
其他修复
- 切换应用时的冗余用量查询;
- DMXAPI 预设使用错误的认证令牌字段;
- 深链接组件缺少翻译键;
- 用量脚本模板初始化逻辑。
技术改进:服务层与深链接的模块化
供应商服务模块化
发布说明给出的目标结构在仓库 services/provider 目录中得到印证:
services/provider/
├── mod.rs 核心服务 - add/update/delete/switch/validate
├── live.rs Live 配置文件操作
├── gemini_auth.rs Gemini 认证类型检测
├── endpoints.rs 自定义端点管理
└── usage.rs 用量脚本执行
其中 endpoints.rs 专职管理 provider_endpoints 表,与上文端点丢失修复直接相关:端点的增删被从供应商主体 CRUD 中拆出,边界清晰。(仓库当前版本还额外有 pi.rs,属后续版本扩展。)
深链接模块化
深链接(ccswitch:// 协议导入)拆分为独立模块 src-tauri/src/deeplink,与文档描述一致:
deeplink/
├── mod.rs 模块导出
├── parser.rs URL 解析
├── provider.rs 供应商导入逻辑
├── mcp.rs MCP 导入逻辑
├── prompt.rs 提示词导入
├── skill.rs Skills 导入
└── utils.rs 工具函数
前端对应的确认交互组件位于 components/deeplink(MCP/Prompt/Skill 三类确认对话框)。
代码质量清理
- 移除 JSON 时代遗留的导入导出死代码;
- 移除未使用的 MCP 类型导出;
- 统一错误处理方式(全部经由 error.rs 的
AppError); - 测试侧:迁移测试整体切到 SQLite 架构(后端测试见 src-tauri/tests,如 provider_service.rs、import_export_sync.rs),前端组件测试与 MSW handlers 同步更新以适配新 API。
技术统计
总体变更:
- 提交数:51
- 文件数:207 个文件变更
- 新增:+17,297 行
- 删除:-6,870 行
- 净增:+10,427 行
提交类型分布:
- fix:25 个(Bug 修复)
- refactor:11 个(代码重构)
- feat:9 个(新功能)
- test:1 个(测试)
- 其他:5 个
改动区域分布:
- 前端源码:112 个文件
- Rust 后端:63 个文件
- 测试文件:20 个文件
- 国际化文件:3 个文件
删除量接近 7000 行,与「移除 JSON 时代死代码 + UI 重构」吻合,说明这并非简单堆功能,而是一次有意识的架构换血。
下载与安装
系统要求
- Windows:Windows 10+
- macOS:macOS 10.15(Catalina)+
- Linux:Ubuntu 22.04+ / Debian 11+ / Fedora 34+
获取方式
- 从项目 Releases 页下载对应安装包:Windows 为
.msi或-Portable.zip,macOS 为.tar.gz或.zip,Linux 为.AppImage或.deb; - macOS 用户也可以使用 Homebrew:
brew tap farion1231/ccswitch
brew install --cask cc-switch
更新:
brew upgrade --cask cc-switch
升级注意:从 v3.7.x 升级到 v3.8.0 无需任何手工操作,首次启动即触发上文所述的自动迁移;升级前无需导出备份,但建议知悉 config.json 会被保留、~/.cc-switch/cc-switch.db 将成为新的主数据文件。更多变更脉络可参考 CHANGELOG.md,项目中文文档见 README_ZH.md。
未来展望
v3.8.0 明确为两个方向铺路(v3.9.0 预览,暂定):
- 本地代理功能:SQLite 化的供应商配置(含端点、元数据)为本地代理的路由与故障切换提供了结构化的数据基础——仓库中
in_failover_queue、provider_health等字段及 proxy 模块 已是后续版本的现实落点。
从源码结构看,「可同步数据进 SQLite、设备级数据留 JSON」的分层一旦稳定,后续任何同步方案(WebDAV/S3 等)只需围绕 cc-switch.db 的 SQL dump 做增量与冲突处理,而不会把窗口状态等噪音带进同步链路——这正是本版本架构决策的核心价值。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00