@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 CHANGED
@@ -8,12 +8,12 @@
8
8
 
9
9
  ## ✨ Features
10
10
 
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.
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": 8192
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": 8192
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
- - `name`: A unique name for the provider.
167
- - `api_base_url`: The full API endpoint for chat completions.
168
- - `api_key`: Your API key for the provider.
169
- - `models`: A list of model names available from this provider.
170
- - `transformer` (optional): Specifies transformers to process requests and responses.
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
- - **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.
177
- ```json
178
- {
179
- "name": "openrouter",
180
- "api_base_url": "https://openrouter.ai/api/v1/chat/completions",
181
- "api_key": "sk-xxx",
182
- "models": [
183
- "google/gemini-2.5-pro-preview",
184
- "anthropic/claude-sonnet-4",
185
- "anthropic/claude-3.5-sonnet"
186
- ],
187
- "transformer": { "use": ["openrouter"] }
188
- }
189
- ```
190
- - **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.
191
- ```json
192
- {
193
- "name": "deepseek",
194
- "api_base_url": "https://api.deepseek.com/chat/completions",
195
- "api_key": "sk-xxx",
196
- "models": ["deepseek-chat", "deepseek-reasoner"],
197
- "transformer": {
198
- "use": ["deepseek"],
199
- "deepseek-chat": { "use": ["tooluse"] }
200
- }
201
- }
202
- ```
203
-
204
- - **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.
205
- ```json
206
- {
207
- "name": "siliconflow",
208
- "api_base_url": "https://api.siliconflow.cn/v1/chat/completions",
209
- "api_key": "sk-xxx",
210
- "models": ["moonshotai/Kimi-K2-Instruct"],
211
- "transformer": {
212
- "use": [
213
- [
214
- "maxtoken",
215
- {
216
- "max_tokens": 16384
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
- - `deepseek`: Adapts requests/responses for DeepSeek API.
227
- - `gemini`: Adapts requests/responses for Gemini API.
228
- - `openrouter`: Adapts requests/responses for OpenRouter API.
229
- - `groq`: Adapts requests/responses for groq API.
230
- - `maxtoken`: Sets a specific `max_tokens` value.
231
- - `tooluse`: Optimizes tool usage for certain models via `tool_choice`.
232
- - `gemini-cli` (experimental): Unofficial support for Gemini via Gemini CLI [gemini-cli.js](https://gist.github.com/musistudio/1c13a65f35916a7ab690649d3df8d1cd).
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
- "path": "$HOME/.claude-code-router/plugins/gemini-cli.js",
243
- "options": {
244
- "project": "xxx"
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
- - `default`: The default model for general tasks.
256
- - `background`: A model for background tasks. This can be a smaller, local model to save costs.
257
- - `think`: A model for reasoning-heavy tasks, like Plan Mode.
258
- - `longContext`: A model for handling long contexts (e.g., > 60K tokens).
259
- - `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.
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 === 'user')?.content;
301
+ const userMessage = req.body.messages.find((m) => m.role === "user")?.content;
294
302
 
295
- if (userMessage && userMessage.includes('explain this code')) {
303
+ if (userMessage && userMessage.includes("explain this code")) {
296
304
  // Use a powerful model for code explanation
297
- return 'openrouter,anthropic/claude-3.5-sonnet';
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
- - [Project Motivation and How It Works](blog/en/project-motivation-and-how-it-works.md)
368
- - [Maybe We Can Do More with the Router](blog/en/maybe-we-can-do-more-with-the-route.md)
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
- - @*o
397
+ - @\*o
391
398
  - [@ceilwoo](https://github.com/ceilwoo)
392
- - @*说
393
- - @*更
394
- - @K*g
395
- - @R*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*r
402
- - @*晖
403
- - @*敏
404
- - @Z*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*o
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": 8192
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": 8192
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" />
@@ -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": 8192
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": 8192
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"