@thxp/claude-code-router 2.0.0

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 ADDED
@@ -0,0 +1,706 @@
1
+ ![](blog/images/claude-code-router-img.png)
2
+
3
+ [![](https://img.shields.io/badge/%F0%9F%87%A8%F0%9F%87%B3-%E4%B8%AD%E6%96%87%E7%89%88-ff0000?style=flat)](README_zh.md)
4
+ [![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white)](https://discord.gg/rdftVMaUcS)
5
+ [![](https://img.shields.io/github/license/musistudio/claude-code-router)](https://github.com/musistudio/claude-code-router/blob/main/LICENSE)
6
+
7
+ <hr>
8
+
9
+ ![](blog/images/sponsors/glm-en.jpg)
10
+ > This project is sponsored by Z.ai, supporting us with their GLM CODING PLAN.
11
+
12
+ > GLM CODING PLAN is a subscription service designed for AI coding, starting at just $10/month. It provides access to their flagship GLM-4.7 & (GLM-5 Only Available for Pro Users)model across 10+ popular AI coding tools (Claude Code, Cline, Roo Code, etc.), offering developers top-tier, fast, and stable coding experiences.
13
+
14
+ > Get 10% OFF GLM CODING PLAN:https://z.ai/subscribe?ic=8JVLJQFSKB
15
+
16
+ > [Progressive Disclosure of Agent Tools from the Perspective of CLI Tool Style](/blog/en/progressive-disclosure-of-agent-tools-from-the-perspective-of-cli-tool-style.md)
17
+
18
+ > A powerful tool to route Claude Code requests to different models and customize any request.
19
+
20
+ ![](blog/images/claude-code.png)
21
+
22
+ ## ✨ Features
23
+
24
+ - **Model Routing**: Route requests to different models based on your needs (e.g., background tasks, thinking, long context).
25
+ - **Multi-Provider Support**: Supports various model providers like OpenRouter, DeepSeek, Ollama, Gemini, Volcengine, and SiliconFlow.
26
+ - **Request/Response Transformation**: Customize requests and responses for different providers using transformers.
27
+ - **Dynamic Model Switching**: Switch models on-the-fly within Claude Code using the `/model` command.
28
+ - **CLI Model Management**: Manage models and providers directly from the terminal with `ccr model`.
29
+ - **GitHub Actions Integration**: Trigger Claude Code tasks in your GitHub workflows.
30
+ - **Plugin System**: Extend functionality with custom transformers.
31
+
32
+ ## 🚀 Getting Started
33
+
34
+ ### 1. Installation
35
+
36
+ First, ensure you have [Claude Code](https://docs.anthropic.com/en/docs/claude-code/quickstart) installed:
37
+
38
+ ```shell
39
+ npm install -g @anthropic-ai/claude-code
40
+ ```
41
+
42
+ Then, install Claude Code Router:
43
+
44
+ ```shell
45
+ npm install -g @thxp/claude-code-router
46
+ ```
47
+
48
+ ### 2. Configuration
49
+
50
+ Create and configure your `~/.claude-code-router/config.json` file. For more details, you can refer to `config.example.json`.
51
+
52
+ The `config.json` file has several key sections:
53
+
54
+ - **`PROXY_URL`** (optional): You can set a proxy for API requests, for example: `"PROXY_URL": "http://127.0.0.1:7890"`.
55
+ - **`LOG`** (optional): You can enable logging by setting it to `true`. When set to `false`, no log files will be created. Default is `true`.
56
+ - **`LOG_LEVEL`** (optional): Set the logging level. Available options are: `"fatal"`, `"error"`, `"warn"`, `"info"`, `"debug"`, `"trace"`. Default is `"debug"`.
57
+ - **Logging Systems**: The Claude Code Router uses two separate logging systems:
58
+ - **Server-level logs**: HTTP requests, API calls, and server events are logged using pino in the `~/.claude-code-router/logs/` directory with filenames like `ccr-*.log`
59
+ - **Application-level logs**: Routing decisions and business logic events are logged in `~/.claude-code-router/claude-code-router.log`
60
+ - **`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"`.
61
+ - **`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"`.
62
+ - **`NON_INTERACTIVE_MODE`** (optional): When set to `true`, enables compatibility with non-interactive environments like GitHub Actions, Docker containers, or other CI/CD systems. This sets appropriate environment variables (`CI=true`, `FORCE_COLOR=0`, etc.) and configures stdin handling to prevent the process from hanging in automated environments. Example: `"NON_INTERACTIVE_MODE": true`.
63
+
64
+ - **`Providers`**: Used to configure different model providers.
65
+ - **`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.
66
+ - **`API_TIMEOUT_MS`**: Specifies the timeout for API calls in milliseconds.
67
+
68
+ #### Environment Variable Interpolation
69
+
70
+ Claude Code Router supports environment variable interpolation for secure API key management. You can reference environment variables in your `config.json` using either `$VAR_NAME` or `${VAR_NAME}` syntax:
71
+
72
+ ```json
73
+ {
74
+ "OPENAI_API_KEY": "$OPENAI_API_KEY",
75
+ "GEMINI_API_KEY": "${GEMINI_API_KEY}",
76
+ "Providers": [
77
+ {
78
+ "name": "openai",
79
+ "api_base_url": "https://api.openai.com/v1/chat/completions",
80
+ "api_key": "$OPENAI_API_KEY",
81
+ "models": ["gpt-5", "gpt-5-mini"]
82
+ }
83
+ ]
84
+ }
85
+ ```
86
+
87
+ This allows you to keep sensitive API keys in environment variables instead of hardcoding them in configuration files. The interpolation works recursively through nested objects and arrays.
88
+
89
+ Here is a comprehensive example:
90
+
91
+ ```json
92
+ {
93
+ "APIKEY": "your-secret-key",
94
+ "PROXY_URL": "http://127.0.0.1:7890",
95
+ "LOG": true,
96
+ "API_TIMEOUT_MS": 600000,
97
+ "NON_INTERACTIVE_MODE": false,
98
+ "Providers": [
99
+ {
100
+ "name": "openrouter",
101
+ "api_base_url": "https://openrouter.ai/api/v1/chat/completions",
102
+ "api_key": "sk-xxx",
103
+ "models": [
104
+ "google/gemini-2.5-pro-preview",
105
+ "anthropic/claude-sonnet-4",
106
+ "anthropic/claude-3.5-sonnet",
107
+ "anthropic/claude-3.7-sonnet:thinking"
108
+ ],
109
+ "transformer": {
110
+ "use": ["openrouter"]
111
+ }
112
+ },
113
+ {
114
+ "name": "deepseek",
115
+ "api_base_url": "https://api.deepseek.com/chat/completions",
116
+ "api_key": "sk-xxx",
117
+ "models": ["deepseek-chat", "deepseek-reasoner"],
118
+ "transformer": {
119
+ "use": ["deepseek"],
120
+ "deepseek-chat": {
121
+ "use": ["tooluse"]
122
+ }
123
+ }
124
+ },
125
+ {
126
+ "name": "ollama",
127
+ "api_base_url": "http://localhost:11434/v1/chat/completions",
128
+ "api_key": "ollama",
129
+ "models": ["qwen2.5-coder:latest"]
130
+ },
131
+ {
132
+ "name": "gemini",
133
+ "api_base_url": "https://generativelanguage.googleapis.com/v1beta/models/",
134
+ "api_key": "sk-xxx",
135
+ "models": ["gemini-2.5-flash", "gemini-2.5-pro"],
136
+ "transformer": {
137
+ "use": ["gemini"]
138
+ }
139
+ },
140
+ {
141
+ "name": "volcengine",
142
+ "api_base_url": "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
143
+ "api_key": "sk-xxx",
144
+ "models": ["deepseek-v3-250324", "deepseek-r1-250528"],
145
+ "transformer": {
146
+ "use": ["deepseek"]
147
+ }
148
+ },
149
+ {
150
+ "name": "modelscope",
151
+ "api_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
152
+ "api_key": "",
153
+ "models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "Qwen/Qwen3-235B-A22B-Thinking-2507"],
154
+ "transformer": {
155
+ "use": [
156
+ [
157
+ "maxtoken",
158
+ {
159
+ "max_tokens": 65536
160
+ }
161
+ ],
162
+ "enhancetool"
163
+ ],
164
+ "Qwen/Qwen3-235B-A22B-Thinking-2507": {
165
+ "use": ["reasoning"]
166
+ }
167
+ }
168
+ },
169
+ {
170
+ "name": "dashscope",
171
+ "api_base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
172
+ "api_key": "",
173
+ "models": ["qwen3-coder-plus"],
174
+ "transformer": {
175
+ "use": [
176
+ [
177
+ "maxtoken",
178
+ {
179
+ "max_tokens": 65536
180
+ }
181
+ ],
182
+ "enhancetool"
183
+ ]
184
+ }
185
+ },
186
+ {
187
+ "name": "aihubmix",
188
+ "api_base_url": "https://aihubmix.com/v1/chat/completions",
189
+ "api_key": "sk-",
190
+ "models": [
191
+ "Z/glm-4.5",
192
+ "claude-opus-4-20250514",
193
+ "gemini-2.5-pro"
194
+ ]
195
+ }
196
+ ],
197
+ "Router": {
198
+ "default": "deepseek,deepseek-chat",
199
+ "background": "ollama,qwen2.5-coder:latest",
200
+ "think": "deepseek,deepseek-reasoner",
201
+ "longContext": "openrouter,google/gemini-2.5-pro-preview",
202
+ "longContextThreshold": 60000,
203
+ "webSearch": "gemini,gemini-2.5-flash"
204
+ }
205
+ }
206
+ ```
207
+
208
+ ### 3. Running Claude Code with the Router
209
+
210
+ Start Claude Code using the router:
211
+
212
+ ```shell
213
+ ccr code
214
+ ```
215
+
216
+ > **Note**: After modifying the configuration file, you need to restart the service for the changes to take effect:
217
+ >
218
+ > ```shell
219
+ > ccr restart
220
+ > ```
221
+
222
+ ### 4. UI Mode
223
+
224
+ For a more intuitive experience, you can use the UI mode to manage your configuration:
225
+
226
+ ```shell
227
+ ccr ui
228
+ ```
229
+
230
+ This will open a web-based interface where you can easily view and edit your `config.json` file.
231
+
232
+ ![UI](/blog/images/ui.png)
233
+
234
+ ### 5. CLI Model Management
235
+
236
+ For users who prefer terminal-based workflows, you can use the interactive CLI model selector:
237
+
238
+ ```shell
239
+ ccr model
240
+ ```
241
+ ![](blog/images/models.gif)
242
+
243
+ This command provides an interactive interface to:
244
+
245
+ - View current configuration:
246
+ - See all configured models (default, background, think, longContext, webSearch, image)
247
+ - Switch models: Quickly change which model is used for each router type
248
+ - Add new models: Add models to existing providers
249
+ - Create new providers: Set up complete provider configurations including:
250
+ - Provider name and API endpoint
251
+ - API key
252
+ - Available models
253
+ - Transformer configuration with support for:
254
+ - Multiple transformers (openrouter, deepseek, gemini, etc.)
255
+ - Transformer options (e.g., maxtoken with custom limits)
256
+ - Provider-specific routing (e.g., OpenRouter provider preferences)
257
+
258
+ The CLI tool validates all inputs and provides helpful prompts to guide you through the configuration process, making it easy to manage complex setups without editing JSON files manually.
259
+
260
+ ### 6. Presets Management
261
+
262
+ Presets allow you to save, share, and reuse configurations easily. You can export your current configuration as a preset and install presets from files or URLs.
263
+
264
+ ```shell
265
+ # Export current configuration as a preset
266
+ ccr preset export my-preset
267
+
268
+ # Export with metadata
269
+ ccr preset export my-preset --description "My OpenAI config" --author "Your Name" --tags "openai,production"
270
+
271
+ # Install a preset from local directory
272
+ ccr preset install /path/to/preset
273
+
274
+ # List all installed presets
275
+ ccr preset list
276
+
277
+ # Show preset information
278
+ ccr preset info my-preset
279
+
280
+ # Delete a preset
281
+ ccr preset delete my-preset
282
+ ```
283
+
284
+ **Preset Features:**
285
+ - **Export**: Save your current configuration as a preset directory (with manifest.json)
286
+ - **Install**: Install presets from local directories
287
+ - **Sensitive Data Handling**: API keys and other sensitive data are automatically sanitized during export (marked as `{{field}}` placeholders)
288
+ - **Dynamic Configuration**: Presets can include input schemas for collecting required information during installation
289
+ - **Version Control**: Each preset includes version metadata for tracking updates
290
+
291
+ **Preset File Structure:**
292
+ ```
293
+ ~/.claude-code-router/presets/
294
+ ├── my-preset/
295
+ │ └── manifest.json # Contains configuration and metadata
296
+ ```
297
+
298
+ ### 7. Activate Command (Environment Variables Setup)
299
+
300
+ The `activate` command allows you to set up environment variables globally in your shell, enabling you to use the `claude` command directly or integrate Claude Code Router with applications built using the Agent SDK.
301
+
302
+ To activate the environment variables, run:
303
+
304
+ ```shell
305
+ eval "$(ccr activate)"
306
+ ```
307
+
308
+ This command outputs the necessary environment variables in shell-friendly format, which are then set in your current shell session. After activation, you can:
309
+
310
+ - **Use `claude` command directly**: Run `claude` commands without needing to use `ccr code`. The `claude` command will automatically route requests through Claude Code Router.
311
+ - **Integrate with Agent SDK applications**: Applications built with the Anthropic Agent SDK will automatically use the configured router and models.
312
+
313
+ The `activate` command sets the following environment variables:
314
+
315
+ - `ANTHROPIC_AUTH_TOKEN`: API key from your configuration
316
+ - `ANTHROPIC_BASE_URL`: The local router endpoint (default: `http://127.0.0.1:3456`)
317
+ - `NO_PROXY`: Set to `127.0.0.1` to prevent proxy interference
318
+ - `DISABLE_TELEMETRY`: Disables telemetry
319
+ - `DISABLE_COST_WARNINGS`: Disables cost warnings
320
+ - `API_TIMEOUT_MS`: API timeout from your configuration
321
+
322
+ > **Note**: Make sure the Claude Code Router service is running (`ccr start`) before using the activated environment variables. The environment variables are only valid for the current shell session. To make them persistent, you can add `eval "$(ccr activate)"` to your shell configuration file (e.g., `~/.zshrc` or `~/.bashrc`).
323
+
324
+ #### Providers
325
+
326
+ The `Providers` array is where you define the different model providers you want to use. Each provider object requires:
327
+
328
+ - `name`: A unique name for the provider.
329
+ - `api_base_url`: The full API endpoint for chat completions.
330
+ - `api_key`: Your API key for the provider.
331
+ - `models`: A list of model names available from this provider.
332
+ - `transformer` (optional): Specifies transformers to process requests and responses.
333
+
334
+ #### Transformers
335
+
336
+ Transformers allow you to modify the request and response payloads to ensure compatibility with different provider APIs.
337
+
338
+ - **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.
339
+ ```json
340
+ {
341
+ "name": "openrouter",
342
+ "api_base_url": "https://openrouter.ai/api/v1/chat/completions",
343
+ "api_key": "sk-xxx",
344
+ "models": [
345
+ "google/gemini-2.5-pro-preview",
346
+ "anthropic/claude-sonnet-4",
347
+ "anthropic/claude-3.5-sonnet"
348
+ ],
349
+ "transformer": { "use": ["openrouter"] }
350
+ }
351
+ ```
352
+ - **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.
353
+
354
+ ```json
355
+ {
356
+ "name": "deepseek",
357
+ "api_base_url": "https://api.deepseek.com/chat/completions",
358
+ "api_key": "sk-xxx",
359
+ "models": ["deepseek-chat", "deepseek-reasoner"],
360
+ "transformer": {
361
+ "use": ["deepseek"],
362
+ "deepseek-chat": { "use": ["tooluse"] }
363
+ }
364
+ }
365
+ ```
366
+
367
+ - **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.
368
+ ```json
369
+ {
370
+ "name": "siliconflow",
371
+ "api_base_url": "https://api.siliconflow.cn/v1/chat/completions",
372
+ "api_key": "sk-xxx",
373
+ "models": ["moonshotai/Kimi-K2-Instruct"],
374
+ "transformer": {
375
+ "use": [
376
+ [
377
+ "maxtoken",
378
+ {
379
+ "max_tokens": 16384
380
+ }
381
+ ]
382
+ ]
383
+ }
384
+ }
385
+ ```
386
+
387
+ **Available Built-in Transformers:**
388
+
389
+ - `Anthropic`:If you use only the `Anthropic` transformer, it will preserve the original request and response parameters(you can use it to connect directly to an Anthropic endpoint).
390
+ - `deepseek`: Adapts requests/responses for DeepSeek API.
391
+ - `gemini`: Adapts requests/responses for Gemini API.
392
+ - `openrouter`: Adapts requests/responses for OpenRouter API. It can also accept a `provider` routing parameter to specify which underlying providers OpenRouter should use. For more details, refer to the [OpenRouter documentation](https://openrouter.ai/docs/features/provider-routing). See an example below:
393
+ ```json
394
+ "transformer": {
395
+ "use": ["openrouter"],
396
+ "moonshotai/kimi-k2": {
397
+ "use": [
398
+ [
399
+ "openrouter",
400
+ {
401
+ "provider": {
402
+ "only": ["moonshotai/fp8"]
403
+ }
404
+ }
405
+ ]
406
+ ]
407
+ }
408
+ }
409
+ ```
410
+ - `groq`: Adapts requests/responses for groq API.
411
+ - `maxtoken`: Sets a specific `max_tokens` value.
412
+ - `tooluse`: Optimizes tool usage for certain models via `tool_choice`.
413
+ - `gemini-cli` (experimental): Unofficial support for Gemini via Gemini CLI [gemini-cli.js](https://gist.github.com/musistudio/1c13a65f35916a7ab690649d3df8d1cd).
414
+ - `reasoning`: Used to process the `reasoning_content` field.
415
+ - `sampling`: Used to process sampling information fields such as `temperature`, `top_p`, `top_k`, and `repetition_penalty`.
416
+ - `enhancetool`: Adds a layer of error tolerance to the tool call parameters returned by the LLM (this will cause the tool call information to no longer be streamed).
417
+ - `cleancache`: Clears the `cache_control` field from requests.
418
+ - `vertex-gemini`: Handles the Gemini API using Vertex authentication.
419
+ - `chutes-glm` Unofficial support for GLM 4.5 model via Chutes [chutes-glm-transformer.js](https://gist.github.com/vitobotta/2be3f33722e05e8d4f9d2b0138b8c863).
420
+ - `qwen-cli` (experimental): Unofficial support for qwen3-coder-plus model via Qwen CLI [qwen-cli.js](https://gist.github.com/musistudio/f5a67841ced39912fd99e42200d5ca8b).
421
+ - `rovo-cli` (experimental): Unofficial support for gpt-5 via Atlassian Rovo Dev CLI [rovo-cli.js](https://gist.github.com/SaseQ/c2a20a38b11276537ec5332d1f7a5e53).
422
+
423
+ **Custom Transformers:**
424
+
425
+ You can also create your own transformers and load them via the `transformers` field in `config.json`.
426
+
427
+ ```json
428
+ {
429
+ "transformers": [
430
+ {
431
+ "path": "/User/xxx/.claude-code-router/plugins/gemini-cli.js",
432
+ "options": {
433
+ "project": "xxx"
434
+ }
435
+ }
436
+ ]
437
+ }
438
+ ```
439
+
440
+ #### Router
441
+
442
+ The `Router` object defines which model to use for different scenarios:
443
+
444
+ - `default`: The default model for general tasks.
445
+ - `background`: A model for background tasks. This can be a smaller, local model to save costs.
446
+ - `think`: A model for reasoning-heavy tasks, like Plan Mode.
447
+ - `longContext`: A model for handling long contexts (e.g., > 60K tokens).
448
+ - `longContextThreshold` (optional): The token count threshold for triggering the long context model. Defaults to 60000 if not specified.
449
+ - `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.
450
+ - `image` (beta): Used for handling image-related tasks (supported by CCR’s built-in agent). If the model does not support tool calling, you need to set the `config.forceUseImageAgent` property to `true`.
451
+
452
+ - You can also switch models dynamically in Claude Code with the `/model` command:
453
+ `/model provider_name,model_name`
454
+ Example: `/model openrouter,anthropic/claude-3.5-sonnet`
455
+
456
+ #### Custom Router
457
+
458
+ For more advanced routing logic, you can specify a custom router script via the `CUSTOM_ROUTER_PATH` in your `config.json`. This allows you to implement complex routing rules beyond the default scenarios.
459
+
460
+ In your `config.json`:
461
+
462
+ ```json
463
+ {
464
+ "CUSTOM_ROUTER_PATH": "/User/xxx/.claude-code-router/custom-router.js"
465
+ }
466
+ ```
467
+
468
+ The custom router file must be a JavaScript module that exports an `async` function. This function receives the request object and the config object as arguments and should return the provider and model name as a string (e.g., `"provider_name,model_name"`), or `null` to fall back to the default router.
469
+
470
+ Here is an example of a `custom-router.js` based on `custom-router.example.js`:
471
+
472
+ ```javascript
473
+ // /User/xxx/.claude-code-router/custom-router.js
474
+
475
+ /**
476
+ * A custom router function to determine which model to use based on the request.
477
+ *
478
+ * @param {object} req - The request object from Claude Code, containing the request body.
479
+ * @param {object} config - The application's config object.
480
+ * @returns {Promise<string|null>} - A promise that resolves to the "provider,model_name" string, or null to use the default router.
481
+ */
482
+ module.exports = async function router(req, config) {
483
+ const userMessage = req.body.messages.find((m) => m.role === "user")?.content;
484
+
485
+ if (userMessage && userMessage.includes("explain this code")) {
486
+ // Use a powerful model for code explanation
487
+ return "openrouter,anthropic/claude-3.5-sonnet";
488
+ }
489
+
490
+ // Fallback to the default router configuration
491
+ return null;
492
+ };
493
+ ```
494
+
495
+ ##### Subagent Routing
496
+
497
+ For routing within subagents, you must specify a particular provider and model by including `<CCR-SUBAGENT-MODEL>provider,model</CCR-SUBAGENT-MODEL>` at the **beginning** of the subagent's prompt. This allows you to direct specific subagent tasks to designated models.
498
+
499
+ **Example:**
500
+
501
+ ```
502
+ <CCR-SUBAGENT-MODEL>openrouter,anthropic/claude-3.5-sonnet</CCR-SUBAGENT-MODEL>
503
+ Please help me analyze this code snippet for potential optimizations...
504
+ ```
505
+
506
+ ## Status Line (Beta)
507
+ To better monitor the status of claude-code-router at runtime, version v1.0.40 includes a built-in statusline tool, which you can enable in the UI.
508
+ ![statusline-config.png](/blog/images/statusline-config.png)
509
+
510
+ The effect is as follows:
511
+ ![statusline](/blog/images/statusline.png)
512
+
513
+ ## 🤖 GitHub Actions
514
+
515
+ 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:
516
+
517
+ ```yaml
518
+ name: Claude Code
519
+
520
+ on:
521
+ issue_comment:
522
+ types: [created]
523
+ # ... other triggers
524
+
525
+ jobs:
526
+ claude:
527
+ if: |
528
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
529
+ # ... other conditions
530
+ runs-on: ubuntu-latest
531
+ permissions:
532
+ contents: read
533
+ pull-requests: read
534
+ issues: read
535
+ id-token: write
536
+ steps:
537
+ - name: Checkout repository
538
+ uses: actions/checkout@v4
539
+ with:
540
+ fetch-depth: 1
541
+
542
+ - name: Prepare Environment
543
+ run: |
544
+ curl -fsSL https://bun.sh/install | bash
545
+ mkdir -p $HOME/.claude-code-router
546
+ cat << 'EOF' > $HOME/.claude-code-router/config.json
547
+ {
548
+ "log": true,
549
+ "NON_INTERACTIVE_MODE": true,
550
+ "OPENAI_API_KEY": "${{ secrets.OPENAI_API_KEY }}",
551
+ "OPENAI_BASE_URL": "https://api.deepseek.com",
552
+ "OPENAI_MODEL": "deepseek-chat"
553
+ }
554
+ EOF
555
+ shell: bash
556
+
557
+ - name: Start Claude Code Router
558
+ run: |
559
+ nohup ~/.bun/bin/bunx @thxp/claude-code-router@1.0.8 start &
560
+ shell: bash
561
+
562
+ - name: Run Claude Code
563
+ id: claude
564
+ uses: anthropics/claude-code-action@beta
565
+ env:
566
+ ANTHROPIC_BASE_URL: http://localhost:3456
567
+ with:
568
+ anthropic_api_key: "any-string-is-ok"
569
+ ```
570
+
571
+ > **Note**: When running in GitHub Actions or other automation environments, make sure to set `"NON_INTERACTIVE_MODE": true` in your configuration to prevent the process from hanging due to stdin handling issues.
572
+
573
+ This setup allows for interesting automations, like running tasks during off-peak hours to reduce API costs.
574
+
575
+ ## 📝 Further Reading
576
+
577
+ - [Project Motivation and How It Works](blog/en/project-motivation-and-how-it-works.md)
578
+ - [Maybe We Can Do More with the Router](blog/en/maybe-we-can-do-more-with-the-route.md)
579
+ - [GLM-4.6 Supports Reasoning and Interleaved Thinking](blog/en/glm-4.6-supports-reasoning.md)
580
+
581
+ ## ❤️ Support & Sponsoring
582
+
583
+ If you find this project helpful, please consider sponsoring its development. Your support is greatly appreciated!
584
+
585
+ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/F1F31GN2GM)
586
+
587
+ [Paypal](https://paypal.me/musistudio1999)
588
+
589
+ <table>
590
+ <tr>
591
+ <td><img src="/blog/images/alipay.jpg" width="200" alt="Alipay" /></td>
592
+ <td><img src="/blog/images/wechat.jpg" width="200" alt="WeChat Pay" /></td>
593
+ </tr>
594
+ </table>
595
+
596
+ ### Our Sponsors
597
+
598
+ A huge thank you to all our sponsors for their generous support!
599
+
600
+
601
+ - [AIHubmix](https://aihubmix.com/)
602
+ - [BurnCloud](https://ai.burncloud.com)
603
+ - [302.AI](https://share.302.ai/ZGVF9w)
604
+ - [Z智谱](https://www.bigmodel.cn/claude-code?ic=FPF9IVAGFJ)
605
+ - @Simon Leischnig
606
+ - [@duanshuaimin](https://github.com/duanshuaimin)
607
+ - [@vrgitadmin](https://github.com/vrgitadmin)
608
+ - @\*o
609
+ - [@ceilwoo](https://github.com/ceilwoo)
610
+ - @\*说
611
+ - @\*更
612
+ - @K\*g
613
+ - @R\*R
614
+ - [@bobleer](https://github.com/bobleer)
615
+ - @\*苗
616
+ - @\*划
617
+ - [@Clarence-pan](https://github.com/Clarence-pan)
618
+ - [@carter003](https://github.com/carter003)
619
+ - @S\*r
620
+ - @\*晖
621
+ - @\*敏
622
+ - @Z\*z
623
+ - @\*然
624
+ - [@cluic](https://github.com/cluic)
625
+ - @\*苗
626
+ - [@PromptExpert](https://github.com/PromptExpert)
627
+ - @\*应
628
+ - [@yusnake](https://github.com/yusnake)
629
+ - @\*飞
630
+ - @董\*
631
+ - @\*汀
632
+ - @\*涯
633
+ - @\*:-)
634
+ - @\*\*磊
635
+ - @\*琢
636
+ - @\*成
637
+ - @Z\*o
638
+ - @\*琨
639
+ - [@congzhangzh](https://github.com/congzhangzh)
640
+ - @\*\_
641
+ - @Z\*m
642
+ - @*鑫
643
+ - @c\*y
644
+ - @\*昕
645
+ - [@witsice](https://github.com/witsice)
646
+ - @b\*g
647
+ - @\*亿
648
+ - @\*辉
649
+ - @JACK
650
+ - @\*光
651
+ - @W\*l
652
+ - [@kesku](https://github.com/kesku)
653
+ - [@biguncle](https://github.com/biguncle)
654
+ - @二吉吉
655
+ - @a\*g
656
+ - @\*林
657
+ - @\*咸
658
+ - @\*明
659
+ - @S\*y
660
+ - @f\*o
661
+ - @\*智
662
+ - @F\*t
663
+ - @r\*c
664
+ - [@qierkang](http://github.com/qierkang)
665
+ - @\*军
666
+ - [@snrise-z](http://github.com/snrise-z)
667
+ - @\*王
668
+ - [@greatheart1000](http://github.com/greatheart1000)
669
+ - @\*王
670
+ - @zcutlip
671
+ - [@Peng-YM](http://github.com/Peng-YM)
672
+ - @\*更
673
+ - @\*.
674
+ - @F\*t
675
+ - @\*政
676
+ - @\*铭
677
+ - @\*叶
678
+ - @七\*o
679
+ - @\*青
680
+ - @\*\*晨
681
+ - @\*远
682
+ - @\*霄
683
+ - @\*\*吉
684
+ - @\*\*飞
685
+ - @\*\*驰
686
+ - @x\*g
687
+ - @\*\*东
688
+ - @\*落
689
+ - @哆\*k
690
+ - @\*涛
691
+ - [@苗大](https://github.com/WitMiao)
692
+ - @\*呢
693
+ - @\d*u
694
+ - @crizcraig
695
+ - s\*s
696
+ - \*火
697
+ - \*勤
698
+ - \*\*锟
699
+ - \*涛
700
+ - \*\*明
701
+ - \*知
702
+ - \*语
703
+ - \*瓜
704
+
705
+
706
+ (If your name is masked, please contact me via my homepage email to update it with your GitHub username.)