前言:为什么是 CCR?
把 Claude Code 接上国内模型,听起来很简单:改一下 `~/.claude/settings.json` 里的 `ANTHROPIC_BASE_URL` 和 `ANTHROPIC_AUTH_TOKEN`,指向 DeepSeek、GLM 或者 Kimi 的兼容端点就行了。
但实际用起来,问题就一个接一个冒出来了:
* 想换个模型试试?打开配置文件、改字段、保存、重启 Claude Code,流程繁琐。
* 长上下文场景想切到 Kimi,思考任务想切到 reasoner?一次只能配一个,换来换去效率极低。
* 接的接口不完全兼容 Anthropic 协议?那你就得自己写转换逻辑,这是个大工程。
* 同事推荐一个新模型想快速体验?对不起,请重新走一遍上面的流程。
Claude Code 本身是一个非常优秀的 Agent 框架,文件编辑、命令执行、上下文管理、子任务编排、todo 跟踪、hook 和 skill 体系都做得相当成熟。但它的模型配置是“单挂”模式,没法像搭积木一样把多个模型同时挂上,再根据场景智能分发。
`claude-code-router`(CCR)就是来解决这个问题的。它能做到:
* **多模型聚合**:一份配置文件里同时挂载多家模型服务商,热切换无需重启。
* **场景智能分发**:将 default、background、think、longContext 等不同任务路由到最合适的模型。
* **transformer 适配层**:自动处理 DeepSeek、Gemini 等兼容性不完美的接口协议转换。
* **会话内动态切换**:在 Claude Code 里一行命令就能换模型,无缝衔接。
一句话总结:Claude Code 是引擎,CCR 就是它的变速箱。
安装过程
安装过程也算不上丝滑。CCR 的安装本身倒不复杂,一行命令搞定:
npm install -g @musistudio/claude-code-router
装完验证一下版本:
ccr -v
# claude-code-router version: 2.0.0
这一切看起来都很顺利。接下来,手动创建了 `C:/Users/**/.claude-code-router/config.json` 这个目录和配置文件。然后信心满满地运行:
ccr code
结果呢?要么没有响应,要么直接报错。第一个坑就这么来了。
坑 1:Router 里的 Provider 名字写错了
这是初始 `config.json` 里 Router 部分的样子:
"Router": {
"default": "arkcodingplan, glm-5.1", ← ❌ arkcodingplan 根本不存在
"background": "arkcodingplan, glm-5.1",
"think": "arkcodingplan, glm-5.1",
"longContext": "arkcodingplan, glm-5.1",
}
而我的 Providers 里定义的是:
"Providers": [
{ "name": "deepseek", ... },
{ "name": "volcengine", ... }
]
问题一目了然:在 Router 里引用了 `arkcodingplan, glm-5.1` 这个组合,但 Provider 名称是 `volcengine`,不是 `arkcodingplan`。CCR 启动日志里安安静静地打印了 `volcengine provider registered`,但 Router 根本不知道 volcengine 是谁——它只知道自己收到指令去找一个叫 `arkcodingplan` 的人,翻遍通讯录都找不到。正确写法是 `"provider名, 模型名"`,provider 名必须和上面 Providers 数组里 `name` 字段完全一致。
"Router": {
"default": "volcengine, glm-5.1"
}
坑 2:API Base URL 路径不完整
火山引擎方舟(volcengine ARK)有一个 Coding Plan 包月套餐,它的完整 API 地址是:
https://ark.cn-beijing.volces.com/api/coding/v1/chat/completions
而我最初只写到了 `/api/coding`:
"api_base_url": "https://ark.cn-beijing.volces.com/api/coding" ← ❌ 缺路径
这个错误非常隐蔽——CCR 启动时不报错,只有实际请求来了才会抛出 404 或者路由错误。直到用 curl 测试才抓到异常。
坑 3:国内服务配了袋里,但袋里没开
配置文件里有一行:
"PROXY_URL": "http://127.0.0.1:7890"
这本来是给海外模型(比如 OpenRouter、Gemini)准备的。但问题是:
1. 火山引擎是国内服务,根本不需要袋里。
2. 我的 Clash 软件没启动,7890 端口没人监听。
3. CCR 强制所有请求走这个袋里端口。
结果是每次请求都报 `fetch failed`,没有任何有用信息。
# 验证袋里状态
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:7890
# 输出 000 → 连不上
解决方案:国内服务直接清空袋里。
"PROXY_URL": "" ← ✅
需要再次用袋里时再填回来,并确保袋里软件正在运行。
坑 4:settings.json 和 CCR 抢方向盘(最容易忽视)
这是最隐蔽的坑,也是最大的问题。实际上,CCR 装完、config.json 修完、袋里清掉以后,`ccr restart` 服务已经能正常启动了。但诡异的是,运行 `ccr code` 之后,Claude Code 界面里的 `/model` 命令只能看到 `glm-5.1`,无法切换模型。
排查了一圈发现,`~/.claude/settings.json` 里有这样一段环境变量覆盖:
{
"env": {
"ANTHROPIC_AUTH_TOKEN": "ark-xxx",
"ANTHROPIC_BASE_URL": "https://ark.cn-beijing.volces.com/api/coding",
"ANTHROPIC_MODEL": "glm-5.1"
},
"model": "glm-5.1"
}
这意味着:
* `ANTHROPIC_BASE_URL` 直接指向火山引擎,完全绕过了 CCR。
* `ANTHROPIC_MODEL` 和顶层 `model` 锁死了模型,`/model` 命令无法切换。
CCR 的原理是在本地启动一个袋里服务器,运行 `ccr code` 时会自动设置环境变量让 Claude Code 连到本地袋里。但如果 `settings.json` 里的 env 配置优先级更高,就会覆盖 CCR 注入的值。
解决方案:删除 settings.json 里与 ANTHROPIC 相关的 env 变量和 model 字段,让 CCR 接管路由控制权。
坑 5:Warp 终端里无法添加文件、代码片段或图片到上下文
CCR 跑通之后,习惯性地用 Warp 终端打开 `ccr code`,准备像以前一样用右键"Attach as context"把代码文件或截图塞进对话框——结果发现功能倒是有,但点了毫无反应。
原因:Warp 的上下文注入功能是基于进程指纹识别实现的。Warp 检测到当前运行的是 `claude` 命令时,才会激活 Agent 增强型输入框和上下文绑定面板。而你执行的是 `ccr code`,Warp 只看到一个叫 `ccr` 的普通 Shell 命令,不会把它当成官方 AI Agent,自然不会激活上下文注入通道。
解法 A:用 Alias 欺骗 Warp(最推荐)
核心思路是把 `ccr code` 伪装成 `claude` 命令,让 Warp 正确识别。
Windows(PowerShell):
# 打开 PowerShell 配置文件
notepad $PROFILE
# 在记事本最后一中添加:
function claude { ccr code @args }
# 保存后刷新配置
& $PROFILE
macOS / Linux(Zsh/Bash):
# 编辑 shell 配置
nano ~/.zshrc
# 添加:
alias claude="ccr code"
# 保存后刷新
source ~/.zshrc
完成上述操作后,需要把当前 Warp 终端关闭,在当前目录下重新打开。之后在 Warp 中直接输入 `claude` 启动,Warp 就能识别到 `claude` 关键字,解锁上下文注入功能。
解法 B:Ctrl + G 唤起富文本输入框
如果 Alias 方案没生效,可以在 `ccr code` 会话中按 `Ctrl + G`,强制拉起 Warp 的 Rich Input Editor(多行富文本输入框),在里面点击附件图标添加代码或图片。
解法 C:用@键盘流注入文件上下文
如果 UI 级绑定彻底被 CCR 阻断,可以放弃鼠标流,改用键盘流:在输入框中键入 `@`,Warp 会基于当前 Git 仓库弹出文件/目录的快速搜索列表,选择后以文本路径方式注入上下文——这种方式 CCR 完全能理解。
解法 B 和 C 我没有实际验证,但解法 A 就足够解决问题了,Warp 的丝滑体验又回来了!
最终配置(可以直接用)
~/.claude-code-router/config.json
{
"LOG": true,
"LOG_LEVEL": "debug",
"HOST": "127.0.0.1",
"PORT": 3456,
"APIKEY": "",
"PROXY_URL": "",
"Providers": [
{
"name": "deepseek",
"api_base_url": "https://api.deepseek.com/chat/completions",
"api_key": "sk-你的DeepSeekKey",
"models": ["deepseek-chat", "deepseek-reasoner"],
"transformer": { "use": ["deepseek"] }
},
{
"name": "volcengine",
"api_base_url": "https://ark.cn-beijing.volces.com/api/coding/v1/chat/completions",
"api_key": "ark-你的火山Key",
"models": ["glm-5.1", "kimi-k2.6", "minimax-m3"]
}
],
"Router": {
"default": "volcengine, glm-5.1",
"background": "volcengine, glm-5.1",
"think": "volcengine, glm-5.1",
"longContext": "volcengine, kimi-k2.6",
"longContextThreshold": 60000,
"webSearch": "",
"image": "volcengine, kimi-k2.6"
}
}
~/.claude/settings.json
{
"theme": "dark",
"enabledPlugins": {
"understand-anything@understand-anything": true
}
}
关键原则就是:`settings.json` 是 Claude Code 自身的配置,不要在里面写什么 `ANTHROPIC_*` 环境变量。让 CCR 来管路由,让 `settings.json` 保持干净。
最终效果
一切就绪后,实际效果是这样的:
| 时机 | 你看到的(Claude Code 界面) | 背后真实发生的 |
|---|
| 普通对话 | "Opus 4.8" | 实际调用 GLM-5.1 |
| 上下文 > 60k | "Opus 4.8" | 自动切到 Kimi-2.6 |
| 你问"你是谁" | "Opus 4.8" | 模型回答"我是 GLM" |
Claude Code 以为自己用的是 Opus 4.8,但每一行代码、每一句回答都来自你配置的第三方模型。这感觉就像给一辆特斯拉换上了比亚迪的电池——仪表盘依然显示"满电",但真正的动力来源早已不是原厂货。
切换模型也有三种方式(按推荐度排序):
1. Claude Code 内直接输入:`/model volcengine, kimi-k2.6`
2. CCR 交互式菜单:另开终端运行 `ccr model`,选择模型后重启。注意要在 Warp 中操作。
3. 编辑配置文件:改 `Router. default` 字段后 `ccr restart`。
总结:排错心法
爬完这几个坑,有必要从架构层面重新理解一下从 CCR 调用大模型的工作流:
> 终端(Warp)→ Claude Code → settings.json 的 env → CCR 本地袋里 → Provider API
每一层都可能配置冲突或覆盖,排错的关键是逐层隔离验证:
1. 检查终端是否识别 Agent 进程(Warp 用户注意进程名匹配)。
2. 检查 CCR 是否启动:`ccr status`。
3. 检查日志有没有 proxy 注册:看 `~/.claude-code-router/logs/`。
4. 用 curl 直接测本地袋里:`curl http://127.0.0.1:3456/v1/messages`。
5. 检查 settings.json 有没有"越权"的 env 变量。
6. 确认 Provider URL 的完整路径。
7. 确认 Router 里的 provider 名和上面定义的一致。
如果你也在折腾 AI 工具的配置,希望这些踩过的坑能帮你少走弯路。