@musistudio/claude-code-router 1.0.18 → 1.0.20
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 +187 -127
- package/README_zh.md +312 -0
- package/config.example.json +78 -0
- package/dist/cli.js +834 -617
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,94 +1,87 @@
|
|
|
1
1
|
# Claude Code Router
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[中文版](README_zh.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> A powerful tool to route Claude Code requests to different models and customize any request.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+

|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## ✨ Features
|
|
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.
|
|
17
|
+
|
|
18
|
+
## 🚀 Getting Started
|
|
19
|
+
|
|
20
|
+
### 1. Installation
|
|
21
|
+
|
|
22
|
+
First, ensure you have [Claude Code](https://docs.anthropic.com/en/docs/claude-code/quickstart) installed:
|
|
10
23
|
|
|
11
24
|
```shell
|
|
12
25
|
npm install -g @anthropic-ai/claude-code
|
|
13
26
|
```
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
Then, install Claude Code Router:
|
|
16
29
|
|
|
17
30
|
```shell
|
|
18
31
|
npm install -g @musistudio/claude-code-router
|
|
19
32
|
```
|
|
20
33
|
|
|
21
|
-
|
|
34
|
+
### 2. Configuration
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
ccr code
|
|
25
|
-
```
|
|
36
|
+
Create and configure your `~/.claude-code-router/config.json` file. For more details, you can refer to `config.example.json`.
|
|
26
37
|
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
The `config.json` file has several key sections:
|
|
39
|
+
- **`PROXY_URL`** (optional): You can set a proxy for API requests, for example: `"PROXY_URL": "http://127.0.0.1:7890"`.
|
|
40
|
+
- **`LOG`** (optional): You can enable logging by setting it to `true`. The log file will be located at `$HOME/.claude-code-router.log`.
|
|
41
|
+
- **`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"`.
|
|
42
|
+
- **`HOST`** (optional): You can set the host address for the server. If `APIKEY` is not set, the host will be forced to `127.0.0.1` for security reasons to prevent unauthorized access. Example: `"HOST": "0.0.0.0"`.
|
|
43
|
+
|
|
44
|
+
- **`Providers`**: Used to configure different model providers.
|
|
45
|
+
- **`Router`**: Used to set up routing rules. `default` specifies the default model, which will be used for all requests if no other route is configured.
|
|
46
|
+
|
|
47
|
+
Here is a comprehensive example:
|
|
29
48
|
|
|
30
49
|
```json
|
|
31
50
|
{
|
|
51
|
+
"APIKEY": "your-secret-key",
|
|
52
|
+
"PROXY_URL": "http://127.0.0.1:7890",
|
|
53
|
+
"LOG": true,
|
|
32
54
|
"Providers": [
|
|
33
55
|
{
|
|
34
56
|
"name": "openrouter",
|
|
35
|
-
// IMPORTANT: api_base_url must be a complete (full) URL.
|
|
36
57
|
"api_base_url": "https://openrouter.ai/api/v1/chat/completions",
|
|
37
58
|
"api_key": "sk-xxx",
|
|
38
59
|
"models": [
|
|
39
60
|
"google/gemini-2.5-pro-preview",
|
|
40
61
|
"anthropic/claude-sonnet-4",
|
|
41
|
-
"anthropic/claude-3.5-sonnet"
|
|
42
|
-
"anthropic/claude-3.7-sonnet:thinking"
|
|
62
|
+
"anthropic/claude-3.5-sonnet"
|
|
43
63
|
],
|
|
44
|
-
"transformer": {
|
|
45
|
-
"use": ["openrouter"]
|
|
46
|
-
}
|
|
64
|
+
"transformer": { "use": ["openrouter"] }
|
|
47
65
|
},
|
|
48
66
|
{
|
|
49
67
|
"name": "deepseek",
|
|
50
|
-
// IMPORTANT: api_base_url must be a complete (full) URL.
|
|
51
68
|
"api_base_url": "https://api.deepseek.com/chat/completions",
|
|
52
69
|
"api_key": "sk-xxx",
|
|
53
70
|
"models": ["deepseek-chat", "deepseek-reasoner"],
|
|
54
71
|
"transformer": {
|
|
55
72
|
"use": ["deepseek"],
|
|
56
|
-
"deepseek-chat": {
|
|
57
|
-
// Enhance tool usage for the deepseek-chat model using the ToolUse transformer.
|
|
58
|
-
"use": ["tooluse"]
|
|
59
|
-
}
|
|
73
|
+
"deepseek-chat": { "use": ["tooluse"] }
|
|
60
74
|
}
|
|
61
75
|
},
|
|
62
76
|
{
|
|
63
77
|
"name": "ollama",
|
|
64
|
-
// IMPORTANT: api_base_url must be a complete (full) URL.
|
|
65
78
|
"api_base_url": "http://localhost:11434/v1/chat/completions",
|
|
66
79
|
"api_key": "ollama",
|
|
67
80
|
"models": ["qwen2.5-coder:latest"]
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"name": "gemini",
|
|
71
|
-
// IMPORTANT: api_base_url must be a complete (full) URL.
|
|
72
|
-
"api_base_url": "https://generativelanguage.googleapis.com/v1beta/models/",
|
|
73
|
-
"api_key": "sk-xxx",
|
|
74
|
-
"models": ["gemini-2.5-flash", "gemini-2.5-pro"],
|
|
75
|
-
"transformer": {
|
|
76
|
-
"use": ["gemini"]
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"name": "volcengine",
|
|
81
|
-
// IMPORTANT: api_base_url must be a complete (full) URL.
|
|
82
|
-
"api_base_url": "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
|
|
83
|
-
"api_key": "sk-xxx",
|
|
84
|
-
"models": ["deepseek-v3-250324", "deepseek-r1-250528"],
|
|
85
|
-
"transformer": {
|
|
86
|
-
"use": ["deepseek"]
|
|
87
|
-
}
|
|
88
81
|
}
|
|
89
82
|
],
|
|
90
83
|
"Router": {
|
|
91
|
-
"default": "deepseek,deepseek-chat",
|
|
84
|
+
"default": "deepseek,deepseek-chat",
|
|
92
85
|
"background": "ollama,qwen2.5-coder:latest",
|
|
93
86
|
"think": "deepseek,deepseek-reasoner",
|
|
94
87
|
"longContext": "openrouter,google/gemini-2.5-pro-preview"
|
|
@@ -96,34 +89,120 @@ ccr code
|
|
|
96
89
|
}
|
|
97
90
|
```
|
|
98
91
|
|
|
99
|
-
- `background`
|
|
100
|
-
This model will be used to handle some background tasks([background-token-usage](https://docs.anthropic.com/en/docs/claude-code/costs#background-token-usage)). Based on my tests, it doesn’t require high intelligence. I’m using the qwen-coder-2.5:7b model running locally on my MacBook Pro M1 (32GB) via Ollama.
|
|
101
|
-
If your computer can’t run Ollama, you can also use some free models, such as qwen-coder-2.5:3b.
|
|
102
92
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
93
|
+
### 3. Running Claude Code with the Router
|
|
94
|
+
|
|
95
|
+
Start Claude Code using the router:
|
|
96
|
+
|
|
97
|
+
```shell
|
|
98
|
+
ccr code
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### Providers
|
|
102
|
+
|
|
103
|
+
The `Providers` array is where you define the different model providers you want to use. Each provider object requires:
|
|
104
|
+
|
|
105
|
+
- `name`: A unique name for the provider.
|
|
106
|
+
- `api_base_url`: The full API endpoint for chat completions.
|
|
107
|
+
- `api_key`: Your API key for the provider.
|
|
108
|
+
- `models`: A list of model names available from this provider.
|
|
109
|
+
- `transformer` (optional): Specifies transformers to process requests and responses.
|
|
110
|
+
|
|
111
|
+
#### Transformers
|
|
112
|
+
|
|
113
|
+
Transformers allow you to modify the request and response payloads to ensure compatibility with different provider APIs.
|
|
114
|
+
|
|
115
|
+
- **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.
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"name": "openrouter",
|
|
119
|
+
"api_base_url": "https://openrouter.ai/api/v1/chat/completions",
|
|
120
|
+
"api_key": "sk-xxx",
|
|
121
|
+
"models": [
|
|
122
|
+
"google/gemini-2.5-pro-preview",
|
|
123
|
+
"anthropic/claude-sonnet-4",
|
|
124
|
+
"anthropic/claude-3.5-sonnet"
|
|
125
|
+
],
|
|
126
|
+
"transformer": { "use": ["openrouter"] }
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
- **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.
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"name": "deepseek",
|
|
133
|
+
"api_base_url": "https://api.deepseek.com/chat/completions",
|
|
134
|
+
"api_key": "sk-xxx",
|
|
135
|
+
"models": ["deepseek-chat", "deepseek-reasoner"],
|
|
136
|
+
"transformer": {
|
|
137
|
+
"use": ["deepseek"],
|
|
138
|
+
"deepseek-chat": { "use": ["tooluse"] }
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- **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.
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"name": "siliconflow",
|
|
147
|
+
"api_base_url": "https://api.siliconflow.cn/v1/chat/completions",
|
|
148
|
+
"api_key": "sk-xxx",
|
|
149
|
+
"models": ["moonshotai/Kimi-K2-Instruct"],
|
|
150
|
+
"transformer": {
|
|
151
|
+
"use": [
|
|
152
|
+
[
|
|
153
|
+
"maxtoken",
|
|
154
|
+
{
|
|
155
|
+
"max_tokens": 16384
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Available Built-in Transformers:**
|
|
164
|
+
|
|
165
|
+
- `deepseek`: Adapts requests/responses for DeepSeek API.
|
|
166
|
+
- `gemini`: Adapts requests/responses for Gemini API.
|
|
167
|
+
- `maxtoken`: Sets a specific `max_tokens` value.
|
|
168
|
+
- `openrouter`: Adapts requests/responses for OpenRouter API.
|
|
169
|
+
- `tooluse`: Optimizes tool usage for certain models.
|
|
170
|
+
- `gemini-cli` (experimental): Unofficial support for Gemini via Gemini CLI [gemini-cli.js](https://gist.github.com/musistudio/1c13a65f35916a7ab690649d3df8d1cd).
|
|
171
|
+
|
|
172
|
+
**Custom Transformers:**
|
|
173
|
+
|
|
174
|
+
You can also create your own transformers and load them via the `transformers` field in `config.json`.
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"transformers": [
|
|
179
|
+
{
|
|
180
|
+
"path": "$HOME/.claude-code-router/plugins/gemini-cli.js",
|
|
181
|
+
"options": {
|
|
182
|
+
"project": "xxx"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Router
|
|
107
190
|
|
|
108
|
-
|
|
109
|
-
This model will be used when the context length exceeds 32K (this value may be modified in the future). You can route the request to a model that performs well with long contexts (I’ve chosen google/gemini-2.5-pro-preview). This scenario has not been thoroughly tested yet, so if you encounter any issues, please submit an issue.
|
|
191
|
+
The `Router` object defines which model to use for different scenarios:
|
|
110
192
|
|
|
111
|
-
- model
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
193
|
+
- `default`: The default model for general tasks.
|
|
194
|
+
- `background`: A model for background tasks. This can be a smaller, local model to save costs.
|
|
195
|
+
- `think`: A model for reasoning-heavy tasks, like Plan Mode.
|
|
196
|
+
- `longContext`: A model for handling long contexts (e.g., > 60K tokens).
|
|
115
197
|
|
|
116
|
-
|
|
198
|
+
You can also switch models dynamically in Claude Code with the `/model` command:
|
|
199
|
+
`/model provider_name,model_name`
|
|
200
|
+
Example: `/model openrouter,anthropic/claude-3.5-sonnet`
|
|
117
201
|
|
|
118
|
-
- [x] Support change models
|
|
119
|
-
- [x] Github Actions
|
|
120
|
-
- [ ] More detailed logs
|
|
121
|
-
- [ ] Support image
|
|
122
|
-
- [ ] Support web search
|
|
123
202
|
|
|
124
|
-
##
|
|
203
|
+
## 🤖 GitHub Actions
|
|
125
204
|
|
|
126
|
-
|
|
205
|
+
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:
|
|
127
206
|
|
|
128
207
|
```yaml
|
|
129
208
|
name: Claude Code
|
|
@@ -131,20 +210,13 @@ name: Claude Code
|
|
|
131
210
|
on:
|
|
132
211
|
issue_comment:
|
|
133
212
|
types: [created]
|
|
134
|
-
|
|
135
|
-
types: [created]
|
|
136
|
-
issues:
|
|
137
|
-
types: [opened, assigned]
|
|
138
|
-
pull_request_review:
|
|
139
|
-
types: [submitted]
|
|
213
|
+
# ... other triggers
|
|
140
214
|
|
|
141
215
|
jobs:
|
|
142
216
|
claude:
|
|
143
217
|
if: |
|
|
144
218
|
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
145
|
-
|
|
146
|
-
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
147
|
-
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
219
|
+
# ... other conditions
|
|
148
220
|
runs-on: ubuntu-latest
|
|
149
221
|
permissions:
|
|
150
222
|
contents: read
|
|
@@ -182,70 +254,58 @@ jobs:
|
|
|
182
254
|
env:
|
|
183
255
|
ANTHROPIC_BASE_URL: http://localhost:3456
|
|
184
256
|
with:
|
|
185
|
-
anthropic_api_key: "
|
|
257
|
+
anthropic_api_key: "any-string-is-ok"
|
|
186
258
|
```
|
|
187
259
|
|
|
188
|
-
|
|
189
|
-
GitHub Actions support allows you to trigger Claude Code at specific times, which opens up some interesting possibilities.
|
|
190
|
-
|
|
191
|
-
For example, between 00:30 and 08:30 Beijing Time, using the official DeepSeek API:
|
|
192
|
-
|
|
193
|
-
- The cost of the `deepseek-v3` model is only 50% of the normal time.
|
|
194
|
-
|
|
195
|
-
- The `deepseek-r1` model is just 25% of the normal time.
|
|
196
|
-
|
|
197
|
-
So maybe in the future, I’ll describe detailed tasks for Claude Code ahead of time and let it run during these discounted hours to reduce costs?
|
|
198
|
-
|
|
199
|
-
## Some tips:
|
|
200
|
-
|
|
201
|
-
Now you can use deepseek-v3 models directly without using any plugins.
|
|
202
|
-
|
|
203
|
-
If you’re using the DeepSeek API provided by the official website, you might encounter an “exceeding context” error after several rounds of conversation (since the official API only supports a 64K context window). In this case, you’ll need to discard the previous context and start fresh. Alternatively, you can use ByteDance’s DeepSeek API, which offers a 128K context window and supports KV cache.
|
|
204
|
-
|
|
205
|
-

|
|
206
|
-
|
|
207
|
-
Note: claude code consumes a huge amount of tokens, but thanks to DeepSeek’s low cost, you can use claude code at a fraction of Claude’s price, and you don’t need to subscribe to the Claude Max plan.
|
|
208
|
-
|
|
209
|
-
Some interesting points: Based on my testing, including a lot of context information can help narrow the performance gap between these LLM models. For instance, when I used Claude-4 in VSCode Copilot to handle a Flutter issue, it messed up the files in three rounds of conversation, and I had to roll everything back. However, when I used claude code with DeepSeek, after three or four rounds of conversation, I finally managed to complete my task—and the cost was less than 1 RMB!
|
|
260
|
+
This setup allows for interesting automations, like running tasks during off-peak hours to reduce API costs.
|
|
210
261
|
|
|
211
|
-
##
|
|
262
|
+
## 📝 Further Reading
|
|
212
263
|
|
|
213
|
-
|
|
214
|
-
|
|
264
|
+
- [Project Motivation and How It Works](blog/en/project-motivation-and-how-it-works.md)
|
|
265
|
+
- [Maybe We Can Do More with the Router](blog/en/maybe-we-can-do-more-with-the-route.md)
|
|
215
266
|
|
|
216
|
-
##
|
|
267
|
+
## ❤️ Support & Sponsoring
|
|
217
268
|
|
|
218
|
-
If you find this project helpful,
|
|
269
|
+
If you find this project helpful, please consider sponsoring its development. Your support is greatly appreciated!
|
|
219
270
|
|
|
220
271
|
[](https://ko-fi.com/F1F31GN2GM)
|
|
221
272
|
|
|
222
273
|
<table>
|
|
223
274
|
<tr>
|
|
224
|
-
<td><img src="/blog/images/alipay.jpg" width="200" /></td>
|
|
225
|
-
<td><img src="/blog/images/wechat.jpg" width="200" /></td>
|
|
275
|
+
<td><img src="/blog/images/alipay.jpg" width="200" alt="Alipay" /></td>
|
|
276
|
+
<td><img src="/blog/images/wechat.jpg" width="200" alt="WeChat Pay" /></td>
|
|
226
277
|
</tr>
|
|
227
278
|
</table>
|
|
228
279
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
@Simon Leischnig
|
|
234
|
-
[@duanshuaimin](https://github.com/duanshuaimin)
|
|
235
|
-
[@vrgitadmin](https://github.com/vrgitadmin)
|
|
236
|
-
|
|
237
|
-
[@ceilwoo](https://github.com/ceilwoo)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
@K
|
|
241
|
-
@R
|
|
242
|
-
[@bobleer](https://github.com/bobleer)
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
[@Clarence-pan](https://github.com/Clarence-pan)
|
|
246
|
-
[@carter003](https://github.com/carter003)
|
|
247
|
-
@S
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
@Z
|
|
251
|
-
|
|
280
|
+
### Our Sponsors
|
|
281
|
+
|
|
282
|
+
A huge thank you to all our sponsors for their generous support!
|
|
283
|
+
|
|
284
|
+
- @Simon Leischnig
|
|
285
|
+
- [@duanshuaimin](https://github.com/duanshuaimin)
|
|
286
|
+
- [@vrgitadmin](https://github.com/vrgitadmin)
|
|
287
|
+
- @*o
|
|
288
|
+
- [@ceilwoo](https://github.com/ceilwoo)
|
|
289
|
+
- @*说
|
|
290
|
+
- @*更
|
|
291
|
+
- @K*g
|
|
292
|
+
- @R*R
|
|
293
|
+
- [@bobleer](https://github.com/bobleer)
|
|
294
|
+
- @*苗
|
|
295
|
+
- @*划
|
|
296
|
+
- [@Clarence-pan](https://github.com/Clarence-pan)
|
|
297
|
+
- [@carter003](https://github.com/carter003)
|
|
298
|
+
- @S*r
|
|
299
|
+
- @*晖
|
|
300
|
+
- @*敏
|
|
301
|
+
- @Z*z
|
|
302
|
+
- @*然
|
|
303
|
+
- [@cluic](https://github.com/cluic)
|
|
304
|
+
- @*苗
|
|
305
|
+
- [@PromptExpert](https://github.com/PromptExpert)
|
|
306
|
+
- @*应
|
|
307
|
+
- [@yusnake](https://github.com/yusnake)
|
|
308
|
+
- @*飞
|
|
309
|
+
- @董*
|
|
310
|
+
|
|
311
|
+
(If your name is masked, please contact me via my homepage email to update it with your GitHub username.)
|