news 2026/9/9 23:26:17

Claude Code Router 配置存储深入解析:config.sqlite 的位置、迁移机制与安全操作指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Claude Code Router 配置存储深入解析:config.sqlite 的位置、迁移机制与安全操作指南

Claude Code Router 配置存储深入解析:config.sqlite 的位置、迁移机制与安全操作指南

【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router

config.sqlite 是 Claude Code Router(CCR)桌面应用维护运行时配置的 SQLite 数据库,也是判断“当前配置到底生效在哪”的关键。本文将以官方文档 configuration-file.md 为骨架,结合仓库源码(app-paths.ts、constants.ts、config-repository.ts、entrypoint.sh),讲清楚各平台数据库默认位置、Docker 环境的数据持久化方式、旧版config.json的一次性迁移语义,以及如何在安全前提下完成备份与修改——读完你既能快速找到自己的配置数据库,也能理解 CCR 内部“JSON 时代 → SQLite 时代”的演进逻辑。

背景:CCR 的运行时配置为什么存放在 SQLite

CCR(Claude Code Router)是一个“本地 AI Agent 控制面”,负责在多个模型 Provider 之间路由请求、编排工具。与很多仅用单个 JSON 文件存配置的工具不同,CCR 的运行时配置统一存放在一个 SQLite 数据库文件中,即config.sqlite

从源码看,配置数据库文件的常量在 constants.ts 中定义:

export const APP_CONFIG_DB_FILE = path.join(CONFIGDIR, "config.sqlite");

CONFIGDIR由 app-paths.ts 按平台解析:

export function resolveRuntimeConfigDir(): string { if (process.platform === "win32") { return path.join(resolveRuntimeAppPath("appData"), APP_STORAGE_NAME); } return path.join(resolveRuntimeAppPath("home"), `.${APP_STORAGE_NAME}`); }

其中APP_STORAGE_NAME固定为"claude-code-router"(app-paths.ts)。也就是说,配置目录的命名规则是“家目录下的隐藏目录”或“系统 AppData 目录下的应用目录”,这也是官方文档默认位置表格的代码来源。

各平台默认位置一览

官方文档给出的默认位置如下,这三行也是排查问题时的“标准答案”:

运行环境配置数据库默认路径
macOS / Linux~/.claude-code-router/config.sqlite
Windows%APPDATA%\claude-code-router\config.sqlite
Docker/data/.claude-code-router/config.sqlite

macOS / Linux:家目录下的隐藏目录

在非 Windows 平台,配置目录固定在家目录下的~/.claude-code-router,不受XDG_CONFIG_HOME影响。这一点与许多遵循 XDG 规范的工具不同,属于 CCR 自己的约定:即使你在 Linux 上设置了XDG_CONFIG_HOME,配置仍然落在~/.claude-code-router/config.sqlite

Windows:优先使用%APPDATA%

在 Windows 上,配置目录解析为appData下的claude-code-routerappData的取值逻辑见 app-paths.ts:

function fallbackAppDataDir(): string { if (process.platform === "win32") { return process.env.APPDATA || process.env.LOCALAPPDATA || (process.env.USERPROFILE ? path.join(process.env.USERPROFILE, "AppData", "Roaming") : path.join(os.homedir(), "AppData", "Roaming")); } return process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config"); }

即依次尝试环境变量APPDATALOCALAPPDATAUSERPROFILE\AppData\Roaming,最终得到%APPDATA%\claude-code-router\config.sqlite

历史版本遗留目录:Windows 上的“Claude Code Router”目录

需要特别注意的是 Windows 上存在一个历史遗留配置目录。源码中保留了对%APPDATA%\Claude Code RouterAPP_NAME="Claude Code Router",带空格)目录的兼容处理(constants.ts):

export const LEGACY_WINDOWS_CONFIGDIR = path.join(resolveRuntimeAppPath("appData"), APP_NAME); export const LEGACY_WINDOWS_CONFIG_FILE = path.join(LEGACY_WINDOWS_CONFIGDIR, "config.json");

并且在模块加载时,会把旧目录中的内容按“仅复制缺失项”的方式并入新目录(constants.ts):

if (process.platform === "win32") { copyMissingDirectoryContents(LEGACY_WINDOWS_CONFIGDIR, CONFIGDIR, "Windows app data directory"); }

copyMissingDirectoryContents使用cpSync(source, target, { errorOnExist: false, force: false, recursive: true }),即不会覆盖新目录下已存在的文件,实现细节见 migration.ts。因此,如果你升级自较早的 Windows 版本,新配置库位于%APPDATA%\claude-code-router\,旧数据会被自动带过来。

提示:如果你在磁盘上找不到config.sqlite,请先确认自己是否属于“老版本迁移”场景——旧版可能只生成了config.json,位于~/.claude-code-router/config.json(macOS/Linux)或%APPDATA%\Claude Code Router\config.json(Windows 旧目录)。

Docker 环境:HOME=/data与整目录持久化

官方文档特别强调:Docker 镜像将HOME设置为/data,因此配置数据库位于/data/.claude-code-router/config.sqlite。这一行为在 entrypoint.sh 中可以看到完整链路:

CCR_DATA_DIR="${CCR_DATA_DIR:-/data}" ... export HOME="${CCR_DATA_DIR}" export CCR_DATA_DIR ... CONFIG_DIR="${HOME}/.claude-code-router" CONFIG_FILE="${CONFIG_DIR}/config.json" APP_CONFIG_DB_FILE="${CONFIG_DIR}/config.sqlite" mkdir -p "${CONFIG_DIR}" "${CONFIG_DIR}/app-data" /run/nginx /var/lib/nginx /var/log/nginx

由于路径解析逻辑是HOME+.claude-code-router,一旦HOME=/dataconfig.sqlite自然落在/data/.claude-code-router/下。同时入口脚本会预先创建app-data子目录,因为配置目录并不是孤立的——它还承载着网关运行需要的其他数据。

必须持久化整个/data,而不是单个文件

文档要求“持久化完整的/data目录,以保证配置数据库和相关文件都被保存”。从 docker/README.md 可以看到容器内数据目录的真实全貌:

/data/.claude-code-router/ ├── config.sqlite ├── gateway.config.json ├── app-data/ │ ├── api-keys.sqlite │ ├── request-logs.sqlite │ ├── usage.sqlite │ └── certs/ ├── profiles/ └── bin/
  • config.sqlite:主配置数据库(本主题核心);
  • gateway.config.json:网关运行时生成文件;
  • app-data/:历史遗留的 API 密钥库、请求日志库、用量统计库、代理/系统级证书(certs/)等。

仓库根目录的 docker-compose.yml 正是通过命名卷挂载整个/data实现持久化:

volumes: - ccr-data:/data

这里有一个经常踩坑的点:重建容器后“配置消失”,绝大多数是因为/data没有被正确挂载或换用了新的空卷docker compose down --volumes会连同数据卷一起删除)。确认容器使用的还是同一个ccr-data卷或同一 bind-mount 路径即可。

此外,入口脚本还有一个细节:首次启动时若config.jsonconfig.sqlite均不存在,会先写一份最小化的遗留版config.json作为引导(entrypoint.sh);当 UI 保存过设置后,SQLite 便成为权威来源(详见下一节)。默认情况下,每次容器启动还会把配置中的监听地址与routerEndpoint同步到 Docker 对外地址(CCR_DOCKER_SYNC_PUBLIC_ENDPOINT控制,见 docker/README.md)。

生效方式:SQLite 是权威来源,config.json只迁移一次

理解“生效方式”是使用 CCR 配置能力的关键。官方文档的表述可以拆成三条事实:

  1. 运行时配置存储在 SQLite 中
  2. 旧版config.json只在“没有 SQLite 配置”时作为一次性迁移来源被读取
  3. 迁移完成后,继续编辑config.json不会影响当前配置

从代码看“一次性迁移”

在 config-repository.ts 中,CCR 明确登记了三类需要归档的遗留 JSON 配置文件:

const legacyJsonConfigFiles = [ LEGACY_ACTIVE_CONFIG_FILE, // 当前配置目录下的 config.json LEGACY_WINDOWS_CONFIG_FILE, // Windows 旧目录 config.json LEGACY_CONFIG_FILE // 家目录 .claude-code-router/config.json ];

当 SQLite 配置库被创建并完成 schema 初始化后,这些遗留 JSON 会被读取、备份并最终清理(archiveLegacyJsonConfigFiles+drainLegacyCleanup,见 config-repository.ts 与 config-repository.ts)。整个流程带有“安全网”设计:

  • 迁移前会先计算遗留文件的 SHA-256,将内容存入数据库内置的legacy_storage_backups备份表,再登记到legacy_storage_cleanup清理队列;
  • 真正删除前会再次比对 SHA-256,若文件在“读取”与“清理”之间发生变化且无对应备份,则保留源文件并等待下次迁移重试,绝不误删用户数据;
  • 由于迁移只执行一次,SQLite 一旦写入成功并记录迁移 ID,之后你对config.json的任何编辑都只是改一个“档案文件”,不再进入当前运行配置。

Docker 场景下的一致行为

Docker 入口脚本同样贯彻了“SQLite 优先”的语义(docker/README.md):首启引导 JSON 只在没有任何配置时生成;一旦 UI 保存过设置,SQLite 即成为权威。容器每次启动的“端点同步”也是分别处理 JSON 与 SQLite 两种情况(entrypoint.sh 中的syncJsonFilesyncSqliteConfig)。

配置库的内部表结构

为方便你理解“配置到底以什么形态存在”,从 config-repository.ts 可以看到首次建库时创建的几张核心表:

用途
app_config主配置键值表,key/value_json/updated_at,默认应用配置以"default"为键
api_keysCCR 客户端 API Key(encrypted_key+encryption+limits_json
runtime_state各类运行时状态(如 onboarding 完成时间等)
config_schema_migrations迁移记录,防止迁移重复执行
legacy_storage_backups/legacy_storage_cleanup遗留 JSON / SQLite 文件的备份与延迟清理队列

因此一个config.sqlite内实际上同时管理着“配置”“客户端密钥”“运行时状态”三类数据,这也是为什么文档反复强调不要在运行时直接编辑数据库

不要在运行时直接编辑config.sqlite:WAL 模式与正确改法

文档给出的操作红线是:

  • 修改配置请使用桌面 UI,或在Settings中导出备份;
  • 不要在 CCR 运行时直接编辑config.sqlite
  • 同一目录下还存在config.sqlite-walconfig.sqlite-shm两个配套文件,编辑数据库时必须一并考虑。

为什么会同时出现-wal-shm文件

SQLite 在 CCR 中被显式配置为WAL(Write-Ahead Logging)模式,见 config-repository.ts:

function configureSqliteDatabase(database: SqlDatabase): void { database.pragma("journal_mode = WAL"); database.pragma("synchronous = NORMAL"); database.pragma("busy_timeout = 5000"); }

在 WAL 模式下,写入先追加到config.sqlite-wal,随后才周期性地 checkpoint 回主文件;config.sqlite-shm则是共享内存索引文件,用于多连接协调。带来的实际影响:

  • 只复制config.sqlite主文件往往得到不完整/不一致的快照(部分最新事务还在-wal里);
  • 在进程运行时用外部工具改写主文件,极易损坏数据库,因为 WAL 与主文件之间的状态会对不上;
  • 直接删除-wal/-shm同样危险,可能丢失尚未 checkpoint 的事务。

所以,请牢记“数据三件套”是一个整体。如果你确实需要文件级备份,最稳妥的顺序是:先停止 CCR(或至少让写入完全静止),再同时复制config.sqliteconfig.sqlite-walconfig.sqlite-shm。恢复时也应整体放回,不要把旧备份覆盖到一个仍在运行、还有新 WAL 数据的目录上(docker/README.md 对此有同样告诫)。

推荐的配置修改路径

CCR 提供的受支持改法本质上都走同一条代码路径——config-repository.ts 中的replacePersistedAppConfig/replacePersistedConfigSnapshot/replaceApiKeys等方法在事务内完成写入并刷新文件权限:

  1. 桌面/浏览器管理 UI:CCR 的管理界面(桌面 App 或 Docker 镜像通过 Nginx 提供的 Web UI)会把用户操作序列化为对app_config/api_keys的替换写库;
  2. Settings → Export data 导出备份:这是官方推荐的应用级备份手段(见 docker/README.md)。Docker 升级/迁移前先执行导出,比手工拷贝文件更安全;
  3. 网关/管理 RPC:若以 Docker 等模式远程管理,应通过认证的管理 RPC 修改,而不是直接进容器改库文件。

敏感性与文件权限

配置库中保存的是 Provider 凭据与 CCR 客户端 Key 等机密。源码在创建目录与每次写入后都会执行权限收紧(config-repository.ts 与 config-repository.ts):

  • 配置目录权限设为0o700
  • 主库文件、-wal-shm三个文件权限均被设为0o600secureDatabaseFilePermissions)。

也就是说,非当前系统用户无法读取配置内容。对应的,任何配置数据库的备份都必须按“包含密钥的敏感数据”对待,不要放进公开仓库或不可信存储。

常见问题排查速查

结合上面的机制,把高频疑问整理如下:

现象原因与解法
找不到config.sqlite先确认平台默认位置;Windows 老版本可能在%APPDATA%\Claude Code Router\(带空格目录),首次运行会并入%APPDATA%\claude-code-router\
修改~/.claude-code-router/config.json后不生效这是预期行为:SQLite 迁移完成后config.json只是归档文件,应改走桌面 UI 或 Settings 导出/导入流程
容器重建后配置消失检查是否仍挂载同一个/data卷;docker compose down --volumes会删除数据
只备份了config.sqlite,恢复后配置不全WAL 模式下最新事务可能还在-wal中;应用级备份请使用 Settings → Export data
想迁移到新机器/新环境备份整个数据目录(含config.sqlite-wal/-shmapp-data/),在 CCR 停止状态下拷贝,恢复前先清空目标目录

小结与延伸阅读

一句话总结:CCR 的运行配置以 SQLite 为唯一权威来源,位置由“平台默认目录 +claude-code-router目录名”决定;Docker 中因HOME=/data落在/data/.claude-code-router/,必须持久化整个/data;旧版config.json只在首次无 SQLite 配置时迁移一次,之后编辑它不再影响任何行为。

本文核心结论均有源码与配置佐证,可供进一步深入的文件包括:

  • 官方文档原文:configuration-file.md(英文)、configuration-file.md(中文)
  • 平台路径解析:app-paths.ts
  • 常量定义与 Windows 兼容拷贝:constants.ts
  • 建库、迁移与权限管理实现:config-repository.ts、migration.ts
  • SQLite 原生驱动封装:sqlite-native.ts
  • Docker 相关:配置库路径语义 entrypoint.sh、持久化布局与备份策略 docker/README.md、数据卷挂载 docker-compose.yml
  • 相关测试:配置迁移与遗留 JSON 行为可参考 config-repository-migration.test.mjs、legacy-json-preservation.test.mjs、config-repository-backup-deduplication.test.mjs

如果你需要继续了解供应商与模型配置、路由规则如何在 UI 中编辑并落到这张数据库里,可以阅读同目录下的 overview.md 或仓库根目录的 README_zh.md。

【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 23:26:08

AI蒸汽除草机器人:Ubuntu+YOLO实现杂草精准识别与喷射

这次我们看的是一个很具体的发明案例:明尼苏达的一位发明家,把 AI 摄像头识别、机械执行和蒸汽加热结合起来,做成了一台不依赖化学除草剂的除草机器人。这个项目在公开材料里的信息不算多,但它的技术路线很值得拆解:Ub…

作者头像 李华
网站建设 2026/9/9 23:26:01

事件直播稳定之道:EasyDSS选型部署与多平台分发实战

做线下活动直播这些年,我见过太多团队在“事件直播”这件事上栽跟头:发布会开始前半小时推流中断、几百人同时观看时画面卡成PPT、领导讲话的精彩片段因为断流没录下来、临时加一路无人机画面却不知道怎么接进系统。这些问题背后,其实是很多团…

作者头像 李华
网站建设 2026/9/9 23:25:47

FineBI零基础实战:从数据连接到仪表板发布

第一次接触FineBI是在一个做零售数据分析的项目里,当时客户要求把销售、库存、会员三块数据整合到一个看板上,业务部门提的需求一周能改八回。技术同事被缠得没脾气,后来索性上了FineBI,把数据准备做完之后,业务自己拖…

作者头像 李华
网站建设 2026/9/9 23:23:14

Seata XA模式实战:订单库存跨库强一致,从原理到踩坑全解析

如果你手头也有一个“下单成功但库存没扣”、“库存扣了但订单失败”这种跨库数据不一致的问题,那你已经站在分布式事务的门槛上了。这篇文章聊的 Seata XA 模式,是我在一个电商后端项目里实际落地过的方案,用在两个 MySQL 库之间做订单和库存…

作者头像 李华