@caeliq/claude-code-router 2.0.2 → 2.0.3
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 +91 -10
- package/dist/cli.js +901 -796
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## ✨ Features
|
|
6
6
|
|
|
7
7
|
- **Model Routing**: Route requests to different models based on your needs (e.g., background tasks, thinking, long context).
|
|
8
|
-
- **Multi-Provider Support**: Supports various model providers like OpenRouter, DeepSeek, Ollama, Gemini, Volcengine, SiliconFlow, Codex, Claude subscription, Qwen, Chrome On-Device, and Cursor (SDK).
|
|
8
|
+
- **Multi-Provider Support**: Supports various model providers like OpenRouter, DeepSeek, Ollama, Gemini, Antigravity, Volcengine, SiliconFlow, Codex, Claude subscription, Qwen, Chrome On-Device, and Cursor (SDK).
|
|
9
9
|
- **Request/Response Transformation**: Customize requests and responses for different providers using transformers.
|
|
10
10
|
- **Dynamic Model Switching**: Switch models on-the-fly within Claude Code using the `/model` command.
|
|
11
11
|
- **CLI Model Management**: Manage models and providers directly from the terminal with `ccr model`.
|
|
@@ -21,10 +21,11 @@ This fork is based on [claude-code-router](https://github.com/musistudio/claude-
|
|
|
21
21
|
- **Mistral Integration**: Added specific handling for Mistral's reasoning parameters and decoupled transformation logic.
|
|
22
22
|
- **Build & Deployment**: Integrated the UI package into the Docker build process and added a Docker Compose configuration.
|
|
23
23
|
- **Code Quality**: Localized codebase (English comments), improved error handling, and addressed Copilot review feedback.
|
|
24
|
-
- **Gemini Stability & Tool Use Fixes**: Corrected `thoughtSignature` placement in Gemini request bodies (
|
|
24
|
+
- **Gemini Stability & Tool Use Fixes**: Corrected `thoughtSignature` placement in Gemini request bodies (Gemini 3 expects it as a sibling field on the `functionCall` part itself, and validates only the first such part per step); filtered synthetic `ccr_` placeholder signatures from outgoing Gemini requests to prevent Gemini 500 errors; fixed `tool_result` content-array serialization in the Anthropic transformer so models receive plain text instead of JSON-wrapped arrays (resolves "Error editing file" in Claude Code); fixed Fastify `onSend` hook to prevent `invalid type 'object'` unhandled rejections on error responses.
|
|
25
25
|
- **Codex (ChatGPT) Integration**: Added Codex transformer for the ChatGPT backend API (Responses API), supporting both OAuth-based authentication (`ccr codex-auth`) and PAT auth via `api_key: "at-..."`, plus SSE streaming, reasoning/thinking content, tool calls with web search, and image handling.
|
|
26
26
|
- **Cursor SDK Integration**: Added `cursor-sdk` transformer that runs Cursor models in-process via `@cursor/sdk`. Default **bridge** mode keeps Claude Code as the tool host (Cursor built-ins denied); supports `plan` / `agent` modes, `crsr_` / `CURSOR_API_KEY` auth, `ccr model get cursor` model discovery, and Docker runtime install of the SDK native packages.
|
|
27
27
|
- **Claude Subscription Integration**: Added `claude-auth` support for routing through a Claude Pro or Max subscription via OAuth (`ccr claude-auth`), using the `claude-auth` + `Anthropic` transformer chain.
|
|
28
|
+
- **Antigravity Integration**: Added Google Antigravity OAuth via `ccr antigravity-auth`, with the `antigravity-auth` + `gemini` transformer chain targeting the Antigravity / `cloudcode-pa` API. Supports Gemini and Claude models under that quota, thought-signature round-tripping / fallback, and Claude tool-schema sanitization for Gemini-backed Claude models. Requires `gemini` options `{"cachedContent": false}` because Antigravity has no Google `cachedContents` resource (leaving the default `true` causes 404s).
|
|
28
29
|
- **Qwen Chat Integration**: Added `qwen-auth` transformer for the Qwen Chat backend (`qwen.aikit.club/v1/chat/completions`), supporting JWT-based authentication (`ccr qwen-auth`) where the user pastes a token copied from `chat.qwen.ai` localStorage, automatic token rotation, and stripping of the trailing `<details>...</details>` metadata block Qwen injects into responses.
|
|
29
30
|
- **DeepSeek Reasoning Replay**: Implemented mandatory reasoning replay for DeepSeek models (e.g., via OpenCode/ZenGo). DeepSeek requires previous assistant reasoning content to be included in subsequent requests — the `reasoning` transformer automatically replays reasoning output from prior turns.
|
|
30
31
|
- **Model Discovery**: Enabled non-interactive model discovery for arbitrary API providers. Using `ccr model get <provider>`, the tool automatically fetches remote models, parses custom JSON structures using configurable paths, and appends missing models to the local configuration while preserving existing settings.
|
|
@@ -324,16 +325,19 @@ The CLI tool validates all inputs and provides helpful prompts to guide you thro
|
|
|
324
325
|
For non-interactive model discovery, you can also test provider access and list remote models directly:
|
|
325
326
|
|
|
326
327
|
```shell
|
|
327
|
-
ccr model get
|
|
328
|
+
ccr model get claude
|
|
328
329
|
ccr model get gemini
|
|
330
|
+
ccr model get openai
|
|
329
331
|
```
|
|
330
332
|
|
|
331
333
|
This command:
|
|
332
334
|
- Calls the provider's model-list endpoint using the configured API key
|
|
333
335
|
- Prints the remote models returned by the provider
|
|
334
|
-
- Prompts to append
|
|
336
|
+
- Prompts to append missing models and remove configured models that the API no longer returns
|
|
335
337
|
|
|
336
|
-
Built-in endpoint support is included for `openai` and `
|
|
338
|
+
Built-in endpoint support is included for `anthropic`/`claude`, `gemini`, `openai`, `codex`, and `cursor`. For Claude subscription providers using `claude-auth`, discovery reads `~/.claude-code-router/claude_auth.json` and sends the required Anthropic OAuth beta headers; the provider `api_key` is only a placeholder in that mode. For other providers, you can configure `models_api_url` and a custom `models_response_format` to handle different JSON response structures.
|
|
339
|
+
|
|
340
|
+
For the `codex` provider, model discovery sends the current Codex CLI `client_version` because the ChatGPT backend can gate newly released Codex model slugs by client version. CCR defaults to the latest stable version known at release time; override it with `codex_client_version` on the provider or `CCR_CODEX_CLIENT_VERSION` when testing a newer Codex CLI rollout. Runtime Codex requests are handled separately by the core Codex transformer, which spoofs the Codex CLI request version and identity headers without depending on CCR's CLI package.
|
|
337
341
|
|
|
338
342
|
The `models_response_format` object supports:
|
|
339
343
|
- `listPath`: JSON path to the array of models (e.g., `"data"`, `"models"`, or `""` for root array)
|
|
@@ -361,10 +365,50 @@ You can also override these settings via CLI flags for testing:
|
|
|
361
365
|
ccr model get my-provider --list-path data --id-path id --strip-prefix "v1/"
|
|
362
366
|
```
|
|
363
367
|
|
|
364
|
-
If the provider returns
|
|
368
|
+
If the provider returns model changes, `ccr model get <provider>` can append missing entries and remove unavailable configured entries, each behind a separate confirmation prompt.
|
|
365
369
|
|
|
366
370
|
> **Note**: After syncing models into `config.json`, restart the service with `ccr restart` so the updated provider list is picked up by the running server.
|
|
367
371
|
|
|
372
|
+
#### Antigravity Authentication
|
|
373
|
+
|
|
374
|
+
Route Claude Code through Google's Antigravity gateway (`cloudcode-pa`) using account OAuth instead of an API key.
|
|
375
|
+
|
|
376
|
+
```shell
|
|
377
|
+
ccr antigravity-auth
|
|
378
|
+
# or, for headless/remote:
|
|
379
|
+
ccr antigravity-auth --manual
|
|
380
|
+
ccr antigravity-auth --project <gcp-project-id>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
This command:
|
|
384
|
+
1. Prints a Google OAuth URL (PKCE; callback `http://localhost:51121/oauth-callback`)
|
|
385
|
+
2. The CCR server handles the public `/oauth-callback` route (Docker maps `51121:3456`, like Codex `1455:3456`)
|
|
386
|
+
3. Tokens land in `~/.claude-code-router/antigravity_auth.json` (mounted config dir in Docker)
|
|
387
|
+
|
|
388
|
+
Example provider:
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"name": "antigravity",
|
|
393
|
+
"api_base_url": "https://daily-cloudcode-pa.sandbox.googleapis.com",
|
|
394
|
+
"api_key": "oauth",
|
|
395
|
+
"project_id": "$ANTIGRAVITY_PROJECT_ID",
|
|
396
|
+
"models": ["gemini-3-flash", "claude-sonnet-4-6", "claude-opus-4-6-thinking"],
|
|
397
|
+
"transformer": {
|
|
398
|
+
"use": [
|
|
399
|
+
["gemini", { "cachedContent": false, "thoughtSignatureFallback": "skip" }],
|
|
400
|
+
"antigravity-auth"
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Why those Gemini options:
|
|
407
|
+
- **`cachedContent: false`** — Antigravity has no Google `cachedContents` resource. The Gemini default is `true`; leaving it on causes 404s.
|
|
408
|
+
- **`thoughtSignatureFallback: "skip"`** — explicit form of the default. When a tool call is replayed without a cached `thoughtSignature`, CCR stamps Google's `skip_thought_signature_validator` sentinel so the gateway does not 400. Only change this to `"none"` if your endpoint rejects that sentinel.
|
|
409
|
+
|
|
410
|
+
> **Note**: Keep the CCR server running during auth. Using Antigravity IDE OAuth client credentials from a non-IDE client may violate Google's terms.
|
|
411
|
+
|
|
368
412
|
#### Codex Provider Authentication
|
|
369
413
|
|
|
370
414
|
The Codex provider supports two authentication modes:
|
|
@@ -384,7 +428,14 @@ This command:
|
|
|
384
428
|
1. Opens your browser to the OpenAI OAuth authorization page
|
|
385
429
|
2. After you sign in, the OAuth callback is handled by the running CCR server
|
|
386
430
|
3. Tokens are stored in `~/.claude-code-router/codex_auth.json`
|
|
387
|
-
4. The
|
|
431
|
+
4. The CLI and server independently refresh tokens five minutes before expiry
|
|
432
|
+
|
|
433
|
+
CCR derives the selected ChatGPT workspace and FedRAMP routing state from the
|
|
434
|
+
OAuth ID token. Runtime requests and `ccr model get codex` both send the same
|
|
435
|
+
Codex bearer, account, and routing headers. Refreshes use an atomic credential
|
|
436
|
+
file and a cross-process lock so a separately running CLI and server cannot
|
|
437
|
+
reuse the same rotating refresh token. A runtime OAuth 401 performs one guarded
|
|
438
|
+
credential reload/refresh retry.
|
|
388
439
|
|
|
389
440
|
> **Note**: The server must be running for `ccr codex-auth` to work, as it hosts the OAuth callback endpoint.
|
|
390
441
|
|
|
@@ -414,7 +465,16 @@ If your provider `api_key` starts with `at-`, CCR treats it as a Codex Personal
|
|
|
414
465
|
}
|
|
415
466
|
```
|
|
416
467
|
|
|
417
|
-
|
|
468
|
+
CCR resolves the PAT's account, user, plan, and FedRAMP metadata through
|
|
469
|
+
OpenAI's `/whoami` endpoint before calling the Codex backend. Both runtime
|
|
470
|
+
requests and `ccr model get codex` then send `Authorization`,
|
|
471
|
+
`ChatGPT-Account-ID`, and `X-OpenAI-Fedramp` when required. Metadata requests
|
|
472
|
+
are deduplicated and cached briefly by the server.
|
|
473
|
+
|
|
474
|
+
Auth mode is explicit: an `at-` value is always treated as a PAT. An invalid or
|
|
475
|
+
revoked PAT fails as PAT authentication and is never silently replaced with
|
|
476
|
+
OAuth. Any non-PAT placeholder selects OAuth tokens from
|
|
477
|
+
`~/.claude-code-router/codex_auth.json`.
|
|
418
478
|
|
|
419
479
|
> **See also**: Full Codex setup and troubleshooting are documented in `docs/docs/server/guides/codex.md`.
|
|
420
480
|
|
|
@@ -449,6 +509,9 @@ Example provider:
|
|
|
449
509
|
- **bridge** (default): Claude Code hosts tools; Cursor built-ins are denied in an isolated workspace under `~/.claude-code-router/cursor-sdk-workspaces/`
|
|
450
510
|
- Discover models with `ccr model get cursor` (lists via `Cursor.models.list`, not REST `/models`)
|
|
451
511
|
- Docker Compose passes `CURSOR_API_KEY` into the container when set; local Cursor sandboxing is forced off in Docker
|
|
512
|
+
- Cursor prompt caching is native to the held-open SDK agent session. CCR reports per-request token estimates to Claude Code and maps SDK cache-read deltas back as bounded Anthropic cache-read usage.
|
|
513
|
+
- Cursor thinking is forwarded from both SDK stream `thinking` messages and token-level `Agent.send({ onDelta })` `thinking-delta` updates, then closed with a synthetic signature so Claude Code can render it as Anthropic extended thinking. Claude Code 2.1.89+ hides interactive thinking summaries by default; enable `"showThinkingSummaries": true` in the settings file passed to Claude Code to display them. This is a client rendering setting: CCR still transports the thinking block when it is disabled.
|
|
514
|
+
- Stopping a Cursor response cancels the owned SDK run with bounded cleanup and invalidates unsafe SDK sessions; active-run send failures use Cursor's native `local.force` retry before CCR falls back to a fresh full-transcript session.
|
|
452
515
|
|
|
453
516
|
> **See also**: Full Cursor setup is documented in `docs/docs/server/guides/cursor.md`.
|
|
454
517
|
|
|
@@ -685,7 +748,9 @@ Transformers allow you to modify the request and response payloads to ensure com
|
|
|
685
748
|
|
|
686
749
|
- `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).
|
|
687
750
|
- `deepseek`: Adapts requests/responses for DeepSeek API.
|
|
688
|
-
- `gemini`: Adapts requests/responses for Gemini API.
|
|
751
|
+
- `gemini`: Adapts requests/responses for Gemini API (also the dialect stage used with Antigravity; same options apply to `vertex-gemini`). Claude Code's effort setting (sent as `output_config.effort`) drives thinking depth: `thinkingLevel` for Gemini 3+ (`low`/`high` on Gemini 3 Pro, plus `medium` on later Pro minors, plus `minimal` on Flash/Lite) or `thinkingBudget` for Gemini 2.5 and Claude-via-Antigravity — never both (the API rejects that mix). Efforts outside a family's range round up (`medium` on Gemini 3 Pro, `xhigh`/`max` anywhere → `high`), and the configured model id is never rewritten (a tier-pinned `gemini-3-pro-low` keeps talking to `gemini-3-pro-low`). Pass options as `["gemini", { ... }]`:
|
|
752
|
+
- **`cachedContent`** (boolean, default `true`): whether CCR may use Google's separate **`cachedContents` HTTP resource** to store/reuse prompt prefixes on the public Gemini API. This is Gemini server-side context cache — **not** Anthropic `cache_control` and **not** Claude Code's local prompt cache. Leave `true` for normal Gemini; set **`false` for Antigravity** (and any gateway without `cachedContents`) or you get 404s.
|
|
753
|
+
- **`thoughtSignatureFallback`** (`"skip"` \| `"none"`, default `"skip"`): what to do when a replayed tool call has no cached Gemini `thoughtSignature` (Claude Code's Anthropic `tool_use` cannot carry that field, so CCR caches signatures by tool-call id and restores them; a miss otherwise 400s). `"skip"` means stamp Google's documented sentinel `skip_thought_signature_validator` on the **first** `functionCall` of the step — the value name refers to that sentinel, **not** “disable the fallback.” Leave `"skip"` for Gemini/Antigravity; set `"none"` only if the endpoint rejects the sentinel (some Vertex). Real cached signatures are always preferred; the sentinel is a last resort.
|
|
689
754
|
- `mistral`: Adapts requests/responses for Mistral API.
|
|
690
755
|
- `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:
|
|
691
756
|
```json
|
|
@@ -719,6 +784,7 @@ Transformers allow you to modify the request and response payloads to ensure com
|
|
|
719
784
|
- `rovo-cli` (experimental): Unofficial support for gpt-5 via Atlassian Rovo Dev CLI [rovo-cli.js](https://gist.github.com/SaseQ/c2a20a38b11276537ec5332d1f7a5e53).
|
|
720
785
|
- `codex`: Adapts requests/responses for the Codex (ChatGPT) backend API. Supports OAuth via `ccr codex-auth` or PAT auth when `api_key` starts with `at-`.
|
|
721
786
|
- `claude-auth`: Authenticates requests to Anthropic's API using your Claude Pro or Max subscription OAuth token. Converts Unified format to Anthropic format and handles SSE response conversion. Use it together with `Anthropic` in the provider chain, and authenticate via `ccr claude-auth`.
|
|
787
|
+
- `antigravity-auth`: OAuth + envelope middleware for Google's Antigravity gateway (`cloudcode-pa`). Chain **after** `gemini`. For Antigravity you must set `cachedContent: false` on the Gemini stage (no `cachedContents` resource there); keep `thoughtSignatureFallback: "skip"` unless the endpoint rejects Google's thought-signature sentinel. Authenticate with `ccr antigravity-auth`.
|
|
722
788
|
- `chrome-on-device`: Routes requests to Chrome's on-device Gemini Nano model via the Prompt API. Uses `responseConstraint` for structured JSON output. Requires a bridge process running on the host (`ccr chrome-bridge`).
|
|
723
789
|
|
|
724
790
|
**Chrome On-Device Provider Configuration:**
|
|
@@ -984,6 +1050,21 @@ Please help me analyze this code snippet for potential optimizations...
|
|
|
984
1050
|
export CLAUDE_CODE_SUBAGENT_MODEL="openrouter,anthropic/claude-3.5-sonnet"
|
|
985
1051
|
```
|
|
986
1052
|
|
|
1053
|
+
## Prompt Caching
|
|
1054
|
+
|
|
1055
|
+
CCR translates Claude Code's Anthropic cache intent into each upstream's native caching mechanism automatically:
|
|
1056
|
+
|
|
1057
|
+
- Anthropic, Claude Auth, and Vertex Claude use Anthropic automatic prompt caching while preserving bounded explicit block markers.
|
|
1058
|
+
- OpenAI Chat and Responses use stable `prompt_cache_key` values; GPT-5.6+ models also receive explicit content breakpoints. Codex uses its separate native contract for every model: a stable prompt key plus session-routing headers, with no explicit content breakpoints.
|
|
1059
|
+
- OpenRouter uses sticky `session_id` routing plus model-native caching. Vercel AI Gateway receives `providerOptions.gateway.caching: "auto"`.
|
|
1060
|
+
- Mistral and Cerebras receive native `prompt_cache_key` values. Qwen/DashScope receives a final-content cache marker. DeepSeek, Groq, and Vertex OpenAI retain their native implicit caching.
|
|
1061
|
+
- Gemini and Vertex Gemini use implicit caching and create/reuse native CachedContent resources for sufficiently large stable system/tool prefixes.
|
|
1062
|
+
- Cursor SDK and Chrome On-Device reuse stable native sessions.
|
|
1063
|
+
|
|
1064
|
+
Provider-incompatible cache fields are removed only after translation. Cache read/write usage reported upstream is converted back to Anthropic `cache_read_input_tokens` and `cache_creation_input_tokens` for Claude Code.
|
|
1065
|
+
|
|
1066
|
+
See [the implementation plan and review](tasks/caching-plan.md) for the provider matrix and verification scope.
|
|
1067
|
+
|
|
987
1068
|
## Status Line (Beta)
|
|
988
1069
|
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.
|
|
989
1070
|

|
|
@@ -1057,4 +1138,4 @@ This setup allows for interesting automations, like running tasks during off-pea
|
|
|
1057
1138
|
|
|
1058
1139
|
- [Codex API](https://developers.openai.com/codex/sdk) — Developer docs for the ChatGPT backend API used by the `codex` transformer (OAuth PKCE, Responses API, streaming, tool calls)
|
|
1059
1140
|
- [Chrome Prompt API](https://developer.chrome.com/docs/ai/prompt-api) — On-device Gemini Nano API used by the `chrome-on-device` transformer and bridge
|
|
1060
|
-
- [Provider Integration Lessons](tasks/lessons.md) — Hard-won knowledge for LLM provider integrations (DeepSeek, Mistral, Gemini, Codex, Gemini Nano)
|
|
1141
|
+
- [Provider Integration Lessons](tasks/lessons.md) — Hard-won knowledge for LLM provider integrations (DeepSeek, Mistral, Gemini, Codex, Gemini Nano)
|