@musistudio/claude-code-router 1.0.27 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -113
- package/README_zh.md +15 -7
- package/config.example.json +14 -7
- package/dist/cli.js +10315 -1914
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
## ✨ Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
11
|
+
- **Model Routing**: Route requests to different models based on your needs (e.g., background tasks, thinking, long context).
|
|
12
|
+
- **Multi-Provider Support**: Supports various model providers like OpenRouter, DeepSeek, Ollama, Gemini, Volcengine, and SiliconFlow.
|
|
13
|
+
- **Request/Response Transformation**: Customize requests and responses for different providers using transformers.
|
|
14
|
+
- **Dynamic Model Switching**: Switch models on-the-fly within Claude Code using the `/model` command.
|
|
15
|
+
- **GitHub Actions Integration**: Trigger Claude Code tasks in your GitHub workflows.
|
|
16
|
+
- **Plugin System**: Extend functionality with custom transformers.
|
|
17
17
|
|
|
18
18
|
## 🚀 Getting Started
|
|
19
19
|
|
|
@@ -36,6 +36,7 @@ npm install -g @musistudio/claude-code-router
|
|
|
36
36
|
Create and configure your `~/.claude-code-router/config.json` file. For more details, you can refer to `config.example.json`.
|
|
37
37
|
|
|
38
38
|
The `config.json` file has several key sections:
|
|
39
|
+
|
|
39
40
|
- **`PROXY_URL`** (optional): You can set a proxy for API requests, for example: `"PROXY_URL": "http://127.0.0.1:7890"`.
|
|
40
41
|
- **`LOG`** (optional): You can enable logging by setting it to `true`. The log file will be located at `$HOME/.claude-code-router.log`.
|
|
41
42
|
- **`APIKEY`** (optional): You can set a secret key to authenticate requests. When set, clients must provide this key in the `Authorization` header (e.g., `Bearer your-secret-key`) or the `x-api-key` header. Example: `"APIKEY": "your-secret-key"`.
|
|
@@ -106,16 +107,20 @@ Here is a comprehensive example:
|
|
|
106
107
|
"name": "modelscope",
|
|
107
108
|
"api_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
|
|
108
109
|
"api_key": "",
|
|
109
|
-
"models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct"],
|
|
110
|
+
"models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "Qwen/Qwen3-235B-A22B-Thinking-2507"],
|
|
110
111
|
"transformer": {
|
|
111
112
|
"use": [
|
|
112
113
|
[
|
|
113
114
|
"maxtoken",
|
|
114
115
|
{
|
|
115
|
-
"max_tokens":
|
|
116
|
+
"max_tokens": 65536
|
|
116
117
|
}
|
|
117
|
-
]
|
|
118
|
-
|
|
118
|
+
],
|
|
119
|
+
"enhancetool"
|
|
120
|
+
],
|
|
121
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507": {
|
|
122
|
+
"use": ["reasoning"]
|
|
123
|
+
}
|
|
119
124
|
}
|
|
120
125
|
},
|
|
121
126
|
{
|
|
@@ -128,9 +133,10 @@ Here is a comprehensive example:
|
|
|
128
133
|
[
|
|
129
134
|
"maxtoken",
|
|
130
135
|
{
|
|
131
|
-
"max_tokens":
|
|
136
|
+
"max_tokens": 65536
|
|
132
137
|
}
|
|
133
|
-
]
|
|
138
|
+
],
|
|
139
|
+
"enhancetool"
|
|
134
140
|
]
|
|
135
141
|
}
|
|
136
142
|
}
|
|
@@ -140,12 +146,12 @@ Here is a comprehensive example:
|
|
|
140
146
|
"background": "ollama,qwen2.5-coder:latest",
|
|
141
147
|
"think": "deepseek,deepseek-reasoner",
|
|
142
148
|
"longContext": "openrouter,google/gemini-2.5-pro-preview",
|
|
149
|
+
"longContextThreshold": 60000,
|
|
143
150
|
"webSearch": "gemini,gemini-2.5-flash"
|
|
144
151
|
}
|
|
145
152
|
}
|
|
146
153
|
```
|
|
147
154
|
|
|
148
|
-
|
|
149
155
|
### 3. Running Claude Code with the Router
|
|
150
156
|
|
|
151
157
|
Start Claude Code using the router:
|
|
@@ -155,6 +161,7 @@ ccr code
|
|
|
155
161
|
```
|
|
156
162
|
|
|
157
163
|
> **Note**: After modifying the configuration file, you need to restart the service for the changes to take effect:
|
|
164
|
+
>
|
|
158
165
|
> ```shell
|
|
159
166
|
> ccr restart
|
|
160
167
|
> ```
|
|
@@ -163,73 +170,74 @@ ccr code
|
|
|
163
170
|
|
|
164
171
|
The `Providers` array is where you define the different model providers you want to use. Each provider object requires:
|
|
165
172
|
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
170
|
-
-
|
|
173
|
+
- `name`: A unique name for the provider.
|
|
174
|
+
- `api_base_url`: The full API endpoint for chat completions.
|
|
175
|
+
- `api_key`: Your API key for the provider.
|
|
176
|
+
- `models`: A list of model names available from this provider.
|
|
177
|
+
- `transformer` (optional): Specifies transformers to process requests and responses.
|
|
171
178
|
|
|
172
179
|
#### Transformers
|
|
173
180
|
|
|
174
181
|
Transformers allow you to modify the request and response payloads to ensure compatibility with different provider APIs.
|
|
175
182
|
|
|
176
|
-
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
183
|
+
- **Global Transformer**: Apply a transformer to all models from a provider. In this example, the `openrouter` transformer is applied to all models under the `openrouter` provider.
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"name": "openrouter",
|
|
187
|
+
"api_base_url": "https://openrouter.ai/api/v1/chat/completions",
|
|
188
|
+
"api_key": "sk-xxx",
|
|
189
|
+
"models": [
|
|
190
|
+
"google/gemini-2.5-pro-preview",
|
|
191
|
+
"anthropic/claude-sonnet-4",
|
|
192
|
+
"anthropic/claude-3.5-sonnet"
|
|
193
|
+
],
|
|
194
|
+
"transformer": { "use": ["openrouter"] }
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
- **Model-Specific Transformer**: Apply a transformer to a specific model. In this example, the `deepseek` transformer is applied to all models, and an additional `tooluse` transformer is applied only to the `deepseek-chat` model.
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"name": "deepseek",
|
|
202
|
+
"api_base_url": "https://api.deepseek.com/chat/completions",
|
|
203
|
+
"api_key": "sk-xxx",
|
|
204
|
+
"models": ["deepseek-chat", "deepseek-reasoner"],
|
|
205
|
+
"transformer": {
|
|
206
|
+
"use": ["deepseek"],
|
|
207
|
+
"deepseek-chat": { "use": ["tooluse"] }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- **Passing Options to a Transformer**: Some transformers, like `maxtoken`, accept options. To pass options, use a nested array where the first element is the transformer name and the second is an options object.
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"name": "siliconflow",
|
|
216
|
+
"api_base_url": "https://api.siliconflow.cn/v1/chat/completions",
|
|
217
|
+
"api_key": "sk-xxx",
|
|
218
|
+
"models": ["moonshotai/Kimi-K2-Instruct"],
|
|
219
|
+
"transformer": {
|
|
220
|
+
"use": [
|
|
221
|
+
[
|
|
222
|
+
"maxtoken",
|
|
223
|
+
{
|
|
224
|
+
"max_tokens": 16384
|
|
225
|
+
}
|
|
219
226
|
]
|
|
220
|
-
|
|
227
|
+
]
|
|
221
228
|
}
|
|
222
|
-
|
|
229
|
+
}
|
|
230
|
+
```
|
|
223
231
|
|
|
224
232
|
**Available Built-in Transformers:**
|
|
225
233
|
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
234
|
+
- `deepseek`: Adapts requests/responses for DeepSeek API.
|
|
235
|
+
- `gemini`: Adapts requests/responses for Gemini API.
|
|
236
|
+
- `openrouter`: Adapts requests/responses for OpenRouter API.
|
|
237
|
+
- `groq`: Adapts requests/responses for groq API.
|
|
238
|
+
- `maxtoken`: Sets a specific `max_tokens` value.
|
|
239
|
+
- `tooluse`: Optimizes tool usage for certain models via `tool_choice`.
|
|
240
|
+
- `gemini-cli` (experimental): Unofficial support for Gemini via Gemini CLI [gemini-cli.js](https://gist.github.com/musistudio/1c13a65f35916a7ab690649d3df8d1cd).
|
|
233
241
|
|
|
234
242
|
**Custom Transformers:**
|
|
235
243
|
|
|
@@ -238,12 +246,12 @@ You can also create your own transformers and load them via the `transformers` f
|
|
|
238
246
|
```json
|
|
239
247
|
{
|
|
240
248
|
"transformers": [
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
249
|
+
{
|
|
250
|
+
"path": "$HOME/.claude-code-router/plugins/gemini-cli.js",
|
|
251
|
+
"options": {
|
|
252
|
+
"project": "xxx"
|
|
246
253
|
}
|
|
254
|
+
}
|
|
247
255
|
]
|
|
248
256
|
}
|
|
249
257
|
```
|
|
@@ -252,12 +260,12 @@ You can also create your own transformers and load them via the `transformers` f
|
|
|
252
260
|
|
|
253
261
|
The `Router` object defines which model to use for different scenarios:
|
|
254
262
|
|
|
255
|
-
-
|
|
256
|
-
-
|
|
257
|
-
-
|
|
258
|
-
-
|
|
259
|
-
-
|
|
260
|
-
|
|
263
|
+
- `default`: The default model for general tasks.
|
|
264
|
+
- `background`: A model for background tasks. This can be a smaller, local model to save costs.
|
|
265
|
+
- `think`: A model for reasoning-heavy tasks, like Plan Mode.
|
|
266
|
+
- `longContext`: A model for handling long contexts (e.g., > 60K tokens).
|
|
267
|
+
- `longContextThreshold` (optional): The token count threshold for triggering the long context model. Defaults to 60000 if not specified.
|
|
268
|
+
- `webSearch`: Used for handling web search tasks and this requires the model itself to support the feature. If you're using openrouter, you need to add the `:online` suffix after the model name.
|
|
261
269
|
|
|
262
270
|
You can also switch models dynamically in Claude Code with the `/model` command:
|
|
263
271
|
`/model provider_name,model_name`
|
|
@@ -290,11 +298,11 @@ Here is an example of a `custom-router.js` based on `custom-router.example.js`:
|
|
|
290
298
|
* @returns {Promise<string|null>} - A promise that resolves to the "provider,model_name" string, or null to use the default router.
|
|
291
299
|
*/
|
|
292
300
|
module.exports = async function router(req, config) {
|
|
293
|
-
const userMessage = req.body.messages.find(m => m.role ===
|
|
301
|
+
const userMessage = req.body.messages.find((m) => m.role === "user")?.content;
|
|
294
302
|
|
|
295
|
-
if (userMessage && userMessage.includes(
|
|
303
|
+
if (userMessage && userMessage.includes("explain this code")) {
|
|
296
304
|
// Use a powerful model for code explanation
|
|
297
|
-
return
|
|
305
|
+
return "openrouter,anthropic/claude-3.5-sonnet";
|
|
298
306
|
}
|
|
299
307
|
|
|
300
308
|
// Fallback to the default router configuration
|
|
@@ -302,7 +310,6 @@ module.exports = async function router(req, config) {
|
|
|
302
310
|
};
|
|
303
311
|
```
|
|
304
312
|
|
|
305
|
-
|
|
306
313
|
## 🤖 GitHub Actions
|
|
307
314
|
|
|
308
315
|
Integrate Claude Code Router into your CI/CD pipeline. After setting up [Claude Code Actions](https://docs.anthropic.com/en/docs/claude-code/github-actions), modify your `.github/workflows/claude.yaml` to use the router:
|
|
@@ -364,8 +371,8 @@ This setup allows for interesting automations, like running tasks during off-pea
|
|
|
364
371
|
|
|
365
372
|
## 📝 Further Reading
|
|
366
373
|
|
|
367
|
-
-
|
|
368
|
-
-
|
|
374
|
+
- [Project Motivation and How It Works](blog/en/project-motivation-and-how-it-works.md)
|
|
375
|
+
- [Maybe We Can Do More with the Router](blog/en/maybe-we-can-do-more-with-the-route.md)
|
|
369
376
|
|
|
370
377
|
## ❤️ Support & Sponsoring
|
|
371
378
|
|
|
@@ -387,39 +394,39 @@ A huge thank you to all our sponsors for their generous support!
|
|
|
387
394
|
- @Simon Leischnig
|
|
388
395
|
- [@duanshuaimin](https://github.com/duanshuaimin)
|
|
389
396
|
- [@vrgitadmin](https://github.com/vrgitadmin)
|
|
390
|
-
-
|
|
397
|
+
- @\*o
|
|
391
398
|
- [@ceilwoo](https://github.com/ceilwoo)
|
|
392
|
-
-
|
|
393
|
-
-
|
|
394
|
-
- @K
|
|
395
|
-
- @R
|
|
399
|
+
- @\*说
|
|
400
|
+
- @\*更
|
|
401
|
+
- @K\*g
|
|
402
|
+
- @R\*R
|
|
396
403
|
- [@bobleer](https://github.com/bobleer)
|
|
397
|
-
-
|
|
398
|
-
-
|
|
404
|
+
- @\*苗
|
|
405
|
+
- @\*划
|
|
399
406
|
- [@Clarence-pan](https://github.com/Clarence-pan)
|
|
400
407
|
- [@carter003](https://github.com/carter003)
|
|
401
|
-
- @S
|
|
402
|
-
-
|
|
403
|
-
-
|
|
404
|
-
- @Z
|
|
405
|
-
-
|
|
408
|
+
- @S\*r
|
|
409
|
+
- @\*晖
|
|
410
|
+
- @\*敏
|
|
411
|
+
- @Z\*z
|
|
412
|
+
- @\*然
|
|
406
413
|
- [@cluic](https://github.com/cluic)
|
|
407
|
-
-
|
|
414
|
+
- @\*苗
|
|
408
415
|
- [@PromptExpert](https://github.com/PromptExpert)
|
|
409
|
-
-
|
|
416
|
+
- @\*应
|
|
410
417
|
- [@yusnake](https://github.com/yusnake)
|
|
411
|
-
-
|
|
412
|
-
-
|
|
413
|
-
-
|
|
414
|
-
-
|
|
415
|
-
-
|
|
416
|
-
-
|
|
417
|
-
-
|
|
418
|
-
-
|
|
419
|
-
- @Z
|
|
420
|
-
-
|
|
418
|
+
- @\*飞
|
|
419
|
+
- @董\*
|
|
420
|
+
- @\*汀
|
|
421
|
+
- @\*涯
|
|
422
|
+
- @\*:-)
|
|
423
|
+
- @\*\*磊
|
|
424
|
+
- @\*琢
|
|
425
|
+
- @\*成
|
|
426
|
+
- @Z\*o
|
|
427
|
+
- @\*琨
|
|
421
428
|
- [@congzhangzh](https://github.com/congzhangzh)
|
|
422
|
-
-
|
|
423
|
-
|
|
429
|
+
- @\*\_
|
|
430
|
+
- @Z\*m
|
|
424
431
|
|
|
425
432
|
(If your name is masked, please contact me via my homepage email to update it with your GitHub username.)
|
package/README_zh.md
CHANGED
|
@@ -103,16 +103,20 @@ npm install -g @musistudio/claude-code-router
|
|
|
103
103
|
"name": "modelscope",
|
|
104
104
|
"api_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
|
|
105
105
|
"api_key": "",
|
|
106
|
-
"models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct"],
|
|
106
|
+
"models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "Qwen/Qwen3-235B-A22B-Thinking-2507"],
|
|
107
107
|
"transformer": {
|
|
108
108
|
"use": [
|
|
109
109
|
[
|
|
110
110
|
"maxtoken",
|
|
111
111
|
{
|
|
112
|
-
"max_tokens":
|
|
112
|
+
"max_tokens": 65536
|
|
113
113
|
}
|
|
114
|
-
]
|
|
115
|
-
|
|
114
|
+
],
|
|
115
|
+
"enhancetool"
|
|
116
|
+
],
|
|
117
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507": {
|
|
118
|
+
"use": ["reasoning"]
|
|
119
|
+
}
|
|
116
120
|
}
|
|
117
121
|
},
|
|
118
122
|
{
|
|
@@ -125,9 +129,10 @@ npm install -g @musistudio/claude-code-router
|
|
|
125
129
|
[
|
|
126
130
|
"maxtoken",
|
|
127
131
|
{
|
|
128
|
-
"max_tokens":
|
|
132
|
+
"max_tokens": 65536
|
|
129
133
|
}
|
|
130
|
-
]
|
|
134
|
+
],
|
|
135
|
+
"enhancetool"
|
|
131
136
|
]
|
|
132
137
|
}
|
|
133
138
|
}
|
|
@@ -137,6 +142,7 @@ npm install -g @musistudio/claude-code-router
|
|
|
137
142
|
"background": "ollama,qwen2.5-coder:latest",
|
|
138
143
|
"think": "deepseek,deepseek-reasoner",
|
|
139
144
|
"longContext": "openrouter,google/gemini-2.5-pro-preview",
|
|
145
|
+
"longContextThreshold": 60000,
|
|
140
146
|
"webSearch": "gemini,gemini-2.5-flash"
|
|
141
147
|
}
|
|
142
148
|
}
|
|
@@ -253,6 +259,7 @@ Transformers 允许您修改请求和响应负载,以确保与不同提供商
|
|
|
253
259
|
- `background`: 用于后台任务的模型。这可以是一个较小的本地模型以节省成本。
|
|
254
260
|
- `think`: 用于推理密集型任务(如计划模式)的模型。
|
|
255
261
|
- `longContext`: 用于处理长上下文(例如,> 60K 令牌)的模型。
|
|
262
|
+
- `longContextThreshold` (可选): 触发长上下文模型的令牌数阈值。如果未指定,默认为 60000。
|
|
256
263
|
- `webSearch`: 用于处理网络搜索任务,需要模型本身支持。如果使用`openrouter`需要在模型后面加上`:online`后缀。
|
|
257
264
|
|
|
258
265
|
您还可以使用 `/model` 命令在 Claude Code 中动态切换模型:
|
|
@@ -415,9 +422,10 @@ jobs:
|
|
|
415
422
|
- @Z*o
|
|
416
423
|
- [@congzhangzh](https://github.com/congzhangzh)
|
|
417
424
|
- @*_
|
|
425
|
+
- @Z\*m
|
|
418
426
|
|
|
419
427
|
(如果您的名字被屏蔽,请通过我的主页电子邮件与我联系,以便使用您的 GitHub 用户名进行更新。)
|
|
420
428
|
|
|
421
429
|
|
|
422
430
|
## 交流群
|
|
423
|
-
<img src="/blog/images/wechat_group.jpg" width="200" alt="wechat_group" />
|
|
431
|
+
<img src="/blog/images/wechat_group.jpg" width="200" alt="wechat_group" />
|
package/config.example.json
CHANGED
|
@@ -70,16 +70,20 @@
|
|
|
70
70
|
"name": "modelscope",
|
|
71
71
|
"api_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
|
|
72
72
|
"api_key": "",
|
|
73
|
-
"models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct"],
|
|
73
|
+
"models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "Qwen/Qwen3-235B-A22B-Thinking-2507"],
|
|
74
74
|
"transformer": {
|
|
75
75
|
"use": [
|
|
76
76
|
[
|
|
77
77
|
"maxtoken",
|
|
78
78
|
{
|
|
79
|
-
"max_tokens":
|
|
79
|
+
"max_tokens": 65536
|
|
80
80
|
}
|
|
81
|
-
]
|
|
82
|
-
|
|
81
|
+
],
|
|
82
|
+
"enhancetool"
|
|
83
|
+
],
|
|
84
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507": {
|
|
85
|
+
"use": ["reasoning"]
|
|
86
|
+
}
|
|
83
87
|
}
|
|
84
88
|
},
|
|
85
89
|
{
|
|
@@ -92,9 +96,10 @@
|
|
|
92
96
|
[
|
|
93
97
|
"maxtoken",
|
|
94
98
|
{
|
|
95
|
-
"max_tokens":
|
|
99
|
+
"max_tokens": 65536
|
|
96
100
|
}
|
|
97
|
-
]
|
|
101
|
+
],
|
|
102
|
+
"enhancetool"
|
|
98
103
|
]
|
|
99
104
|
}
|
|
100
105
|
}
|
|
@@ -103,7 +108,9 @@
|
|
|
103
108
|
"default": "deepseek,deepseek-chat",
|
|
104
109
|
"background": "ollama,qwen2.5-coder:latest",
|
|
105
110
|
"think": "deepseek,deepseek-reasoner",
|
|
106
|
-
"longContext": "openrouter,google/gemini-2.5-pro-preview"
|
|
111
|
+
"longContext": "openrouter,google/gemini-2.5-pro-preview",
|
|
112
|
+
"longContextThreshold": 60000,
|
|
113
|
+
"webSearch": "gemini,gemini-2.5-flash"
|
|
107
114
|
},
|
|
108
115
|
"APIKEY": "your-secret-key",
|
|
109
116
|
"HOST": "0.0.0.0"
|