@musistudio/claude-code-router 1.0.19 → 1.0.21

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
@@ -1,111 +1,87 @@
1
1
  # Claude Code Router
2
2
 
3
- > This is a tool for routing Claude Code requests to different models, and you can customize any request.
3
+ [中文版](README_zh.md)
4
4
 
5
- ![](screenshoots/claude-code.png)
5
+ > A powerful tool to route Claude Code requests to different models and customize any request.
6
6
 
7
- ## Usage
7
+ ![](blog/images/claude-code.png)
8
8
 
9
- 1. Install Claude Code
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
- 2. Install Claude Code Router
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
- 3. Start Claude Code by claude-code-router
34
+ ### 2. Configuration
22
35
 
23
- ```shell
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`.
37
+
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.
26
46
 
27
- 4. Configure routing
28
- Set up your `~/.claude-code-router/config.json` file like this:
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
- },
89
- {
90
- "name": "siliconflow",
91
- // IMPORTANT: api_base_url must be a complete (full) URL.
92
- "api_base_url": "https://api.siliconflow.cn/v1/chat/completions",
93
- "api_key": "sk-xxx",
94
- "models": ["moonshotai/Kimi-K2-Instruct"],
95
- "transformer": {
96
- "use": [
97
- [
98
- "maxtoken",
99
- {
100
- "max_tokens": 16384 // for siliconflow max_tokens
101
- }
102
- ]
103
- ]
104
- }
105
81
  }
106
82
  ],
107
83
  "Router": {
108
- "default": "deepseek,deepseek-chat", // IMPORTANT OPENAI_MODEL has been deprecated
84
+ "default": "deepseek,deepseek-chat",
109
85
  "background": "ollama,qwen2.5-coder:latest",
110
86
  "think": "deepseek,deepseek-reasoner",
111
87
  "longContext": "openrouter,google/gemini-2.5-pro-preview"
@@ -113,83 +89,91 @@ ccr code
113
89
  }
114
90
  ```
115
91
 
116
- - `background`
117
- 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.
118
- If your computer can’t run Ollama, you can also use some free models, such as qwen-coder-2.5:3b.
119
92
 
120
- - `think`
121
- This model will be used when enabling Claude Code to perform reasoning. However, reasoning budget control has not yet been implemented (since the DeepSeek-R1 model does not support it), so there is currently no difference between using UltraThink and Think modes.
122
- It is worth noting that Plan Mode also use this model to achieve better planning results.
123
- Note: The reasoning process via the official DeepSeek API may be very slow, so you may need to wait for an extended period of time.
93
+ ### 3. Running Claude Code with the Router
124
94
 
125
- - `longContext`
126
- 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.
95
+ Start Claude Code using the router:
127
96
 
128
- - model command
129
- You can also switch models within Claude Code by using the `/model` command. The format is: `provider,model`, like this:
130
- `/model openrouter,anthropic/claude-3.5-sonnet`
131
- This will use the anthropic/claude-3.5-sonnet model provided by OpenRouter to handle all subsequent tasks.
132
-
133
- 5. About transformer
134
- `transformer` is used to convert requests and responses for different vendors. For different vendors, we can configure different transformers.
135
-
136
- For example, in the following case, we use the `openrouter` transformer for the OpenRouter vendor. This transformer removes the `cache_control` parameter (mainly used to adapt Claude's prompt cache) from the request for models other than Claude. In the response, it adapts the reasoning field.
137
- ```json
138
- {
139
- "name": "openrouter",
140
- "api_base_url": "https://openrouter.ai/api/v1/chat/completions",
141
- "api_key": "",
142
- "models": [
143
- "google/gemini-2.5-pro-preview",
144
- "anthropic/claude-sonnet-4",
145
- "anthropic/claude-3.5-sonnet",
146
- "anthropic/claude-3.7-sonnet:thinking",
147
- "deepseek/deepseek-chat-v3-0324"
148
- ],
149
- "transformer": {
150
- "use": [
151
- "openrouter"
152
- ]
153
- }
154
- }
155
- ```
156
- You can also configure transformers for different models of the same vendor. For instance, in the following example, we use the `deepseek` transformer for the DeepSeek vendor. This transformer sets the maximum value of `max_tokens` to `8192` in the request, and in the response, it adapts the `reasoning_content` field. Additionally, for the `deepseek-chat` model, we use the `tooluse` transformer, which optimizes the tool call for the `deepseek-v3` model using the `tool_choice` parameter (mainly because deepseek-r1 does not support the tool_choice parameter).
157
- ```json
158
- {
159
- "name": "deepseek",
160
- "api_base_url": "https://api.deepseek.com/chat/completions",
161
- "api_key": "",
162
- "models": [
163
- "deepseek-chat",
164
- "deepseek-reasoner"
165
- ],
166
- "transformer": {
167
- "use": [
168
- "deepseek"
169
- ],
170
- "deepseek-chat": {
171
- "use": [
172
- "tooluse"
173
- ]
174
- }
175
- }
176
- }
97
+ ```shell
98
+ ccr code
177
99
  ```
178
- Currently, the following transformers are available:
179
100
 
180
- - deepseek
181
-
182
- - gemini
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
+ ```
183
162
 
184
- - maxtoken
163
+ **Available Built-in Transformers:**
185
164
 
186
- - openrouter
165
+ - `deepseek`: Adapts requests/responses for DeepSeek API.
166
+ - `gemini`: Adapts requests/responses for Gemini API.
167
+ - `openrouter`: Adapts requests/responses for OpenRouter API.
168
+ - `groq`: Adapts requests/responses for groq API.
169
+ - `maxtoken`: Sets a specific `max_tokens` value.
170
+ - `tooluse`: Optimizes tool usage for certain models via `tool_choice`.
171
+ - `gemini-cli` (experimental): Unofficial support for Gemini via Gemini CLI [gemini-cli.js](https://gist.github.com/musistudio/1c13a65f35916a7ab690649d3df8d1cd).
187
172
 
188
- - tooluse
173
+ **Custom Transformers:**
189
174
 
190
- - gemini-cli (experimental, unofficial support: https://gist.github.com/musistudio/1c13a65f35916a7ab690649d3df8d1cd)
175
+ You can also create your own transformers and load them via the `transformers` field in `config.json`.
191
176
 
192
- You can configure custom transformers in the `config.json` file using the `transformers` field, for example:
193
177
  ```json
194
178
  {
195
179
  "transformers": [
@@ -203,17 +187,23 @@ You can configure custom transformers in the `config.json` file using the `trans
203
187
  }
204
188
  ```
205
189
 
206
- ## Features
190
+ #### Router
191
+
192
+ The `Router` object defines which model to use for different scenarios:
193
+
194
+ - `default`: The default model for general tasks.
195
+ - `background`: A model for background tasks. This can be a smaller, local model to save costs.
196
+ - `think`: A model for reasoning-heavy tasks, like Plan Mode.
197
+ - `longContext`: A model for handling long contexts (e.g., > 60K tokens).
207
198
 
208
- - [x] Support change models
209
- - [x] Github Actions
210
- - [ ] More detailed logs
211
- - [ ] Support image
212
- - [ ] Support web search
199
+ You can also switch models dynamically in Claude Code with the `/model` command:
200
+ `/model provider_name,model_name`
201
+ Example: `/model openrouter,anthropic/claude-3.5-sonnet`
213
202
 
214
- ## Github Actions
215
203
 
216
- You just need to install `Claude Code Actions` in your repository according to the [official documentation](https://docs.anthropic.com/en/docs/claude-code/github-actions). For `ANTHROPIC_API_KEY`, you can use any string. Then, modify your `.github/workflows/claude.yaml` file to include claude-code-router, like this:
204
+ ## 🤖 GitHub Actions
205
+
206
+ 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:
217
207
 
218
208
  ```yaml
219
209
  name: Claude Code
@@ -221,20 +211,13 @@ name: Claude Code
221
211
  on:
222
212
  issue_comment:
223
213
  types: [created]
224
- pull_request_review_comment:
225
- types: [created]
226
- issues:
227
- types: [opened, assigned]
228
- pull_request_review:
229
- types: [submitted]
214
+ # ... other triggers
230
215
 
231
216
  jobs:
232
217
  claude:
233
218
  if: |
234
219
  (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
235
- (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
236
- (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
237
- (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
220
+ # ... other conditions
238
221
  runs-on: ubuntu-latest
239
222
  permissions:
240
223
  contents: read
@@ -272,74 +255,61 @@ jobs:
272
255
  env:
273
256
  ANTHROPIC_BASE_URL: http://localhost:3456
274
257
  with:
275
- anthropic_api_key: "test"
258
+ anthropic_api_key: "any-string-is-ok"
276
259
  ```
277
260
 
278
- You can modify the contents of `$HOME/.claude-code-router/config.json` as needed.
279
- GitHub Actions support allows you to trigger Claude Code at specific times, which opens up some interesting possibilities.
280
-
281
- For example, between 00:30 and 08:30 Beijing Time, using the official DeepSeek API:
282
-
283
- - The cost of the `deepseek-v3` model is only 50% of the normal time.
284
-
285
- - The `deepseek-r1` model is just 25% of the normal time.
286
-
287
- 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?
288
-
289
- ## Some tips:
290
-
291
- Now you can use deepseek-v3 models directly without using any plugins.
292
-
293
- 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.
294
-
295
- ![](screenshoots/contexterror.jpg)
296
-
297
- 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.
298
-
299
- 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!
261
+ This setup allows for interesting automations, like running tasks during off-peak hours to reduce API costs.
300
262
 
301
- ## Some articles:
263
+ ## 📝 Further Reading
302
264
 
303
- 1. [Project Motivation and Principles](blog/en/project-motivation-and-how-it-works.md) ([项目初衷及原理](blog/zh/项目初衷及原理.md))
304
- 2. [Maybe We Can Do More with the Router](blog/en/maybe-we-can-do-more-with-the-route.md) ([或许我们能在 Router 中做更多事情](blog/zh/或许我们能在Router中做更多事情.md))
265
+ - [Project Motivation and How It Works](blog/en/project-motivation-and-how-it-works.md)
266
+ - [Maybe We Can Do More with the Router](blog/en/maybe-we-can-do-more-with-the-route.md)
305
267
 
306
- ## Buy me a coffee
268
+ ## ❤️ Support & Sponsoring
307
269
 
308
- If you find this project helpful, you can choose to sponsor the author with a cup of coffee. Please provide your GitHub information so I can add you to the sponsor list below.
270
+ If you find this project helpful, please consider sponsoring its development. Your support is greatly appreciated!
309
271
 
310
272
  [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/F1F31GN2GM)
311
273
 
312
274
  <table>
313
275
  <tr>
314
- <td><img src="/blog/images/alipay.jpg" width="200" /></td>
315
- <td><img src="/blog/images/wechat.jpg" width="200" /></td>
276
+ <td><img src="/blog/images/alipay.jpg" width="200" alt="Alipay" /></td>
277
+ <td><img src="/blog/images/wechat.jpg" width="200" alt="WeChat Pay" /></td>
316
278
  </tr>
317
279
  </table>
318
280
 
319
- ## Sponsors
320
-
321
- Thanks to the following sponsors for supporting the continued development of this project:
322
-
323
- @Simon Leischnig (If you see this, feel free to contact me and I can update it with your GitHub information)
324
- [@duanshuaimin](https://github.com/duanshuaimin)
325
- [@vrgitadmin](https://github.com/vrgitadmin)
326
- @\*o (可通过主页邮箱联系我修改 github 用户名)
327
- [@ceilwoo](https://github.com/ceilwoo)
328
- @\*说 (可通过主页邮箱联系我修改 github 用户名)
329
- @\*更 (可通过主页邮箱联系我修改 github 用户名)
330
- @K\*g (可通过主页邮箱联系我修改 github 用户名)
331
- @R\*R (可通过主页邮箱联系我修改 github 用户名)
332
- [@bobleer](https://github.com/bobleer)
333
- @\*苗 (可通过主页邮箱联系我修改 github 用户名)
334
- @\*划 (可通过主页邮箱联系我修改 github 用户名)
335
- [@Clarence-pan](https://github.com/Clarence-pan)
336
- [@carter003](https://github.com/carter003)
337
- @S\*r (可通过主页邮箱联系我修改 github 用户名)
338
- @\*晖 (可通过主页邮箱联系我修改 github 用户名)
339
- @\*敏 (可通过主页邮箱联系我修改 github 用户名)
340
- @Z\*z (可通过主页邮箱联系我修改 github 用户名)
341
- @\*然 (可通过主页邮箱联系我修改 github 用户名)
342
- [@cluic](https://github.com/cluic)
343
- @\*苗 (可通过主页邮箱联系我修改 github 用户名)
344
- [@PromptExpert](https://github.com/PromptExpert)
345
- @\*应 (可通过主页邮箱联系我修改 github 用户名)
281
+ ### Our Sponsors
282
+
283
+ A huge thank you to all our sponsors for their generous support!
284
+
285
+ - @Simon Leischnig
286
+ - [@duanshuaimin](https://github.com/duanshuaimin)
287
+ - [@vrgitadmin](https://github.com/vrgitadmin)
288
+ - @*o
289
+ - [@ceilwoo](https://github.com/ceilwoo)
290
+ - @*说
291
+ - @*更
292
+ - @K*g
293
+ - @R*R
294
+ - [@bobleer](https://github.com/bobleer)
295
+ - @*苗
296
+ - @*划
297
+ - [@Clarence-pan](https://github.com/Clarence-pan)
298
+ - [@carter003](https://github.com/carter003)
299
+ - @S*r
300
+ - @*晖
301
+ - @*敏
302
+ - @Z*z
303
+ - @*然
304
+ - [@cluic](https://github.com/cluic)
305
+ - @*苗
306
+ - [@PromptExpert](https://github.com/PromptExpert)
307
+ - @*应
308
+ - [@yusnake](https://github.com/yusnake)
309
+ - @*飞
310
+ - @董*
311
+ - *汀
312
+ - *涯
313
+ - *:-)
314
+
315
+ (If your name is masked, please contact me via my homepage email to update it with your GitHub username.)