Refactor router pipeline and improve provider handling

This commit is contained in:
musi
2026-07-14 06:23:02 +08:00
parent e9f59c5425
commit f1930b249c
23 changed files with 1749 additions and 780 deletions
+21 -2
View File
@@ -85,7 +85,7 @@ Instead of wiring every agent to every model service by hand, CCR centralizes th
## Documentation
Read the full documentation at [ccrdesk.top](https://ccrdesk.top/).
Read the full documentation at [ccrdesk.top](https://ccrdesk.top/), including the [CLI reference](https://ccrdesk.top/en/guides/cli/) and [Docker deployment guide](https://ccrdesk.top/en/guides/docker/).
## Download And Install
@@ -98,12 +98,31 @@ Read the full documentation at [ccrdesk.top](https://ccrdesk.top/).
3. Install and launch **Claude Code Router**.
4. On first launch, CCR creates its local configuration database:
- macOS/Linux: `~/.claude-code-router/config.sqlite`
- Windows: `%APPDATA%\Claude Code Router\config.sqlite`
- Windows: `%APPDATA%\claude-code-router\config.sqlite`
CCR stores runtime configuration in SQLite. A legacy `config.json` is read only once for migration when no SQLite config exists.
After the service is started from the **Server** page, CCR listens on `http://127.0.0.1:3456` by default. The **Server** page controls the gateway `Host`, `Port`, proxy mode, system proxy, network capture, and CA certificate status.
## CLI And Docker
The npm CLI requires Node.js 22 or newer and provides the browser management UI, gateway, and Agent Config launch commands without Electron:
```sh
npm install -g @musistudio/claude-code-router
ccr ui
```
The CLI management UI defaults to `http://127.0.0.1:3458`, while its model gateway defaults to `http://127.0.0.1:3456`. See the [complete CLI reference](https://ccrdesk.top/en/guides/cli/) for background/foreground service commands, options, profile launching, authentication, and data locations.
To run the browser UI and gateway behind one Nginx port with persistent Docker storage:
```sh
docker compose up -d --build
```
Docker exposes both management and gateway routes at `http://127.0.0.1:3458` by default. Read the [Docker deployment guide](https://ccrdesk.top/en/guides/docker/) before remote exposure; it covers the internal port topology, management and gateway authentication, `CCR_PUBLIC_BASE_URL`, volumes, backup/restore, upgrades, and health checks.
## Quick Start
CCR can be configured entirely from the desktop UI. Use this setup order for a clean first run.
+21 -2
View File
@@ -85,7 +85,7 @@ Claude Code Router Desktop 是给编程 Agent 用的本地控制平面。它为
## 文档
完整文档见 [ccrdesk.top](https://ccrdesk.top/)。
完整文档见 [ccrdesk.top](https://ccrdesk.top/),其中包括 [CLI 命令参考](https://ccrdesk.top/guides/cli/) 和 [Docker 部署指南](https://ccrdesk.top/guides/docker/)
## 下载和安装
@@ -98,12 +98,31 @@ Claude Code Router Desktop 是给编程 Agent 用的本地控制平面。它为
3. 安装并启动 **Claude Code Router**
4. 首次启动后,CCR 会创建本地配置数据库:
- macOS/Linux`~/.claude-code-router/config.sqlite`
- Windows`%APPDATA%\Claude Code Router\config.sqlite`
- Windows`%APPDATA%\claude-code-router\config.sqlite`
CCR 的运行配置存储在 SQLite 中。旧版 `config.json` 只会在没有 SQLite 配置时作为迁移来源读取一次。
**服务** 页面启动后,CCR 默认监听 `http://127.0.0.1:3456`。**服务** 页面负责配置网关 `Host``Port`、代理模式、系统代理、网络捕获和 CA 证书状态。
## CLI 与 Docker
npm CLI 要求 Node.js 22 或更高版本,不依赖 Electron,也能提供浏览器管理界面、模型网关和 Agent 配置启动命令:
```sh
npm install -g @musistudio/claude-code-router
ccr ui
```
CLI 管理界面默认是 `http://127.0.0.1:3458`,模型网关默认是 `http://127.0.0.1:3456`。后台 / 前台服务、全部选项、Profile 启动、鉴权和数据位置见[完整 CLI 参考](https://ccrdesk.top/guides/cli/)。
如果要使用单一 Nginx 端口和持久化 Docker 数据卷运行管理 UI 与网关:
```sh
docker compose up -d --build
```
Docker 默认把管理和网关路径都发布在 `http://127.0.0.1:3458`。远程暴露前请先阅读 [Docker 部署指南](https://ccrdesk.top/guides/docker/),其中包含内部端口拓扑、管理与网关鉴权、`CCR_PUBLIC_BASE_URL`、数据卷、备份恢复、升级和健康检查。
## 快速开始
CCR 可以完全通过桌面 UI 完成配置。首次使用建议按下面顺序操作。
+305 -57
View File
@@ -1,68 +1,214 @@
# Docker deployment
# Docker Deployment
This image runs the core server package with PM2 and serves the built UI package
through Nginx. Nginx is the only published entrypoint: it serves the UI, proxies
management API calls to the internal core server, and proxies gateway API calls
to the internal gateway listener.
[中文说明](#中文说明) · [Project documentation](https://ccrdesk.top/en/) · [GitHub](https://github.com/musistudio/claude-code-router)
## Build and run
The Docker image runs the CCR core server under PM2 and serves the built management UI through Nginx. Nginx is the only public container entrypoint: the browser UI, management RPC, gateway API, and health route all share one published port.
The image is intended for a persistent gateway and browser-based administration. It does not include Electron, the npm `ccr` command, system tray features, desktop Agent/App launching, automatic desktop updates, or desktop-only browser integrations.
## Architecture And Ports
```text
host:3458 -> container Nginx:8080
|-> static management UI
|-> management RPC: 127.0.0.1:3459
|-> gateway: 127.0.0.1:3456
`-> gateway core: 127.0.0.1:3457
```
Only Nginx port `8080` should be published. The three internal ports are container implementation details and should not be exposed individually.
Nginx routes:
| Public route | Purpose |
| --- | --- |
| `/` and `/pages/home/index.html` | Browser management UI. `/` redirects to a URL containing the management token. |
| `/api/ccr/rpc` | Authenticated management RPC. |
| `/health` | Gateway health, not container/UI health. It can return `502` until a provider and model are configured and the gateway starts. |
| `/v1/*`, `/v1beta/*`, `/messages`, `/chat/completions`, `/responses`, `/interactions`, `/mcp/*` | Supported model and MCP gateway requests. |
## Quick Start With Compose
From the repository root:
```sh
docker compose up --build
docker compose up -d --build
docker compose logs -f ccr
```
Then open:
Open <http://127.0.0.1:3458>. On a new volume, the management UI is immediately available. Add a provider and model, create a CCR client key under **API Keys**, and start the gateway from **Server**.
- Web UI: <http://localhost:3458>
- Gateway endpoint: <http://localhost:3458>
`docker-compose.yml` publishes only Nginx (`3458:8080`). Behind Nginx, the image
runs separate container-private listeners for management RPC, API gateway
routing, and the core gateway runtime. They are implementation details and are
not published or configured by the default Compose file.
To use a different host port, change the Compose port mapping and keep the
public router endpoint in sync:
The repository Compose file publishes `3458:8080`, stores data in the `ccr-data` named volume, and restarts the service unless explicitly stopped. A mapping without a host IP binds on every host interface. For local-only access, change it to:
```yaml
services:
ccr:
ports:
- "8088:8080"
environment:
CCR_PUBLIC_BASE_URL: http://127.0.0.1:8088
ports:
- "127.0.0.1:3458:8080"
```
The container stores config and SQLite databases under `/data`, backed by the
`ccr-data` volume in `docker-compose.yml`.
Stop or remove the container without deleting its named volume:
On a fresh data volume, the Web UI starts immediately. The gateway endpoint is
available through the same Nginx entrypoint, but the gateway only starts after at
least one provider and model are configured.
```sh
docker compose stop
docker compose down
```
## Image scripts
Do not add `--volumes` to `docker compose down` unless you intentionally want to delete all persisted CCR data.
## `docker run`
Build and run without Compose:
```sh
docker build -t claude-code-router:local .
docker run -d \
--name claude-code-router \
--restart unless-stopped \
-p 127.0.0.1:3458:8080 \
-e CCR_PUBLIC_BASE_URL=http://127.0.0.1:3458 \
-v ccr-data:/data \
claude-code-router:local
```
Equivalent repository scripts are available:
```sh
npm run docker:build
npm run docker:run
```
## Smoke test
`npm run docker:run` uses port `3458` and the `ccr-data` volume, but runs an ephemeral container without a fixed name or restart policy.
```sh
npm run test:docker
## Authentication And Network Security
There are two independent authentication layers:
1. `CCR_WEB_AUTH_TOKEN` protects management RPC. Nginx puts it into the management-page URL, and the browser sends it to RPC as `x-ccr-web-auth`.
2. CCR client API keys created in the **API Keys** page protect model gateway requests. These are separate from upstream provider credentials.
If `CCR_WEB_AUTH_TOKEN` is unset, the entrypoint generates a new random token on each container start. Opening `/` still works because Nginx redirects to a tokenized URL, but a stable token is recommended for persistent or remote deployments.
Avoid putting the token directly in shell history. Create a protected environment file instead:
```dotenv
CCR_WEB_AUTH_TOKEN=replace-with-a-long-random-value
CCR_PUBLIC_BASE_URL=http://127.0.0.1:3458
```
The smoke test builds the image, starts an isolated temporary container with a
special-character `CCR_WEB_AUTH_TOKEN`, verifies that only the Nginx port is
published, checks UI and RPC authentication, confirms legacy Docker config is
migrated to the public Nginx router endpoint, and removes its temporary
container and volume. Set `CCR_DOCKER_TEST_SKIP_BUILD=1` to reuse an already
built image.
Then use it with `docker run --env-file` or map the same variables under the Compose service's `environment` section. Keep this file out of version control.
The Dockerfile uses `node:22-bookworm` for build and native SQLite dependency
installation, then copies the production dependencies into a smaller
`node:22-bookworm-slim` runtime image. To use different base images:
Security guidance:
- Bind the published port to `127.0.0.1` unless LAN or remote access is intentional.
- Never expose the management UI over untrusted networks without TLS, a firewall/private network, and a fixed strong management token.
- Treat tokenized management URLs as secrets; URLs may be recorded in browser history, proxy logs, screenshots, and support tickets.
- Create scoped CCR client API keys before exposing gateway routes. Do not reuse upstream provider credentials as client keys.
- Protect `/data` and its backups because they contain configuration, provider credentials, CCR client keys, request data, and generated certificates.
## Changing The Public Address
The host-facing URL is separate from the container's internal ports. Whenever the host port, hostname, or scheme changes, set `CCR_PUBLIC_BASE_URL` to the exact URL clients should use:
```yaml
services:
ccr:
ports:
- "127.0.0.1:8088:8080"
environment:
CCR_PUBLIC_BASE_URL: http://127.0.0.1:8088
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
`CCR_PUBLIC_BASE_URL` is written to CCR's public router endpoint. It does not publish a Docker port by itself.
For a reverse proxy or ingress that terminates HTTPS:
```yaml
services:
ccr:
ports:
- "127.0.0.1:3458:8080"
environment:
CCR_PUBLIC_BASE_URL: https://ccr.example.com
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
Proxy all paths to Nginx and preserve streaming. The external proxy should allow long-lived responses and should not buffer SSE/model streams. Keep the host port private when the reverse proxy is the public entrypoint.
## Persistent Data
The entrypoint sets `HOME=/data`, so CCR stores files under:
```text
/data/.claude-code-router/
├── config.sqlite
├── gateway.config.json
├── app-data/
│ ├── api-keys.sqlite
│ ├── request-logs.sqlite
│ ├── usage.sqlite
│ └── certs/
├── profiles/
└── bin/
```
Use a named volume unless a bind mount is operationally required. Bind mounts must be writable by the container and should not be shared by two running CCR containers.
The first-run bootstrap writes a minimal legacy `config.json` only when neither `config.json` nor `config.sqlite` exists. When the UI saves current settings, SQLite becomes authoritative. By default, every container start also synchronizes the stored gateway listener and `routerEndpoint` to the Docker public endpoint.
## Backup And Restore
The safest application-level backup is **Settings → Export data**. For a full volume backup, stop writes before copying the data directory:
```sh
docker compose stop ccr
docker compose cp ccr:/data/. ./ccr-data-backup/
docker compose start ccr
```
Keep the backup private. It contains secrets and may include request/response data.
For a full restore, use a new empty volume or empty `/data` directory, copy the backup contents into it while the CCR container is stopped, then start the container. Do not overlay an old backup onto a populated live volume: stale SQLite WAL/SHM files and newer runtime files can produce an inconsistent result. Make a second backup before replacing existing data.
## Upgrade And Rollback
Back up `/data`, update the source revision, rebuild with fresh base layers, and recreate the service:
```sh
git pull
docker compose build --pull
docker compose up -d
docker compose ps
docker compose logs --tail=200 ccr
```
Configuration migrations run against the persistent data. To roll back, use the previous image/source revision together with a backup created before the upgrade; do not assume a newer database can always be read by an older build.
## Environment Variables
Most deployments should set only `CCR_WEB_AUTH_TOKEN`, `CCR_PUBLIC_BASE_URL`, and the Docker port mapping. Internal listener values normally should remain unchanged.
| Variable | Default | Description |
| --- | --- | --- |
| `CCR_WEB_AUTH_TOKEN` | Random per container start | Management UI/RPC token. Set a stable strong value for persistent or remote use. |
| `CCR_PUBLIC_BASE_URL` | `http://127.0.0.1:3458` | Exact public gateway/UI base URL written into CCR configuration. Overrides `CCR_PUBLIC_HOST` and `CCR_PUBLIC_PORT`. |
| `CCR_PUBLIC_HOST` | `127.0.0.1` | Used only to derive `CCR_PUBLIC_BASE_URL` when the full URL is unset; it does not change Docker port publishing. |
| `CCR_PUBLIC_PORT` | `3458` | Used only to derive `CCR_PUBLIC_BASE_URL` when the full URL is unset. |
| `CCR_DATA_DIR` | `/data` | Container data root and process `HOME`. Mount persistent storage here. |
| `CCR_NGINX_PORT` | `8080` | Container-private Nginx listen port. Match the container side of the published mapping if changed. |
| `CCR_WEB_HOST` | `127.0.0.1` | Container-private management server host. |
| `CCR_WEB_PORT` | `3459` | Container-private management server port. |
| `CCR_GATEWAY_HOST` | `127.0.0.1` | Container-private gateway listener host. |
| `CCR_GATEWAY_PORT` | `3456` | Container-private gateway listener port used by Nginx. |
| `CCR_GATEWAY_CORE_PORT` | `3457` | Container-private core gateway runtime port. |
| `CCR_NO_GATEWAY` | `0` | Set to `1`, `true`, or `yes` to run the management UI without starting the gateway at boot. |
| `CCR_DOCKER_INIT_CONFIG` | `1` | Set to `0` to disable minimal first-run `config.json` bootstrap. |
| `CCR_DOCKER_SYNC_PUBLIC_ENDPOINT` | `1` | Set to `0` to stop startup from syncing existing JSON/SQLite listener and public endpoint fields to Docker values. |
Changing internal ports requires corresponding Nginx/PM2 variables and offers no benefit in normal deployments. Publish only `CCR_NGINX_PORT`.
## Build Options And Smoke Test
The Dockerfile builds native dependencies with `node:22-bookworm`, then copies production dependencies and built assets into `node:22-bookworm-slim`. Override the base images when required:
```sh
docker build \
@@ -71,21 +217,123 @@ docker build \
-t claude-code-router:local .
```
## Environment
Run the isolated Docker smoke test:
Most deployments only need the published Nginx port mapping, `CCR_WEB_AUTH_TOKEN`,
and optionally `CCR_PUBLIC_BASE_URL` when the host-facing URL is not
`http://127.0.0.1:3458`.
```sh
npm run test:docker
```
| Variable | Default | Description |
| --- | --- | --- |
| `CCR_WEB_AUTH_TOKEN` | generated | Shared management UI token used by Nginx redirects and the core server. |
| `CCR_PUBLIC_BASE_URL` | `http://127.0.0.1:3458` | Full public router endpoint override. Set this when changing the host-facing Compose port. |
| `CCR_DATA_DIR` | `/data` | Container data root. |
| `CCR_NO_GATEWAY` | `0` | Set to `1` to run only the Web UI management service. |
| `CCR_DOCKER_INIT_CONFIG` | `1` | Set to `0` to disable first-run `config.json` bootstrap. |
| `CCR_DOCKER_SYNC_PUBLIC_ENDPOINT` | `1` | Sync existing Docker config to the Nginx public router endpoint on startup. |
The test builds the image, starts a temporary container and volume, verifies that only Nginx is published, checks UI/RPC authentication, tests public-endpoint migration, starts a configured gateway, checks `/health`, and removes its resources. Set `CCR_DOCKER_TEST_SKIP_BUILD=1` to reuse an existing image or `CCR_DOCKER_TEST_IMAGE` to test a different local tag.
The first-run bootstrap writes a minimal legacy `config.json` only when neither
`config.json` nor `config.sqlite` exists in the mounted data directory. Once the
UI saves settings into SQLite, existing persisted configuration takes priority.
## Operations And Troubleshooting
Useful commands:
```sh
docker compose ps
docker compose logs -f ccr
docker compose restart ccr
docker compose config
```
### `/` returns `302`
This is expected. Nginx redirects the root URL to the management page and URL-encodes the management token.
### `/health` returns `502`
`/health` checks the model gateway, not Nginx or the management UI. On a fresh volume it returns `502` until a provider/model exists and the gateway has started. Use `docker compose ps` for container health and open the UI to configure/start the gateway.
### The UI returns `401` after a token change
Open the bare root URL again so Nginx creates a URL with the current token. Close stale tabs and avoid bookmarks that contain an old `ccr_web_token`.
### Clients still use the old port or hostname
Update `CCR_PUBLIC_BASE_URL` and recreate the container. Leave `CCR_DOCKER_SYNC_PUBLIC_ENDPOINT=1` so existing SQLite configuration is synchronized at startup.
### Configuration disappears after recreation
Confirm that `/data` is mounted and that the same named volume or bind-mount path is being reused. `docker compose down` keeps named volumes; `docker compose down --volumes` deletes them.
### A bind mount fails with permission errors
Verify that the host directory exists, is writable by the container, and is not mounted read-only. Named volumes avoid most host ownership and labeling issues.
### The container is healthy but model requests fail
Container health only verifies Nginx/UI reachability. Check **Server** status, provider connectivity, CCR client-key authentication, routing, and request logs. Then inspect `docker compose logs --tail=200 ccr` for startup or runtime errors.
---
## 中文说明
Docker 镜像通过 PM2 运行 CCR Core,并由 Nginx 同时提供管理 UI、管理 RPC、模型网关和健康检查。对外只应发布 Nginx 的容器端口 `8080``3459``3456``3457` 都是容器内部实现端口,不应单独暴露。
这个镜像面向常驻网关和浏览器管理,不包含 Electron、npm 的 `ccr` 命令、系统托盘、桌面 Agent/App 启动、桌面自动更新和桌面专属浏览器集成。
### 快速启动
```sh
docker compose up -d --build
docker compose logs -f ccr
```
打开 <http://127.0.0.1:3458>。首次启动时管理 UI 可以立即访问;添加供应商和模型、在 **API 密钥** 页面创建 CCR 客户端 Key,然后从 **服务** 页面启动网关。
仓库默认映射是 `3458:8080`,会监听宿主机所有网卡。如果只允许本机访问,请改为:
```yaml
ports:
- "127.0.0.1:3458:8080"
```
### 鉴权与远程访问
- `CCR_WEB_AUTH_TOKEN` 用于管理 UI / RPC;不设置时,每次容器启动都会生成新的随机 Token。
- **API 密钥** 页面创建的 CCR 客户端 Key 用于模型网关请求。
- 上游供应商凭据是第三类凭据,不应拿来代替 CCR 客户端 Key。
根路径会重定向到包含 `ccr_web_token` 的管理 URL。请把该 URL 当作密码。远程部署至少应使用固定强 Token、TLS、主机防火墙或私网,并让反向代理把全部路径转发到 Nginx。流式响应和 SSE 不应被代理缓冲。
外部端口、域名或协议变化时,必须同步设置公开地址:
```yaml
environment:
CCR_PUBLIC_BASE_URL: https://ccr.example.com
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
`CCR_PUBLIC_BASE_URL` 只负责写入客户端应使用的公开地址,不会自动发布 Docker 端口。
### 数据、备份与升级
数据实际位于 `/data/.claude-code-router/`,其中包括 `config.sqlite``app-data/`、Agent 配置和生成文件。优先使用命名卷,不要让两个运行中的 CCR 容器共享同一个数据目录。
完整文件备份前先停止写入:
```sh
docker compose stop ccr
docker compose cp ccr:/data/. ./ccr-data-backup/
docker compose start ccr
```
备份包含密钥和请求数据,必须按敏感数据保存。恢复时应复制到新的空卷或空 `/data`,不要把旧备份覆盖到仍有新数据的目录。升级前先备份,然后执行:
```sh
git pull
docker compose build --pull
docker compose up -d
docker compose ps
docker compose logs --tail=200 ccr
```
### 常见排查
- `/` 返回 `302`:正常,Nginx 正在跳转到带管理 Token 的页面。
- `/health` 返回 `502`:它检查的是模型网关;首次启动尚未配置模型时属于预期行为。
- 修改 Token 后 UI 返回 `401`:重新打开不带参数的根地址,关闭仍使用旧 Token 的标签页。
- 重建后配置消失:检查是否仍挂载同一个 `/data` 卷;`docker compose down --volumes` 会删除数据卷。
- 容器健康但模型请求失败:继续检查服务状态、供应商连通性、CCR 客户端 Key、路由和请求日志;容器健康只表示 Nginx / UI 可访问。
完整的环境变量、端口拓扑、远程部署、构建参数和烟雾测试说明见本页英文主体,对应变量名和命令在中英文环境中完全相同。
@@ -8,7 +8,9 @@ lead: Locate the SQLite configuration database maintained by the CCR desktop app
## Default Locations
- **macOS/Linux**: `~/.claude-code-router/config.sqlite`
- **Windows**: `%APPDATA%\Claude Code Router\config.sqlite`
- **Windows**: `%APPDATA%\claude-code-router\config.sqlite`
Docker sets `HOME=/data`, so its configuration database is `/data/.claude-code-router/config.sqlite`. Persist the complete `/data` directory rather than mounting only one database file.
## Applying Changes
@@ -5,6 +5,18 @@ eyebrow: Detailed Configuration
lead: Configure the CCR gateway host, port, and Proxy mode for MITM interception and proxying into CCR.
---
## Management And Gateway Addresses Are Separate
The Host/Port fields under **Server** configure the model gateway, not the browser management page:
| Distribution | Management entry | Model gateway |
| --- | --- | --- |
| Desktop | App window | `http://127.0.0.1:3456` by default |
| npm CLI | `http://127.0.0.1:3458` by default | `http://127.0.0.1:3456` by default |
| Docker | Public `http://127.0.0.1:3458` by default | Combined into the same public Nginx endpoint |
CLI `--host`/`--port` options configure management; this page configures the gateway. Docker internal listeners should not be published separately. See [Docker Deployment](../../guides/docker/).
## Main Fields
| Field | Capability |
@@ -12,6 +24,20 @@ lead: Configure the CCR gateway host, port, and Proxy mode for MITM interception
| Host | Host address the CCR gateway listens on. Common values are `127.0.0.1` and `0.0.0.0`. |
| Port | Gateway listening port. Clients should point their API base URL to this port. |
`127.0.0.1` allows local access only; `0.0.0.0` listens on every IPv4 interface. Use a wildcard only for intentional LAN/remote access, together with CCR client API keys, firewall/private-network controls, and TLS at a reverse proxy.
Management tokens, CCR client API keys, and upstream credentials are separate. Gateway clients use keys created under **API Keys** and should never receive upstream provider credentials.
## Start And Verify
1. Add at least one provider and model.
2. Create a client key under **API Keys**.
3. Click **Start** or **Restart**.
4. Confirm Running status and request the gateway `/health` route.
5. Send a minimal model request and inspect the resolved provider/model under Logs.
A reachable management UI does not prove the gateway is running. Docker returns `502` from `/health` until the gateway starts, and desktop/CLI can keep management available without usable models.
## Proxy Mode
Proxy mode is the local proxy capability. When enabled, clients can send HTTP/HTTPS traffic to CCR. CCR uses MITM interception to identify and decrypt HTTPS requests, then proxies supported model requests into the CCR gateway path.
@@ -26,3 +52,5 @@ Proxy mode is the local proxy capability. When enabled, clients can send HTTP/HT
| Check Trust | Checks again whether the proxy CA is trusted by the system. |
| Proxy status | Shows whether the proxy service is running. |
| Restart Proxy | Restarts the proxy service when proxy mode is enabled. |
Proxy mode changes local networking and certificate trust and is primarily a desktop feature. Container deployments should normally point clients directly at the public CCR Nginx gateway instead of trying to change the host system proxy or install a host CA from inside the container.
+7 -9
View File
@@ -7,17 +7,15 @@ lead: Start from installation, connect a provider, let agents send requests thro
## Install And Start CCR
### Download And Install
CCR is available as a desktop app, a Node.js 22+ npm CLI, and a single-entrypoint Docker deployment.
1. Open the [GitHub Releases](https://github.com/musistudio/claude-code-router/releases) page.
2. Download the package for your system: `.dmg` or `.zip` for macOS, `.exe` for Windows, and `.AppImage` for Linux.
3. Install and open **Claude Code Router** like a normal desktop app.
| Distribution | Start entry | Default management | Default model gateway |
| --- | --- | --- | --- |
| Desktop | App UI / `ccr-app` | In-app window | `http://127.0.0.1:3456` |
| npm CLI | `ccr ui` / `ccr serve` | `http://127.0.0.1:3458` | `http://127.0.0.1:3456` |
| Docker | `docker compose up -d --build` | Shared `http://127.0.0.1:3458` | Shared Nginx endpoint |
### Start The Service
Open the **Server** page and click **Start**. After the page shows Running, CCR listens on the default local address `http://localhost:8080`.
If you want the service to start when the app opens, enable **Auto start** on the Server page.
Use the [installation page](install/) to choose a distribution. See the [CLI reference](cli/) for terminal commands and [Docker Deployment](docker/) for container ports, authentication, persistence, and upgrades.
## Add A Provider
+161
View File
@@ -0,0 +1,161 @@
---
title: CLI Installation And Reference
pageTitle: CLI Installation And Reference
eyebrow: Quick Start
lead: Run the browser management UI and model gateway from npm, and launch locally installed agents through CCR profiles without Electron.
---
## `ccr` And `ccr-app`
CCR has two related commands:
| Command | Source | Primary use |
| --- | --- | --- |
| `ccr` | npm package `@musistudio/claude-code-router` | Electron-free management UI, gateway service, and profile launches. |
| `ccr-app` | CCR desktop application | Desktop-managed profile launcher used by commands copied from Agent Config cards. |
Both distributions use the same local configuration directory, but their command names are not interchangeable. Use the desktop app for tray features, notifications, automatic app updates, and desktop-only browser integrations. Use the npm CLI for headless hosts or external process supervision.
## Install, Upgrade, Or Remove
Node.js 22 or newer is required:
```sh
node --version
npm install -g @musistudio/claude-code-router
ccr --help
```
Upgrade or uninstall with npm:
```sh
npm install -g @musistudio/claude-code-router@latest
npm uninstall -g @musistudio/claude-code-router
```
Uninstalling the package does not delete local configuration or databases. If `ccr` is not found, run `npm prefix -g`, add npm's global binary directory to `PATH`, and open a new shell.
## First Start
Start the background service and open the UI:
```sh
ccr ui
```
For SSH or headless sessions:
```sh
ccr ui --no-open
```
Then add a provider/model, create a CCR client key under **API Keys**, configure routing if needed, and confirm the gateway is running under **Server**. The management UI defaults to `http://127.0.0.1:3458`; the model gateway defaults to `http://127.0.0.1:3456`.
The management token and CCR client keys are separate credentials. The first protects UI/RPC access; the second authenticates model gateway requests.
## Service Command Summary
| Command | Mode | Purpose |
| --- | --- | --- |
| `ccr start` | Background | Starts management and the gateway, then prints the authenticated management URL. |
| `ccr ui` | Background | Reuses or starts the background service and opens a browser. |
| `ccr stop` | One-shot | Stops the service created by `start` or `ui`. |
| `ccr serve` | Foreground | Runs in the current terminal for logs or process supervision. |
| `ccr web` | Foreground | Alias of `serve`. |
| `ccr <profile>` | Foreground | Launches an enabled Agent Config profile. |
## Service Options
```text
ccr start [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
ccr ui [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
ccr serve [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
ccr stop
```
| Option | Description |
| --- | --- |
| `--host <host>` | Management listener, default `127.0.0.1`. `--host=value` is also accepted. |
| `--port <port>` | Preferred management port, default `3458`. `--port=value` is also accepted. |
| `--open` / `--no-open` | Enables or disables browser opening. `ui` opens by default. |
| `--gateway` | Explicitly requests model gateway startup; this is the default. |
| `--no-gateway` | Starts management without starting the model gateway during service startup. |
When the preferred port is occupied, CCR tries following ports and prints the actual URL. `serve` handles `SIGINT` and `SIGTERM`; `ccr stop` manages only detached services.
## Background Service Reuse
`start` and `ui` store the process ID, URL, and a private service token in `service.json`. A later invocation verifies both the process and RPC identity before reuse.
- A valid service is reused rather than duplicated.
- New host, port, or `--no-gateway` options do not reconfigure an already running service.
- A command that requires the gateway can ask the existing management process to start it.
- Stale state is removed before a replacement service starts.
Stop first when changing listener settings:
```sh
ccr stop
ccr start --host 127.0.0.1 --port 3458
```
## Launch Agent Config Profiles
Create and enable a profile under **Agent Config**, then use:
```text
ccr <profile-name-or-id> [cli|app] [-- <agent arguments>]
```
Examples:
```sh
ccr "Codex - Work"
ccr "Codex - Work" app
ccr "Claude - Review" cli -- --model sonnet
ccr profile-id -- --help
```
- `--cli` and `--app` are alternatives to the positional surface.
- Put agent arguments after `--` to avoid ambiguity.
- Claude Code, Codex, and Grok default to CLI; ZCode defaults to App.
- Grok supports CLI only; ZCode supports App only.
- Claude App and ZCode App reject trailing agent arguments.
- App launches require a locally installed application and graphical session.
- Only enabled profiles are launchable. Use the profile ID when names are ambiguous.
Most profiles require the CCR gateway to be running. Grok CLI can create a managed temporary shared service and stops it after the final managed Grok session exits.
## Configuration And Data
| Platform | Configuration directory |
| --- | --- |
| macOS / Linux | `~/.claude-code-router` |
| Windows | `%APPDATA%\claude-code-router` |
Important paths include `config.sqlite`, `app-data/`, `service.json`, `gateway.config.json`, `profiles/`, and generated launch wrappers under `bin/`. Do not edit or copy live SQLite files. Use **Settings → Export data**, or stop CCR before taking a filesystem backup.
## Authentication And Remote Access
`CCR_WEB_HOST` and `CCR_WEB_PORT` provide defaults when command-line listener options are omitted. Set `CCR_WEB_AUTH_TOKEN` to keep a stable management UI/RPC token; otherwise a random token is generated for the process. The authenticated management URL contains `ccr_web_token`; treat the full URL as a password.
Keep the listener on `127.0.0.1` unless remote access is intentional. A remote deployment should use a strong fixed token, firewall/private network controls, and TLS at a trusted reverse proxy. Create separate CCR client API keys for gateway access and protect the data directory because it contains upstream credentials.
## Process Supervisors
Use `ccr serve --no-open` with an external supervisor. Fix the service user, `HOME`, listener, and `CCR_WEB_AUTH_TOKEN`. Do not also run a detached `ccr start` service, which can create a second management listener or make both processes compete for the same configuration.
## Troubleshooting
- **UI works but gateway requests fail:** add a provider/model and CCR client key, start the gateway under **Server**, and use `ccr serve` to inspect startup errors.
- **The UI is not on port 3458:** the preferred port was occupied; use the printed URL or stop the conflict.
- **Profile not found:** confirm it is enabled, use its ID when names are ambiguous, and re-save it if generated launchers are missing.
- **Old background options remain active:** run `ccr stop`, then start again with the new options.
- **A foreground service does not stop through `ccr stop`:** stop `ccr serve` from its terminal or supervisor.
## Related Pages
- [Install And Start CCR](../install/)
- [Agent Config](../../configuration/profiles/)
- [Server](../../configuration/server/)
- [Docker Deployment](../docker/)
+198
View File
@@ -0,0 +1,198 @@
---
title: Docker Deployment
pageTitle: Docker Deployment
eyebrow: Quick Start
lead: Run CCR Core and the browser UI behind a single Nginx entrypoint with documented ports, authentication, persistence, upgrades, and troubleshooting.
---
## Scope And Limitations
The image contains CCR Core, the built management UI, PM2, and Nginx. It is intended for a persistent model gateway and browser administration. It does not include Electron, the npm `ccr` command, tray features, host desktop Agent/App launching, desktop automatic updates, or desktop-only browser integrations.
Use the desktop distribution for local app profiles and tray workflows, or the [CLI](../cli/) for an Electron-free host command.
## Process And Port Topology
```text
host 3458 -> container Nginx 8080
|-> static management UI
|-> management RPC: 127.0.0.1:3459
|-> model gateway: 127.0.0.1:3456
`-> core runtime: 127.0.0.1:3457
```
Publish only container port `8080`. The other listeners are implementation details and should remain private.
| Public route | Purpose |
| --- | --- |
| `/`, `/pages/home/index.html` | Management UI. The root redirects to a tokenized page URL. |
| `/api/ccr/rpc` | Authenticated management RPC. |
| `/health` | Model gateway health, not UI/container health. |
| `/v1/*`, `/v1beta/*`, `/messages`, `/chat/completions`, `/responses`, `/interactions`, `/mcp/*` | Model and MCP gateway routes. |
## Start With Compose
From the repository root:
```sh
docker compose up -d --build
docker compose logs -f ccr
```
Open <http://127.0.0.1:3458>. Add a provider/model, create a CCR client key under **API Keys**, and start the gateway under **Server**. A fresh UI is available immediately, but `/health` can return `502` until the gateway has usable models.
Stop or remove the container without deleting its volume:
```sh
docker compose stop
docker compose down
```
Do not add `--volumes` unless all persisted CCR data should be deleted.
The repository mapping `3458:8080` binds every host interface. For local-only access, use:
```yaml
ports:
- "127.0.0.1:3458:8080"
```
## Authentication
CCR uses three distinct credential types:
| Credential | Purpose | Location |
| --- | --- | --- |
| `CCR_WEB_AUTH_TOKEN` | Management UI/RPC | Container environment |
| CCR client API key | Model gateway requests | **API Keys** page |
| Upstream credential | Requests from CCR to a provider | **Providers** page |
Without `CCR_WEB_AUTH_TOKEN`, the entrypoint generates a new random token for every container start. Opening `/` still works because Nginx redirects to a URL containing the current token. Use a fixed strong token for persistent or remote deployments.
Keep secrets out of shell history by using an ignored environment file:
```dotenv
CCR_WEB_AUTH_TOKEN=replace-with-a-long-random-value
CCR_PUBLIC_BASE_URL=http://127.0.0.1:3458
```
Pass it through `docker run --env-file` or the Compose service `environment`. Treat the complete management URL as a secret because `ccr_web_token` can be captured in browser history, proxy logs, screenshots, and tickets.
## Change The Public Address
Changing the host-facing port, hostname, or scheme also requires the exact client URL in `CCR_PUBLIC_BASE_URL`:
```yaml
services:
ccr:
ports:
- "127.0.0.1:8088:8080"
environment:
CCR_PUBLIC_BASE_URL: http://127.0.0.1:8088
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
`CCR_PUBLIC_BASE_URL` updates CCR's public router endpoint. It does not publish a Docker port.
For TLS at a reverse proxy or ingress, set the HTTPS URL and keep the host port private:
```yaml
environment:
CCR_PUBLIC_BASE_URL: https://ccr.example.com
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
Proxy every path, allow long-lived requests and adequate body sizes, and disable buffering for SSE/model streams. Add firewall, private-network, or equivalent access controls before exposing management to an untrusted network.
## Persistent Data
The entrypoint sets `HOME=/data`; CCR data is under `/data/.claude-code-router/`, including `config.sqlite`, `gateway.config.json`, `app-data/`, `profiles/`, and generated files under `bin/`.
Prefer a named volume. A bind mount must be writable by the container, and two running CCR containers must not share the same data directory.
On a completely empty volume, the entrypoint writes minimal bootstrap `config.json`. Once the UI saves configuration, SQLite is authoritative. Startup also synchronizes persisted listener/router endpoint fields to the Docker public address unless disabled.
## Backup, Restore, And Upgrade
Use **Settings → Export data** for an application-level backup. For a complete copy, stop writes first:
```sh
docker compose stop ccr
docker compose cp ccr:/data/. ./ccr-data-backup/
docker compose start ccr
```
The backup contains secrets and may contain request/response data. Restore into a new empty volume or empty `/data` while the container is stopped. Do not overlay an old copy onto populated live data because SQLite WAL/SHM and newer runtime files can be mixed.
Upgrade after backing up:
```sh
git pull
docker compose build --pull
docker compose up -d
docker compose ps
docker compose logs --tail=200 ccr
```
Rollback should pair the previous image/source revision with a pre-upgrade backup; an older build may not understand a newer database.
## Environment Reference
Most installations should change only `CCR_WEB_AUTH_TOKEN`, `CCR_PUBLIC_BASE_URL`, and the Docker port mapping.
| Variable | Default | Description |
| --- | --- | --- |
| `CCR_WEB_AUTH_TOKEN` | Random per start | Management UI/RPC token. |
| `CCR_PUBLIC_BASE_URL` | `http://127.0.0.1:3458` | Exact public URL written to CCR configuration. |
| `CCR_PUBLIC_HOST` | `127.0.0.1` | Used only to derive the public URL when the full URL is unset. |
| `CCR_PUBLIC_PORT` | `3458` | Used only to derive the public URL when the full URL is unset. |
| `CCR_DATA_DIR` | `/data` | Data root and process `HOME`. |
| `CCR_NGINX_PORT` | `8080` | Container-private Nginx port. |
| `CCR_WEB_HOST` | `127.0.0.1` | Container-private management host. |
| `CCR_WEB_PORT` | `3459` | Container-private management port. |
| `CCR_GATEWAY_HOST` | `127.0.0.1` | Container-private model gateway host. |
| `CCR_GATEWAY_PORT` | `3456` | Container-private model gateway port used by Nginx. |
| `CCR_GATEWAY_CORE_PORT` | `3457` | Container-private core runtime port. |
| `CCR_NO_GATEWAY` | `0` | `1`, `true`, or `yes` starts management without the gateway at boot. |
| `CCR_DOCKER_INIT_CONFIG` | `1` | `0` disables empty-volume bootstrap `config.json`. |
| `CCR_DOCKER_SYNC_PUBLIC_ENDPOINT` | `1` | `0` disables startup synchronization of persisted listener/public endpoint fields. |
Internal ports normally should not change. Publish only `CCR_NGINX_PORT`.
## Build And Smoke Test
```sh
docker build \
--build-arg NODE_IMAGE=node:22-bookworm \
--build-arg RUNTIME_NODE_IMAGE=node:22-bookworm-slim \
-t claude-code-router:local .
npm run test:docker
```
The smoke test creates temporary resources and verifies the single Nginx entrypoint, UI/RPC auth, public endpoint migration, gateway startup, and `/health`. Set `CCR_DOCKER_TEST_SKIP_BUILD=1` to reuse an image or `CCR_DOCKER_TEST_IMAGE` to select another local tag.
## Operations And Troubleshooting
```sh
docker compose ps
docker compose logs -f ccr
docker compose restart ccr
docker compose config
```
- **`/` returns `302`:** expected tokenized management-page redirect.
- **`/health` returns `502`:** the model gateway is not yet configured/running; this is separate from container health.
- **UI returns `401` after a token change:** reopen the bare root URL and close tabs/bookmarks containing the old token.
- **Clients use an old host/port:** update `CCR_PUBLIC_BASE_URL` and recreate the container with endpoint synchronization enabled.
- **Data disappears after recreation:** verify the same `/data` volume is mounted; `docker compose down --volumes` deletes it.
- **Bind mount permission errors:** ensure the host directory exists and is writable, or use a named volume.
- **Container is healthy but requests fail:** inspect Server status, provider connectivity, CCR client-key auth, routing, request logs, and `docker compose logs --tail=200 ccr`.
## Related Pages
- [Install And Start CCR](../install/)
- [CLI Installation And Reference](../cli/)
- [Server](../../configuration/server/)
- [API Keys](../../configuration/api-keys/)
+57 -8
View File
@@ -2,17 +2,66 @@
title: Install And Start CCR
pageTitle: Install And Start CCR
eyebrow: Quick Start
lead: Download the desktop app, install it, and start the local CCR service.
lead: Choose the desktop app, npm CLI, or Docker for the deployment, and distinguish the management address from the model gateway address.
---
## Download And Install
## Choose A Distribution
1. Open the [GitHub Releases](https://github.com/musistudio/claude-code-router/releases) page.
2. Download the package for your system: `.dmg` or `.zip` for macOS, `.exe` for Windows, and `.AppImage` for Linux.
3. Install and open **Claude Code Router** like a normal desktop app.
| Distribution | Best for | Entry | Default management address | Default gateway address |
| --- | --- | --- | --- | --- |
| Desktop app | Daily local use, tray, multi-instance Agent Apps, desktop integrations | App UI, `ccr-app` | In-app window | `http://127.0.0.1:3456` |
| npm CLI | Terminal, SSH, no Electron, external process supervisors | `ccr` | `http://127.0.0.1:3458` | `http://127.0.0.1:3456` |
| Docker | Persistent servers and container operations | Nginx | Shared public endpoint | `http://127.0.0.1:3458` with the default mapping |
## Start The Service
In desktop/CLI deployments, management and the model gateway do not use the same port. Do not use CLI management port `3458` as the default model gateway. Docker intentionally combines both through one Nginx endpoint.
Open the **Server** page and click **Start**. After the page shows Running, CCR listens on the default local address `http://localhost:8080`.
## Install The Desktop App
If you want the service to start when the app opens, enable **Auto start** on the Server page.
1. Open [GitHub Releases](https://github.com/musistudio/claude-code-router/releases).
2. Download `.dmg`/`.zip` for macOS, `.exe` for Windows, or `.AppImage` for Linux.
3. Install and open **Claude Code Router**.
4. Add a provider/model, create a client key under **API Keys**, then click **Start** under **Server**.
When Server shows Running, the model gateway defaults to `http://127.0.0.1:3456`. Enable automatic startup under Server if the gateway should start whenever the app opens.
## Install The npm CLI
Node.js 22 or newer is required:
```sh
npm install -g @musistudio/claude-code-router
ccr ui
```
`ccr ui` starts a background service and opens the browser. Use `ccr ui --no-open` on a headless host or `ccr serve --no-open` under a process supervisor. See [CLI Installation And Reference](../cli/) for all commands and profile launches.
## Use Docker
From a source checkout:
```sh
docker compose up -d --build
```
Open <http://127.0.0.1:3458>. Docker publishes one Nginx endpoint shared by management and the gateway. Add a provider/model, create a CCR client key, and start the gateway under Server. See [Docker Deployment](../docker/) for ports, authentication, persistence, backups, and remote access.
## Verify The Installation
After configuring a provider, model, and CCR client key:
1. Confirm Server shows Running.
2. Request `/health` on the deployment's gateway address and expect a `200` running response.
3. Send one minimal model request to a compatible endpoint using the CCR client key.
4. Confirm requested/resolved model, provider, status, and latency under Logs.
A reachable management UI does not prove that the model gateway is usable. Docker `/health` returning `502` is expected before a provider/model has been configured.
## Data Locations
| Distribution | Configuration location |
| --- | --- |
| Desktop / CLI on macOS or Linux | `~/.claude-code-router` |
| Desktop / CLI on Windows | `%APPDATA%\claude-code-router` |
| Docker | `/data/.claude-code-router`; persist `/data` |
Current configuration is stored in `config.sqlite`. Legacy `config.json` is only a migration source when SQLite does not exist, or an initial Docker bootstrap. Do not edit live SQLite files.
+6 -5
View File
@@ -12,7 +12,7 @@ The top navigation is split into four standalone pages:
| Page | Contents |
| --- | --- |
| [Documentation](./) | Product positioning, architecture overview, and reading path |
| [Quick Start](guides/) | From installation and provider setup to connecting an agent |
| [Quick Start](guides/) | Desktop, CLI, and Docker installation plus provider and Agent setup |
| [Detailed Configuration](configuration/overview/) | Overview dashboard, API keys, server, providers, routing, Agent Config, Fusion, Bots, tray, and config database location |
| [Q&A](troubleshooting/) | Request logs, observability panel, and common questions |
@@ -22,7 +22,8 @@ Bot platform guides are child pages under Detailed Configuration. Each platform
If this is your first time using CCR:
1. Start with [Quick Start](guides/) to connect a provider and Agent Config.
2. Use the app's request logs to confirm whether requests are passing through CCR.
3. Open [Detailed Configuration](configuration/overview/) for the overview dashboard, API keys, server, providers, vision, web search, MCP tools, tray, and IM relay.
4. Use [Q&A](troubleshooting/) for 401, 404, timeout, wrong-routing, or Bot delivery questions.
1. Choose desktop, npm CLI, or Docker on the [installation page](guides/install/), then use the dedicated [CLI](guides/cli/) or [Docker](guides/docker/) guide.
2. Continue through [Quick Start](guides/) to connect a provider and Agent Config.
3. Use request logs to confirm whether requests are passing through CCR.
4. Open [Detailed Configuration](configuration/overview/) for the overview dashboard, API keys, server, providers, vision, web search, MCP tools, tray, and IM relay.
5. Use [Q&A](troubleshooting/) for 401, 404, timeout, wrong-routing, or Bot delivery questions.
@@ -8,7 +8,9 @@ lead: 找到 CCR 桌面 App 默认维护的 SQLite 配置数据库。
## 默认位置
- macOS/Linux`~/.claude-code-router/config.sqlite`
- Windows`%APPDATA%\Claude Code Router\config.sqlite`
- Windows`%APPDATA%\claude-code-router\config.sqlite`
Docker 设置 `HOME=/data`,因此配置数据库位于 `/data/.claude-code-router/config.sqlite`;需要持久化挂载整个 `/data`,而不是只挂载单个数据库文件。
## 生效方式
@@ -5,6 +5,18 @@ eyebrow: 详细配置
lead: 配置 CCR 网关监听地址、端口,以及通过代理模式进行 MITM 劫持并代理到 CCR 的能力。
---
## 先区分管理地址和网关地址
**服务配置** 中的 Host / Port 指模型网关,不是浏览器管理页面:
| 运行方式 | 管理入口 | 模型网关 |
| --- | --- | --- |
| 桌面应用 | 应用窗口 | 默认 `http://127.0.0.1:3456` |
| npm CLI | 默认 `http://127.0.0.1:3458` | 默认 `http://127.0.0.1:3456` |
| Docker | 默认公开入口 `http://127.0.0.1:3458` | 由 Nginx 合并到同一公开入口 |
CLI 的 `--host` / `--port` 配置管理服务;本页字段配置模型网关。Docker 的内部管理和网关端口不应单独发布,详见 [Docker 部署](../../guides/docker/)。
## 主字段
| 字段 | 代表的能力 |
@@ -12,6 +24,20 @@ lead: 配置 CCR 网关监听地址、端口,以及通过代理模式进行 MI
| Host | CCR 网关监听的主机地址。常见值是 `127.0.0.1``0.0.0.0`。 |
| Port | CCR 网关监听端口。客户端需要把 API Base URL 指向这个端口。 |
Host 使用 `127.0.0.1` 时仅本机可访问;`0.0.0.0` 会监听所有 IPv4 网卡。只有在确实需要局域网或远程访问时才使用通配地址,并同时配置 CCR 客户端 API Key、防火墙 / 私网和 TLS 反向代理。
管理 Token、CCR 客户端 API Key 和上游供应商凭据彼此独立。客户端访问网关时使用 **API 密钥** 页面创建的 CCR Key,不要直接暴露上游凭据。
## 启动和验证
1. 至少添加一个供应商和模型。
2.**API 密钥** 页面创建客户端 Key。
3. 点击 **启动****重启**
4. 确认状态显示运行中,并请求网关的 `/health`
5. 发出最小模型请求,再到请求日志核对最终供应商 / 模型。
管理 UI 可访问不代表模型网关已运行。Docker 在网关未启动时会让 `/health` 返回 `502`;桌面版 / CLI 也可能在没有可用模型时只保留管理服务。
## 代理模式
代理模式是本地代理能力。开启后,客户端可以把 HTTP/HTTPS 流量交给 CCRCCR 会通过 MITM 劫持识别和解密 HTTPS 请求,并把可处理的模型请求代理到 CCR 网关链路。
@@ -26,3 +52,5 @@ lead: 配置 CCR 网关监听地址、端口,以及通过代理模式进行 MI
| 检查信任 | 重新检测代理 CA 是否已被系统信任。 |
| 代理状态 | 显示代理服务当前是否运行。 |
| 重启代理 | 代理模式开启时,重新启动代理服务。 |
代理模式需要操作本机网络和证书信任,主要面向桌面环境。容器部署通常应把客户端直接指向 CCR 的 Nginx 网关入口,不建议依赖容器修改宿主机系统代理或安装宿主机 CA。
+7 -9
View File
@@ -7,17 +7,15 @@ lead: 从安装开始,逐步接入供应商、让 Agent 通过 CCR 发请求
## 安装并启动 CCR
### 下载安装
CCR 提供三种发行方式:桌面应用、Node.js 22+ 的 npm CLI,以及 Docker 单入口部署。
1. 打开 [GitHub Releases](https://github.com/musistudio/claude-code-router/releases) 页面。
2. 按你的系统下载安装包:macOS 使用 `.dmg``.zip`Windows 使用 `.exe`Linux 使用 `.AppImage`
3. 像普通桌面软件一样安装并打开 **Claude Code Router**
| 方式 | 启动入口 | 默认管理地址 | 默认模型网关 |
| --- | --- | --- | --- |
| 桌面应用 | 应用界面 / `ccr-app` | 应用内窗口 | `http://127.0.0.1:3456` |
| npm CLI | `ccr ui` / `ccr serve` | `http://127.0.0.1:3458` | `http://127.0.0.1:3456` |
| Docker | `docker compose up -d --build` | 与网关共用 `http://127.0.0.1:3458` | 与管理界面共用 Nginx 入口 |
### 启动服务
进入 **服务** 页面,点击 **启动**。页面显示运行中后,CCR 会在本机监听默认地址 `http://localhost:8080`
如果希望打开 App 后自动启动服务,可以在服务页面开启自动启动。
先阅读[安装页](install/)选择发行方式;完整终端命令见 [CLI 参考](cli/),容器端口、鉴权、持久化和升级见 [Docker 部署](docker/)。
## 接入供应商
+220
View File
@@ -0,0 +1,220 @@
---
title: CLI 安装与命令参考
pageTitle: CLI 安装与命令参考
eyebrow: 快速开始
lead: 使用 npm 版 CCR 在开发机或无桌面服务器上运行管理界面、模型网关,并按 Agent 配置启动本机工具。
---
## CLI 与桌面版命令的区别
CCR 有两个相关命令:
| 命令 | 来源 | 主要用途 |
| --- | --- | --- |
| `ccr` | npm 包 `@musistudio/claude-code-router` | 不依赖 Electron,启动浏览器管理界面、模型网关和 Agent 配置。 |
| `ccr-app` | CCR 桌面应用 | 桌面版生成的配置启动器;Agent配置卡片复制的命令使用这个名称。 |
两个发行版会读取同一套本机配置目录,但不要把命令名混用。需要托盘、桌面通知、自动更新和桌面专属浏览器集成时,使用桌面版;需要无桌面部署或由进程管理器托管时,使用 npm CLI。
## 安装、升级与卸载
CLI 要求 Node.js 22 或更高版本:
```sh
node --version
npm install -g @musistudio/claude-code-router
ccr --help
```
升级和卸载:
```sh
npm install -g @musistudio/claude-code-router@latest
npm uninstall -g @musistudio/claude-code-router
```
卸载 npm 包不会删除 CCR 的本地配置和数据库。
如果安装成功但找不到命令,执行 `npm prefix -g`,确认 npm 全局可执行目录已经加入 `PATH`,然后打开一个新终端。
## 第一次启动
在后台启动 CCR 并打开管理界面:
```sh
ccr ui
```
SSH 或无桌面环境使用:
```sh
ccr ui --no-open
```
随后按这个顺序完成配置:
1. 添加供应商和至少一个模型。
2.**API 密钥** 页面创建用于访问网关的 CCR 客户端 Key。
3. 按需要设置默认模型、路由规则和 Fallback。
4.**服务** 页面确认网关已经运行。
5. 把客户端 Base URL 指向界面显示的网关地址。
管理界面默认使用 `http://127.0.0.1:3458`,模型网关默认使用 `http://127.0.0.1:3456`。管理 Token 与 CCR 客户端 Key 是两种独立凭据:前者保护 UI / RPC,后者验证模型请求。
## 服务命令总览
| 命令 | 运行方式 | 用途 |
| --- | --- | --- |
| `ccr start` | 后台 | 启动管理服务和模型网关,打印带认证信息的管理 URL。 |
| `ccr ui` | 后台 | 复用或启动后台服务,并打开浏览器。 |
| `ccr stop` | 一次性 | 停止由 `start``ui` 启动的后台服务。 |
| `ccr serve` | 前台 | 在当前终端运行,适合查看日志或交给进程管理器。 |
| `ccr web` | 前台 | `serve` 的别名。 |
| `ccr <配置名称或 ID>` | 前台 | 启动一个已启用的 Agent 配置。 |
## `ccr start`
```text
ccr start [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
| 选项 | 说明 |
| --- | --- |
| `--host <host>` | 管理服务监听地址,默认 `127.0.0.1`。也接受 `--host=value`。 |
| `--port <port>` | 管理服务首选端口,默认 `3458`。也接受 `--port=value`。 |
| `--open` | 启动后打开浏览器。 |
| `--no-open` | 不打开浏览器。 |
| `--gateway` | 明确要求启动模型网关;这是默认行为。 |
| `--no-gateway` | 只启动管理服务,不在启动阶段拉起模型网关。 |
如果首选端口被占用,CCR 会继续尝试后续端口并打印实际 URL。端口必须是 `1``65535` 的整数。
## `ccr ui`
```text
ccr ui [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
`ui``start` 使用同一个后台服务,但默认会打开浏览器。管理 URL 包含 `ccr_web_token` 查询参数;请把完整 URL 当作密码,不要粘贴到日志、工单或公开截图。
## `ccr serve`
```text
ccr serve [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
`serve` 留在前台,收到 `SIGINT``SIGTERM` 后关闭管理服务和已配置服务。排查启动错误时优先使用它,因为错误会直接输出到当前终端。
`ccr stop` 只管理后台服务。前台 `serve` 应通过当前终端或外部进程管理器停止。
## 后台服务的复用规则
`start``ui` 会把进程 ID、URL 和私有服务 Token 写入 `service.json`。再次执行时,CCR 会先验证对应进程和 RPC 身份:
- 服务有效时直接复用,不会再启动第二个后台进程。
- 新传入的 Host、Port 和 `--no-gateway` 不会重配已经运行的进程。
- 如果新命令要求网关运行,CCR 会尝试在现有管理进程中启动网关。
- 状态文件失效或进程已经退出时,CCR 会清理旧状态并启动新服务。
需要修改监听参数时先执行:
```sh
ccr stop
ccr start --host 127.0.0.1 --port 3458
```
## 按 Agent 配置启动
先在 **Agent配置** 中创建并启用配置,然后使用:
```text
ccr <配置名称或 ID> [cli|app] [-- <Agent 参数>]
```
示例:
```sh
ccr "Codex - Work"
ccr "Codex - Work" app
ccr "Claude - Review" cli -- --model sonnet
ccr profile-id -- --help
```
规则如下:
- `--cli``--app` 可以替代位置形式的 `cli` / `app`
- Agent 自己的参数放到 `--` 后,避免与 CCR 选项或入口名冲突。
- 省略入口时,Claude Code、Codex、Grok CLI 默认使用 CLIZCode 默认使用 App。
- Grok 只支持 CLIZCode 只支持 App。
- Claude App 和 ZCode App 不支持额外 Agent 参数。
- 启动 App 需要本机安装对应桌面应用,并且当前环境有图形会话。
- 只有已启用的配置可以启动。名称产生歧义时使用配置 ID。
大多数配置要求 CCR 网关已经运行。Grok CLI 是例外:如果服务不存在,它可以自动启动一个受管的临时共享服务,并在最后一个 Grok 会话退出后关闭。
## 配置和数据位置
| 平台 | 配置目录 |
| --- | --- |
| macOS / Linux | `~/.claude-code-router` |
| Windows | `%APPDATA%\claude-code-router` |
常见文件和目录:
| 路径 | 用途 |
| --- | --- |
| `config.sqlite` | 当前应用配置。 |
| `app-data/` | API Key、用量、请求日志、证书等运行数据。 |
| `service.json` | 后台 CLI 服务状态和私有 Token。 |
| `gateway.config.json` | 生成的网关运行配置。 |
| `profiles/` | 按 Agent 配置隔离的文件。 |
| `bin/` | CCR 生成的 Agent 启动包装器。 |
不要在 CCR 运行时直接编辑或复制活跃 SQLite 文件。优先使用 **Settings → Export data**;文件级备份前先停止 CLI 和桌面应用。
## 环境变量与远程访问
公开的管理认证变量是:
| 变量 | 说明 |
| --- | --- |
| `CCR_WEB_HOST` | 省略 `--host` 时使用的管理服务监听地址。 |
| `CCR_WEB_PORT` | 省略 `--port` 时使用的管理服务端口。 |
| `CCR_WEB_AUTH_TOKEN` | 固定管理 UI / RPC Token;不设置时进程会生成随机 Token。 |
监听到 `0.0.0.0` 会让管理界面进入局域网或外部网络。只有在确实需要时才这样配置,并同时使用固定强 Token、主机防火墙或私网,以及可信反向代理提供的 TLS。
模型网关还需要单独创建 CCR 客户端 Key。上游供应商凭据保存在本地数据目录,因此目录和备份都应按敏感数据保护。
## 进程管理器示例
生产环境应使用 `ccr serve --no-open`,让外部管理器负责重启和日志。启动命令至少应固定工作用户、`HOME`、监听地址和 `CCR_WEB_AUTH_TOKEN`。不要同时运行由 `ccr start` 创建的后台服务,否则可能得到两个管理端口或竞争同一套配置。
## 常见问题
### UI 能打开,但 `/health` 或模型请求失败
管理服务可以在没有可用模型网关时运行。添加供应商和模型、创建 CCR 客户端 Key,然后从 **服务** 页面启动或重启网关。使用 `ccr serve` 查看启动错误。
### 实际管理端口不是 3458
3458 已被占用,CCR 使用了后续可用端口。以命令打印的 URL 为准;需要固定端口时,先停止冲突进程。
### 找不到 Agent 配置
确认配置已启用,并检查名称是否重复。CCR 会按 ID、名称、忽略大小写的名称和清理后的名称匹配;多个结果时必须使用 ID。
### 提示启动器不存在
先打开一次 CCR 或重新保存该 Agent 配置,让 CCR 重新生成 `bin/` 下的启动包装器。
### 后台服务无法停止
先运行 `ccr stop`。如果状态文件已经失效,命令会清理它并报告服务未运行。前台 `ccr serve` 不受 `ccr stop` 管理,应回到对应终端或进程管理器停止。
## 相关页面
- [安装并启动 CCR](../install/)
- [Agent配置](../../configuration/profile/)
- [服务配置](../../configuration/server/)
- [Docker 部署](../docker/)
+297
View File
@@ -0,0 +1,297 @@
---
title: Docker 部署
pageTitle: Docker 部署
eyebrow: 快速开始
lead: 使用 Nginx 单入口运行 CCR Core 和浏览器管理界面,并正确处理端口、鉴权、持久化、远程访问、备份和升级。
---
## 适用范围与限制
Docker 镜像适合常驻模型网关和浏览器管理。它包含 CCR Core、构建后的管理 UI、PM2 和 Nginx,但不包含:
- Electron 桌面应用、系统托盘和桌面通知;
- npm 发行版的 `ccr` 命令;
- 从容器中启动宿主机 Claude App、ChatGPT、ZCode 等桌面 App
- 桌面自动更新和桌面专属的内置浏览器集成。
如果主要需求是本机 Agent 多开、托盘或桌面 App 启动,请使用桌面版;如果需要终端命令但不需要容器,请使用 [CLI](../cli/)。
## 进程和端口拓扑
```text
宿主机 3458 -> 容器 Nginx 8080
|-> 静态管理 UI
|-> 管理 RPC127.0.0.1:3459
|-> 模型网关:127.0.0.1:3456
`-> Core Runtime127.0.0.1:3457
```
只应发布 Nginx 的容器端口 `8080``3459``3456``3457` 都是容器内部实现端口,不要分别映射到宿主机。
Nginx 对外提供:
| 路径 | 用途 |
| --- | --- |
| `/``/pages/home/index.html` | 管理 UI。根路径会跳转到带管理 Token 的页面。 |
| `/api/ccr/rpc` | 需要管理 Token 的管理 RPC。 |
| `/health` | 模型网关健康状态,不是容器或 UI 健康状态。 |
| `/v1/*``/v1beta/*``/messages``/chat/completions``/responses``/interactions``/mcp/*` | 模型和 MCP 网关接口。 |
## 使用 Compose 快速启动
在仓库根目录执行:
```sh
docker compose up -d --build
docker compose logs -f ccr
```
打开 <http://127.0.0.1:3458>。新数据卷上管理 UI 会立即可用;模型网关要在添加供应商和模型后才能正常启动。
首次配置顺序:
1. 添加供应商和至少一个模型。
2.**API 密钥** 页面创建 CCR 客户端 Key。
3.**服务** 页面启动网关。
4. 请求 `/health`,确认返回 `200` 和运行状态。
5. 把客户端 Base URL 指向 `http://127.0.0.1:3458`,并使用刚创建的 CCR 客户端 Key。
停止或移除容器不会自动删除命名卷:
```sh
docker compose stop
docker compose down
```
不要给 `docker compose down` 添加 `--volumes`,除非你明确要删除全部 CCR 数据。
## 只允许本机访问
仓库默认映射 `3458:8080` 会监听宿主机所有网卡。如果只从当前机器访问,修改为:
```yaml
services:
ccr:
ports:
- "127.0.0.1:3458:8080"
```
端口映射左侧是宿主机地址和端口,右侧是 Nginx 容器端口。不要把右侧改为内部网关的 `3456`
## 使用 `docker run`
不使用 Compose 时:
```sh
docker build -t claude-code-router:local .
docker run -d \
--name claude-code-router \
--restart unless-stopped \
-p 127.0.0.1:3458:8080 \
-e CCR_PUBLIC_BASE_URL=http://127.0.0.1:3458 \
-v ccr-data:/data \
claude-code-router:local
```
仓库也提供 `npm run docker:build``npm run docker:run`。后者使用 `3458``ccr-data`,但容器带 `--rm`,没有固定名称和自动重启策略,更适合临时验证。
## 三类凭据不要混用
| 凭据 | 用途 | 配置位置 |
| --- | --- | --- |
| `CCR_WEB_AUTH_TOKEN` | 管理 UI / RPC 鉴权 | 容器环境变量 |
| CCR 客户端 API Key | 模型网关请求鉴权 | UI 的 **API 密钥** 页面 |
| 上游供应商凭据 | CCR 调用模型供应商 | UI 的 **供应商** 页面 |
不设置 `CCR_WEB_AUTH_TOKEN` 时,EntryPoint 每次启动容器都会生成新的随机 Token。打开根地址仍可工作,因为 Nginx 会跳转到包含当前 Token 的 URL;但持久部署和远程部署应固定一个足够长的强 Token。
不要把 Token 直接写进 Shell 历史。可以创建不进入版本控制的环境文件:
```dotenv
CCR_WEB_AUTH_TOKEN=replace-with-a-long-random-value
CCR_PUBLIC_BASE_URL=http://127.0.0.1:3458
```
通过 `docker run --env-file` 使用,或把同名变量映射到 Compose 服务的 `environment`。包含 `ccr_web_token` 的完整管理 URL 也应按密码保护,因为它可能出现在浏览器历史、反向代理日志、截图和工单中。
## 修改外部端口或地址
宿主机对外地址与容器内部端口是两层配置。修改宿主机端口时,还要把 `CCR_PUBLIC_BASE_URL` 设置为客户端真实使用的完整地址:
```yaml
services:
ccr:
ports:
- "127.0.0.1:8088:8080"
environment:
CCR_PUBLIC_BASE_URL: http://127.0.0.1:8088
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
`CCR_PUBLIC_BASE_URL` 会同步到 CCR 的公开 Router Endpoint。它本身不会发布 Docker 端口,也不会改变 Nginx 监听地址。
## 域名、HTTPS 与反向代理
由反向代理或 Ingress 终止 TLS 时:
```yaml
services:
ccr:
ports:
- "127.0.0.1:3458:8080"
environment:
CCR_PUBLIC_BASE_URL: https://ccr.example.com
CCR_WEB_AUTH_TOKEN: ${CCR_WEB_AUTH_TOKEN:?set CCR_WEB_AUTH_TOKEN}
```
反向代理应把全部路径交给 CCR Nginx,并满足:
- 支持长时间模型请求;
- 不缓冲 SSE 和流式模型响应;
- 允许足够的请求体大小;
- 只有反向代理入口对外公开,宿主机 `3458` 保持仅本机监听;
- 配合防火墙、VPN / 私网或额外访问控制,避免管理界面直接暴露到不可信网络。
## 持久化目录
EntryPoint 会设置 `HOME=/data`,实际数据位于:
```text
/data/.claude-code-router/
├── config.sqlite
├── gateway.config.json
├── app-data/
│ ├── api-keys.sqlite
│ ├── request-logs.sqlite
│ ├── usage.sqlite
│ └── certs/
├── profiles/
└── bin/
```
优先使用命名卷。Bind Mount 目录必须允许容器写入,而且不能让两个运行中的 CCR 容器共享同一份数据。
全新数据目录中既没有 `config.json` 也没有 `config.sqlite` 时,EntryPoint 默认写入最小的旧格式 `config.json` 作为首次引导。UI 保存后 SQLite 成为权威配置。每次启动默认还会把 JSON / SQLite 中的网关监听字段和 `routerEndpoint` 同步到当前 Docker 公开地址。
## 备份与恢复
应用级备份优先使用 **Settings → Export data**。做完整文件备份时,先停止写入:
```sh
docker compose stop ccr
docker compose cp ccr:/data/. ./ccr-data-backup/
docker compose start ccr
```
备份包含供应商凭据、CCR 客户端 Key,并可能包含请求 / 响应数据,必须按敏感数据保存。
完整恢复时,应把备份复制到新的空卷或空 `/data` 目录,并确保容器已停止。不要把旧备份直接覆盖到仍有新数据的活动目录,否则旧 SQLite WAL / SHM 和新运行文件可能混合。替换现有数据前再做一份备份。
## 升级与回滚
先备份 `/data`,再更新源码、刷新基础镜像并重建:
```sh
git pull
docker compose build --pull
docker compose up -d
docker compose ps
docker compose logs --tail=200 ccr
```
升级会对持久化数据执行当前版本需要的迁移。回滚时应同时使用旧镜像 / 旧源码和升级前备份,不要假设旧版本一定能读取新版本数据库。
## 环境变量完整参考
一般部署只需要设置 `CCR_WEB_AUTH_TOKEN``CCR_PUBLIC_BASE_URL` 和 Docker Port Mapping。内部监听变量通常不需要修改。
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `CCR_WEB_AUTH_TOKEN` | 每次启动随机生成 | 管理 UI / RPC Token。持久或远程部署应设置固定强值。 |
| `CCR_PUBLIC_BASE_URL` | `http://127.0.0.1:3458` | 写入 CCR 配置的完整公开地址;设置后优先于 Public Host / Port。 |
| `CCR_PUBLIC_HOST` | `127.0.0.1` | 仅在没有完整公开 URL 时用于拼接公开地址,不会改变 Docker 端口绑定。 |
| `CCR_PUBLIC_PORT` | `3458` | 仅在没有完整公开 URL 时用于拼接公开地址。 |
| `CCR_DATA_DIR` | `/data` | 数据根目录,同时作为进程 `HOME`。 |
| `CCR_NGINX_PORT` | `8080` | Nginx 容器内监听端口,应与 Port Mapping 右侧一致。 |
| `CCR_WEB_HOST` | `127.0.0.1` | 管理服务容器内监听地址。 |
| `CCR_WEB_PORT` | `3459` | 管理服务容器内端口。 |
| `CCR_GATEWAY_HOST` | `127.0.0.1` | 模型网关容器内监听地址。 |
| `CCR_GATEWAY_PORT` | `3456` | Nginx 转发到的模型网关容器内端口。 |
| `CCR_GATEWAY_CORE_PORT` | `3457` | Core Gateway Runtime 容器内端口。 |
| `CCR_NO_GATEWAY` | `0` | 设为 `1``true``yes` 时,启动阶段只运行管理 UI。 |
| `CCR_DOCKER_INIT_CONFIG` | `1` | 设为 `0` 时禁用首次最小 `config.json` 引导。 |
| `CCR_DOCKER_SYNC_PUBLIC_ENDPOINT` | `1` | 设为 `0` 时不再在启动时同步已有 JSON / SQLite 的监听和公开地址字段。 |
修改内部端口需要同时保证 PM2 和 Nginx 变量一致,正常部署没有收益。对外仍然只发布 `CCR_NGINX_PORT`
## 构建和烟雾测试
默认使用 `node:22-bookworm` 构建原生依赖,再把生产依赖和构建产物复制到 `node:22-bookworm-slim`。需要替换基础镜像时:
```sh
docker build \
--build-arg NODE_IMAGE=node:22-bookworm \
--build-arg RUNTIME_NODE_IMAGE=node:22-bookworm-slim \
-t claude-code-router:local .
```
运行 Docker 烟雾测试:
```sh
npm run test:docker
```
测试会创建临时容器和数据卷,检查单一 Nginx 端口、UI / RPC 鉴权、公开地址迁移、网关启动和 `/health`,最后自动清理。使用 `CCR_DOCKER_TEST_SKIP_BUILD=1` 复用已有镜像,或通过 `CCR_DOCKER_TEST_IMAGE` 指定本地 Tag。
## 日常运维命令
```sh
docker compose ps
docker compose logs -f ccr
docker compose restart ccr
docker compose config
```
`docker compose ps` 显示的是容器健康;`/health` 显示的是模型网关健康。两者不能互相替代。
## 常见问题
### 根地址返回 `302`
这是正常行为。Nginx 正在把根地址跳转到带 URL 编码管理 Token 的页面。
### `/health` 返回 `502`
它检查模型网关,不检查 Nginx 或 UI。新数据卷尚未配置供应商 / 模型时会返回 `502`。先打开 UI 完成配置并启动网关。
### 修改 Token 后 UI 返回 `401`
重新打开不带参数的根地址,让 Nginx 生成包含新 Token 的 URL;关闭仍使用旧 `ccr_web_token` 的标签页和书签。
### 客户端仍使用旧端口或域名
更新 `CCR_PUBLIC_BASE_URL` 并重新创建容器。保持 `CCR_DOCKER_SYNC_PUBLIC_ENDPOINT=1`,让已有 SQLite 配置在启动时同步。
### 重建后配置消失
确认 `/data` 仍挂载同一个命名卷或 Bind Mount。`docker compose down` 保留卷,`docker compose down --volumes` 删除卷。
### Bind Mount 权限错误
确认宿主机目录存在、容器可写且没有只读挂载。命名卷通常可以避免宿主机 UID、所有权和安全标签问题。
### 容器健康,但模型请求失败
容器健康只代表 Nginx / UI 可访问。继续检查 **服务** 状态、供应商连通性、CCR 客户端 Key、路由和请求日志,并查看:
```sh
docker compose logs --tail=200 ccr
```
## 相关页面
- [安装并启动 CCR](../install/)
- [CLI 安装与命令参考](../cli/)
- [服务配置](../../configuration/server/)
- [API 密钥](../../configuration/api-keys/)
+56 -7
View File
@@ -2,17 +2,66 @@
title: 安装并启动 CCR
pageTitle: 安装并启动 CCR
eyebrow: 快速开始
lead: 下载桌面应用,安装后启动本地 CCR 服务
lead: 根据桌面版、npm CLI 或 Docker 的运行场景选择安装方式,并确认管理界面与模型网关的不同地址
---
## 下载安装
## 选择发行方式
| 方式 | 适合场景 | 入口 | 默认管理地址 | 默认网关地址 |
| --- | --- | --- | --- | --- |
| 桌面应用 | 日常本机使用、托盘、多开 Agent App、桌面集成 | 应用界面、`ccr-app` | 应用内窗口 | `http://127.0.0.1:3456` |
| npm CLI | 终端、SSH、无 Electron 环境、进程管理器 | `ccr` | `http://127.0.0.1:3458` | `http://127.0.0.1:3456` |
| Docker | 常驻服务器、容器运维、统一浏览器入口 | Nginx | 与网关共用公开地址 | `http://127.0.0.1:3458`(默认端口映射) |
管理 UI 地址和模型网关地址在桌面版 / CLI 中不是同一个端口。不要把 CLI 的管理端口 `3458` 当成默认模型网关端口;Docker 才通过 Nginx 把两者合并到同一公开入口。
## 安装桌面应用
1. 打开 [GitHub Releases](https://github.com/musistudio/claude-code-router/releases) 页面。
2.你的系统下载安装包macOS 使用 `.dmg``.zip`Windows 使用 `.exe`Linux 使用 `.AppImage`
3. 像普通桌面软件一样安装并打开 **Claude Code Router**
2. 按系统下载:macOS 使用 `.dmg``.zip`Windows 使用 `.exe`Linux 使用 `.AppImage`
3. 安装并打开 **Claude Code Router**
4. 添加供应商和模型,在 **API 密钥** 中创建客户端 Key,然后从 **服务** 页面点击 **启动**
## 启动服务
页面显示运行中后,模型网关默认监听 `http://127.0.0.1:3456`。需要打开应用时自动启动网关,可在 **服务** 页面开启自动启动。
进入 **Server** 页面,点击 **Start**。页面显示 Running 后,CCR 会在本机监听默认地址 `http://localhost:8080`
## 安装 npm CLI
如果希望打开 App 后自动启动服务,可以在 Server 页面开启 **Auto start**
要求 Node.js 22 或更高版本:
```sh
npm install -g @musistudio/claude-code-router
ccr ui
```
`ccr ui` 会启动后台服务并打开浏览器。无桌面环境使用 `ccr ui --no-open`,生产前台托管使用 `ccr serve --no-open`。完整命令和 Profile 启动说明见 [CLI 安装与命令参考](../cli/)。
## 使用 Docker
在源码仓库根目录执行:
```sh
docker compose up -d --build
```
打开 <http://127.0.0.1:3458>。Docker 只发布 Nginx 单入口,管理 UI 和模型网关共用该地址。首次启动后仍需添加供应商 / 模型、创建 CCR 客户端 Key,并从 **服务** 页面启动网关。端口、鉴权、持久化、备份和远程部署见 [Docker 部署](../docker/)。
## 验证安装
完成供应商、模型和 CCR 客户端 Key 配置后:
1.**服务** 页面确认状态为运行中。
2. 请求当前部署的 `/health`;成功时应返回 `200` 和运行状态。
3. 用 CCR 客户端 Key 向兼容路径发送一个最小模型请求。
4.**日志** 页面确认请求模型、最终供应商 / 模型、状态码和耗时。
管理界面能打开并不代表模型网关已经可用。没有供应商 / 模型时,Docker 的 `/health` 返回 `502` 属于预期行为。
## 数据位置
| 方式 | 配置位置 |
| --- | --- |
| 桌面 / CLImacOS、Linux | `~/.claude-code-router` |
| 桌面 / CLIWindows | `%APPDATA%\claude-code-router` |
| Docker | `/data/.claude-code-router`,应持久化挂载 `/data` |
CCR 当前配置存储在 `config.sqlite` 中;`config.json` 只在没有 SQLite 配置时作为旧版迁移或 Docker 首次引导来源。不要在 CCR 运行时直接编辑 SQLite。
+6 -5
View File
@@ -12,7 +12,7 @@ lead: 了解 CCR 的定位、能力边界和文档结构。需要动手配置时
| 分类 | 内容 |
| --- | --- |
| [文档](./) | 产品定位、架构概览、阅读路径 |
| [快速开始](guides/) | 从安装、接供应商,到接入 Agent 的上手流程 |
| [快速开始](guides/) | 桌面版、CLI、Docker 安装部署,以及供应商和 Agent 接入流程 |
| [详细配置](configuration/overview/) | 概览仪表盘、API 密钥、服务、供应商、路由、Agent配置、Fusion、Bot、托盘和配置数据库位置 |
| [Q&A](troubleshooting/) | 请求日志、观测面板和常见问题 |
@@ -22,9 +22,10 @@ Bot 平台教程是「详细配置」分类下的子页面,每个平台有独
第一次使用时可以从这些页面了解 CCR 的主要流程:
1. [快速开始](guides/) 覆盖供应商接入和 Agent配置
2. App 的请求日志页面展示请求是否经过 CCR
3. [详细配置](configuration/overview/) 覆盖概览仪表盘、API 密钥、服务、供应商、图像、联网搜索、MCP 工具、托盘和 IM 接力
4. [Q&A](troubleshooting/) 覆盖 401、404、超时、路由不对或 Bot 收不到消息等常见问题
1. [安装页](guides/install/)选择桌面版、npm CLI 或 Docker;对应细节见 [CLI](guides/cli/) 和 [Docker](guides/docker/) 页面
2. [快速开始](guides/) 继续覆盖供应商接入和 Agent配置
3. App 的请求日志页面展示请求是否经过 CCR
4. [详细配置](configuration/overview/) 覆盖概览仪表盘、API 密钥、服务、供应商、图像、联网搜索、MCP 工具、托盘和 IM 接力
5. [Q&A](troubleshooting/) 覆盖 401、404、超时、路由不对或 Bot 收不到消息等常见问题。
这样文档不会挤在一个长页面里,后续也能按顶部分类逐步扩展。
+8
View File
@@ -40,6 +40,8 @@ export const docsContent = {
icon: "book",
items: [
"安装并启动 CCR",
"CLI 安装与命令参考",
"Docker 部署",
"接入供应商",
"接入 Agent配置",
"日志&观测",
@@ -51,6 +53,8 @@ export const docsContent = {
sidebarChildren: {},
sidebarLinks: {
"安装并启动 CCR": "/guides/install/",
"CLI 安装与命令参考": "/guides/cli/",
"Docker 部署": "/guides/docker/",
: "/guides/provider/",
"接入 Agent配置": "/guides/agent-profile/",
"日志&观测": "/guides/observability/",
@@ -197,6 +201,8 @@ export const docsContent = {
icon: "book",
items: [
"Install And Start CCR",
"CLI Installation And Reference",
"Docker Deployment",
"Add A Provider",
"Connect Agent Config",
"Logs & Observability",
@@ -208,6 +214,8 @@ export const docsContent = {
sidebarChildren: {},
sidebarLinks: {
"Install And Start CCR": "/en/guides/install/",
"CLI Installation And Reference": "/en/guides/cli/",
"Docker Deployment": "/en/guides/docker/",
"Add A Provider": "/en/guides/provider/",
"Connect Agent Config": "/en/guides/agent-profile/",
"Logs & Observability": "/en/guides/observability/",
+2
View File
@@ -5,6 +5,8 @@ import { enGuideDocs, sectionSlugFromPath } from "../../../section-docs";
export function getStaticPaths() {
const activeLabels: Record<string, string> = {
install: "Install And Start CCR",
cli: "CLI Installation And Reference",
docker: "Docker Deployment",
provider: "Add A Provider",
"agent-profile": "Connect Agent Config",
observability: "Logs & Observability",
+2
View File
@@ -5,6 +5,8 @@ import { sectionSlugFromPath, zhGuideDocs } from "../../section-docs";
export function getStaticPaths() {
const activeLabels: Record<string, string> = {
install: "安装并启动 CCR",
cli: "CLI 安装与命令参考",
docker: "Docker 部署",
provider: "接入供应商",
"agent-profile": "接入 Agent配置",
observability: "日志&观测",
+141 -332
View File
@@ -1,375 +1,184 @@
<h1 align="center">Claude Code Router Desktop</h1>
# Claude Code Router CLI
<p align="center">
<a href="README_zh.md"><img alt="Chinese README" src="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" /></a>
<a href="https://discord.gg/rdftVMaUcS"><img alt="Discord" src="https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white" /></a>
<a href="https://x.com/musistudio2026"><img alt="X" src="https://img.shields.io/badge/X-@musistudio2026-000000?logo=x&logoColor=white" /></a>
<a href="https://github.com/musistudio/claude-code-router/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/musistudio/claude-code-router" /></a>
<a href="https://ccrdesk.top/"><img alt="Documentation" src="https://img.shields.io/badge/Docs-ccrdesk.top-0ea5e9?style=flat" /></a>
</p>
[中文](README_zh.md) · [Documentation](https://ccrdesk.top/en/) · [GitHub](https://github.com/musistudio/claude-code-router)
<div align="center">
`@musistudio/claude-code-router` is the Node.js distribution of Claude Code Router. It provides the `ccr` command, the browser-based management UI, the local model gateway, and profile launch commands without requiring Electron.
<table width="100%">
<tr>
<td align="center">
<a href="https://www.kimi.com/code?aff=ccr">
<img src="https://gcdn.moonshot.cn/growth-cdn/sponsor/kimi-en.png" width="960" alt="Kimi K2.7 Code sponsor banner" />
</a>
<br />
<sub>
<a href="https://www.kimi.com/code?aff=ccr"><strong>Kimi Code Subscription</strong></a>
&nbsp;·&nbsp;
<a href="https://platform.kimi.ai?aff=ccr"><strong>API Global</strong></a>
&nbsp;·&nbsp;
<a href="https://platform.kimi.com?aff=ccr">API China</a>
</sub>
</td>
</tr>
<tr>
<td align="left">
<p>
<strong>Thanks to Kimi for sponsoring this project!</strong> Kimi K2.7 Code is an open-source, coding-focused agentic model developed by Moonshot AI, with substantial gains on real-world long-horizon coding tasks and higher end-to-end success across complex software engineering workflows. It also cuts thinking-token usage by approximately 30% compared with K2.6. Inside CCR, Kimi ships as built-in provider presets: import the pay-as-you-go API or the Kimi Code subscription in one click and route your coding agent's requests to Kimi, the subscription endpoint passes straight through natively with no protocol conversion, API endpoints are adapted automatically, and your balance and subscription usage show up right in the CCR dashboard.
</p>
<p align="center">
CCR already supports Kimi. Visit the Kimi Open Platform (<a href="https://platform.kimi.com?aff=ccr">中文站</a> | <a href="https://platform.kimi.ai?aff=ccr">Global</a>) to try the API, or explore the <a href="https://www.kimi.com/code?aff=ccr">cost-effective Coding Plan</a>.
</p>
</td>
</tr>
</table>
Use the CLI on developer machines and headless hosts. If you want the tray, desktop notifications, automatic app updates, or desktop-only browser integrations, install the desktop application instead.
</div>
## Requirements And Installation
Claude Code Router Desktop is a local gateway and desktop control panel for routing agent requests from Claude Code, Codex, ZCode, and compatible clients to the model provider you actually want to use.
- Node.js 22 or newer
- A supported upstream model provider, or a locally logged-in agent account that CCR can import
- A locally installed agent executable when using profile launch commands
<p align="center">
<img src="blog/images/claude-code-router.png" width="720" alt="Claude Code Router Desktop screenshot" />
</p>
Install globally:
## Why Use CCR
```sh
npm install -g @musistudio/claude-code-router
ccr --help
```
- Use one local endpoint for multiple agent tools instead of configuring every client separately.
- Route requests with default routing, conditional rules, fallback targets, and request rewrites instead of editing client configuration by hand.
- Mix providers without changing your workflow. CCR supports OpenAI-compatible APIs, Anthropic Messages, Gemini Generate Content, OpenRouter, DeepSeek, SiliconFlow, Moonshot, Kimi Code, Mistral, Z.AI, Bailian, and custom providers.
- Control cost and reliability with fallback routing, API key rotation, usage statistics, and request logs.
Upgrade or remove it with npm:
## Features
```sh
npm install -g @musistudio/claude-code-router@latest
npm uninstall -g @musistudio/claude-code-router
```
- **Overview dashboard**: inspect system status, usage widgets, account balances, model distribution, and share cards.
- **Provider management**: add provider presets or custom endpoints, probe protocol support, test model connectivity, manage credentials, and monitor supported account balances where available.
- **Routing rules**: configure default routing, conditional and model-prefix rules, fallback handling, and request rewrites.
- **Agent Config**: configure Claude Code, Codex, and ZCode launch entries, models, scopes, and multi-instance app profiles.
- **Gateway compatibility**: translate supported client requests through the local CCR model gateway.
- **Proxy mode**: capture supported API traffic through a local proxy with optional system proxy integration and network capture.
- **Fusion models**: combine a base model with vision, web search, or MCP tools into a reusable selectable model.
## Documentation
Read the full documentation at [ccrdesk.top](https://ccrdesk.top/).
## Download And Install
1. Open the [GitHub Releases page](https://github.com/musistudio/claude-code-router/releases).
2. Download the package for your platform:
- macOS Apple Silicon: `Claude-Code-Router_<version>-mac-Apple-Silicon-arm64.dmg` or `.zip`
- macOS Intel: `Claude-Code-Router_<version>-mac-Intel-x64.dmg` or `.zip`
- Windows: `Claude Code Router_<version>.exe`
- Linux: `Claude Code Router_<version>.AppImage`
3. Install and launch **Claude Code Router**.
4. On first launch, CCR creates its local configuration database:
- macOS/Linux: `~/.claude-code-router/config.sqlite`
- Windows: `%APPDATA%\Claude Code Router\config.sqlite`
CCR stores runtime configuration in SQLite. A legacy `config.json` is read only once for migration when no SQLite config exists.
After the service is started from the **Server** page, CCR listens on `http://localhost:8080` by default. The **Server** page controls the gateway `Host`, `Port`, proxy mode, system proxy, network capture, and CA certificate status.
Removing the package does not delete CCR's local configuration or databases.
## Quick Start
CCR can be configured entirely from the desktop UI. Use this setup order for a clean first run.
Start the background service and open the management UI:
### 1. Add a provider
```sh
ccr ui
```
Open **Providers**, click **Add Provider**, then choose a built-in preset or **Other / custom API endpoint**. Fill in the provider name, base URL, protocol, API key, and model list. Run protocol probing and model connectivity checks when available, then save the provider.
Then:
### 2. Configure routing
1. Add an upstream provider and at least one model.
2. Create a CCR client key under **API Keys**.
3. Configure routing if the default provider/model is not sufficient.
4. Confirm that the gateway is running under **Server**.
5. Point your client at the gateway URL shown in the UI. The default gateway is `http://127.0.0.1:3456`; the management UI defaults to `http://127.0.0.1:3458`.
Open **Routing** to add conditional rules, configure request rewrites, and set fallback behavior.
The management token and CCR client API keys are different credentials. The management token protects the browser UI and RPC API. CCR client keys authenticate model requests sent to the gateway.
Use **Add Routing Rule** for request conditions, model-prefix routing, or rule-level fallback targets.
## Service Commands
### 3. Start the gateway
| Command | Behavior |
| --- | --- |
| `ccr start` | Starts a detached background management service and gateway, then prints its authenticated management URL. |
| `ccr ui` | Reuses or starts the background service and opens the management UI. |
| `ccr stop` | Stops the detached service started by `ccr start` or `ccr ui`. |
| `ccr serve` | Runs the management service and gateway in the foreground. `ccr web` is an alias. |
| `ccr <profile>` | Opens an enabled Agent Config profile by name or ID. |
Open **Server** and click **Start**. After the page shows Running, CCR listens on `http://localhost:8080`. Enable **Auto start** if you want CCR to start the local gateway whenever the desktop app opens.
### `ccr start`
### 4. Connect your agent tool
```text
ccr start [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
Open **Agent Config** and choose the client you want to use. Configure Claude Code, Codex, or ZCode, select the target model and effect scope, then apply the config. For app entries, use the **Open Agent** action to open the target app through CCR.
- `--host <host>`: management listener, default `127.0.0.1`.
- `--port <port>`: preferred management port, default `3458`.
- `--open` / `--no-open`: enable or disable opening a browser.
- `--gateway`: explicitly request gateway startup; this is the default.
- `--no-gateway`: start only the management service.
### 5. Monitor and adjust
### `ccr ui`
Use **Settings → Logs & Observability** to enable request logs and agent observability. Use **Logs** to confirm `request model`, `resolved provider`, `resolved model`, status, tokens, latency, and errors; use the tray window for quick token and account status.
```text
ccr ui [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
## Acknowledgements
`ui` opens the browser by default. Use `--no-open` on SSH or other headless sessions.
Codex support is powered by [musistudio/codexl](https://github.com/musistudio/codexl).
### `ccr serve`
## Support & Sponsoring
```text
ccr serve [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
<div align="center">
`serve` stays attached to the current terminal and handles `SIGINT`/`SIGTERM`. It is the appropriate mode for a process supervisor. `ccr stop` only manages the detached service; stop a foreground server through its terminal or supervisor.
<p>If you find this project helpful, please consider sponsoring its development. Your support is greatly appreciated.</p>
If the preferred management port is occupied, CCR tries the next available ports and prints the actual URL. When `start` or `ui` reuses an existing service, new host, port, and `--no-gateway` choices do not reconfigure that process. Run `ccr stop` first when those settings must change.
<table>
<tr>
<td align="center" width="220">
<a href="https://ko-fi.com/F1F31GN2GM">
<img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
</a>
<br />
<sub>One-time support via Ko-fi</sub>
</td>
<td align="center" width="220">
<a href="https://paypal.me/musistudio1999">
<img src="https://img.shields.io/badge/PayPal-Sponsor-003087?logo=paypal&logoColor=white" alt="Sponsor with PayPal" />
</a>
<br />
<sub>International sponsorship</sub>
</td>
</tr>
</table>
## Agent Config Profiles
<table>
<tr>
<td align="center" width="220">
<strong>Alipay</strong>
<br />
<img src="/blog/images/alipay.jpg" width="160" alt="Alipay QR code" />
</td>
<td align="center" width="220">
<strong>WeChat Pay</strong>
<br />
<img src="/blog/images/wechat.jpg" width="160" alt="WeChat Pay QR code" />
</td>
</tr>
</table>
Create and enable profiles in **Agent Config**, then launch one by name or ID:
</div>
```sh
ccr "Codex - Work"
ccr "Codex - Work" app
ccr "Claude - Review" cli -- --model sonnet
ccr profile-id -- --help
```
### Our Sponsors
The syntax is:
<div align="center">
```text
ccr <profile-name-or-id> [cli|app] [-- <agent arguments>]
```
<p>A huge thank you to all our sponsors for their generous support.</p>
- `--cli` and `--app` are accepted alternatives to the positional surface.
- Put agent-specific arguments after `--` so they cannot be confused with CCR options.
- If the surface is omitted, CCR uses the first surface allowed by the profile: CLI for Claude Code, Codex, and Grok CLI; App for ZCode.
- Grok supports CLI only. ZCode supports App only. Claude App and ZCode App do not accept trailing agent arguments.
- Desktop App launches require that app to be installed and a graphical session to be available.
- Start the CCR service before opening most profiles. A Grok CLI profile can start a temporary shared service automatically and stops it after the last managed session exits.
<table width="100%">
<tr>
<td align="center" width="330">
<a href="https://www.bigmodel.cn/claude-code?ic=FPF9IVAGFJ">
<img src="/docs/public/provider-icons/zhipu-cn-general.png" width="42" height="42" alt="Zhipu icon" />
<br />
<strong>Z智谱</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://aihubmix.com/">
<img src="https://www.google.com/s2/favicons?domain=aihubmix.com&amp;sz=128" width="42" height="42" alt="AIHubmix icon" />
<br />
<strong>AIHubmix</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://ai.burncloud.com">
<img src="https://www.burncloud.com/favicon.png" width="42" height="42" alt="BurnCloud icon" />
<br />
<strong>BurnCloud</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://share.302.ai/ZGVF9w">
<img src="https://www.google.com/s2/favicons?domain=302.ai&amp;sz=128" width="42" height="42" alt="302.AI icon" />
<br />
<strong>302.AI</strong>
</a>
</td>
</tr>
<tr>
<td align="center" width="330">
<a href="https://runapi.co/register?aff=IX1t">
<img src="/docs/public/provider-icons/runapi.jpg" width="42" height="42" alt="RunAPI icon" />
<br />
<strong>RunAPI</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://teamorouter.com/">
<img src="/docs/public/provider-icons/teamorouter.png" width="42" height="42" alt="TeamoRouter icon" />
<br />
<strong>TeamoRouter</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://s.qiniu.com/AVjMVf">
<img src="/docs/public/provider-icons/qiniu-ai.png" width="42" height="42" alt="Qiniu Cloud AI icon" />
<br />
<strong>Qiniu Cloud AI</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://api.fenno.ai/register?redirect=/purchase?tab=subscription%26group=16&amp;aff=9HHHAB5QLAES">
<img src="/docs/public/provider-icons/fenno.jpg" width="42" height="42" alt="Fenno.ai icon" />
<br />
<strong>Fenno.ai</strong>
</a>
</td>
</tr>
</table>
The desktop application installs a related command named `ccr-app`. Commands copied from desktop Agent Config cards use `ccr-app`; the npm package documented here installs `ccr`.
<h4>Community Sponsors</h4>
## Configuration And Runtime Files
<table width="100%">
<tr>
<td align="center" width="220">@Simon Leischnig</td>
<td align="center" width="220"><a href="https://github.com/duanshuaimin">@duanshuaimin</a></td>
<td align="center" width="220"><a href="https://github.com/vrgitadmin">@vrgitadmin</a></td>
<td align="center" width="220">@*o</td>
<td align="center" width="220"><a href="https://github.com/ceilwoo">@ceilwoo</a></td>
<td align="center" width="220">@*说</td>
</tr>
<tr>
<td align="center" width="220">@*更</td>
<td align="center" width="220">@K*g</td>
<td align="center" width="220">@R*R</td>
<td align="center" width="220"><a href="https://github.com/bobleer">@bobleer</a></td>
<td align="center" width="220">@*苗</td>
<td align="center" width="220">@*划</td>
</tr>
<tr>
<td align="center" width="220"><a href="https://github.com/Clarence-pan">@Clarence-pan</a></td>
<td align="center" width="220"><a href="https://github.com/carter003">@carter003</a></td>
<td align="center" width="220">@S*r</td>
<td align="center" width="220">@*晖</td>
<td align="center" width="220">@*敏</td>
<td align="center" width="220">@Z*z</td>
</tr>
<tr>
<td align="center" width="220">@*然</td>
<td align="center" width="220"><a href="https://github.com/cluic">@cluic</a></td>
<td align="center" width="220">@*苗</td>
<td align="center" width="220"><a href="https://github.com/PromptExpert">@PromptExpert</a></td>
<td align="center" width="220">@*应</td>
<td align="center" width="220"><a href="https://github.com/yusnake">@yusnake</a></td>
</tr>
<tr>
<td align="center" width="220">@*飞</td>
<td align="center" width="220">@董*</td>
<td align="center" width="220">@*汀</td>
<td align="center" width="220">@*涯</td>
<td align="center" width="220">@*:-</td>
<td align="center" width="220">@**磊</td>
</tr>
<tr>
<td align="center" width="220">@*琢</td>
<td align="center" width="220">@*成</td>
<td align="center" width="220">@Z*o</td>
<td align="center" width="220">@*琨</td>
<td align="center" width="220"><a href="https://github.com/congzhangzh">@congzhangzh</a></td>
<td align="center" width="220">@*_</td>
</tr>
<tr>
<td align="center" width="220">@Z*m</td>
<td align="center" width="220">@*鑫</td>
<td align="center" width="220">@c*y</td>
<td align="center" width="220">@*昕</td>
<td align="center" width="220"><a href="https://github.com/witsice">@witsice</a></td>
<td align="center" width="220">@b*g</td>
</tr>
<tr>
<td align="center" width="220">@*亿</td>
<td align="center" width="220">@*辉</td>
<td align="center" width="220">@JACK</td>
<td align="center" width="220">@*光</td>
<td align="center" width="220">@W*l</td>
<td align="center" width="220"><a href="https://github.com/kesku">@kesku</a></td>
</tr>
<tr>
<td align="center" width="220"><a href="https://github.com/biguncle">@biguncle</a></td>
<td align="center" width="220">@二吉吉</td>
<td align="center" width="220">@a*g</td>
<td align="center" width="220">@*林</td>
<td align="center" width="220">@*咸</td>
<td align="center" width="220">@*明</td>
</tr>
<tr>
<td align="center" width="220">@S*y</td>
<td align="center" width="220">@f*o</td>
<td align="center" width="220">@*智</td>
<td align="center" width="220">@F*t</td>
<td align="center" width="220">@r*c</td>
<td align="center" width="220"><a href="https://github.com/qierkang">@qierkang</a></td>
</tr>
<tr>
<td align="center" width="220">@*军</td>
<td align="center" width="220"><a href="https://github.com/snrise-z">@snrise-z</a></td>
<td align="center" width="220">@*王</td>
<td align="center" width="220"><a href="https://github.com/greatheart1000">@greatheart1000</a></td>
<td align="center" width="220">@*王</td>
<td align="center" width="220">@zcutlip</td>
</tr>
<tr>
<td align="center" width="220"><a href="https://github.com/Peng-YM">@Peng-YM</a></td>
<td align="center" width="220">@*更</td>
<td align="center" width="220">@*.</td>
<td align="center" width="220">@F*t</td>
<td align="center" width="220">@*政</td>
<td align="center" width="220">@*铭</td>
</tr>
<tr>
<td align="center" width="220">@*叶</td>
<td align="center" width="220">@七*o</td>
<td align="center" width="220">@*青</td>
<td align="center" width="220">@**晨</td>
<td align="center" width="220">@*远</td>
<td align="center" width="220">@*霄</td>
</tr>
<tr>
<td align="center" width="220">@**吉</td>
<td align="center" width="220">@**飞</td>
<td align="center" width="220">@**驰</td>
<td align="center" width="220">@x*g</td>
<td align="center" width="220">@**东</td>
<td align="center" width="220">@*落</td>
</tr>
<tr>
<td align="center" width="220">@哆*k</td>
<td align="center" width="220">@*涛</td>
<td align="center" width="220"><a href="https://github.com/WitMiao">@苗大</a></td>
<td align="center" width="220">@*呢</td>
<td align="center" width="220">@d*u</td>
<td align="center" width="220">@crizcraig</td>
</tr>
<tr>
<td align="center" width="220">s*s</td>
<td align="center" width="220">*火</td>
<td align="center" width="220">*勤</td>
<td align="center" width="220">**锟</td>
<td align="center" width="220">*涛</td>
<td align="center" width="220">**明</td>
</tr>
<tr>
<td align="center" width="220">*知</td>
<td align="center" width="220">*语</td>
<td align="center" width="220">*瓜</td>
<td align="center" width="220"></td>
<td align="center" width="220"></td>
<td align="center" width="220"></td>
</tr>
</table>
| Platform | Config directory |
| --- | --- |
| macOS / Linux | `~/.claude-code-router` |
| Windows | `%APPDATA%\claude-code-router` |
<sub>If your name is masked, please contact me via my homepage email to update it with your GitHub username.</sub>
Important files include:
</div>
- `config.sqlite`: current application configuration.
- `app-data/`: API key, usage, request-log, certificate, and other runtime databases/files.
- `service.json`: state and private token for a detached CLI service.
- `gateway.config.json`: generated gateway runtime configuration.
- `profiles/` and `bin/`: isolated profile configuration and launch wrappers.
Do not edit or copy live SQLite files while CCR is writing to them. Use the UI export feature, or stop CCR before taking a filesystem backup.
## Environment And Security
| Variable | Description |
| --- | --- |
| `CCR_WEB_HOST` | Default management listener when `--host` is omitted. |
| `CCR_WEB_PORT` | Default management port when `--port` is omitted. |
| `CCR_WEB_AUTH_TOKEN` | Fixes the management UI/RPC token instead of generating a random token for the process. |
The authenticated management URL contains `ccr_web_token` in its query string. Treat that URL like a password and avoid copying it into logs, tickets, or shell history. Bind to `127.0.0.1` unless remote access is intentional. For remote access, use a firewall or private network plus TLS at a trusted reverse proxy.
Do not expose the gateway without creating CCR client API keys. Upstream provider credentials are stored in CCR's local data directory, so protect that directory and its backups.
## Troubleshooting
### `ccr` is not found
Confirm Node.js is version 22 or later and that npm's global binary directory is on `PATH`:
```sh
node --version
npm prefix -g
```
Open a new shell after installation if your shell caches command paths.
### The management URL changed ports
The requested port was already occupied. Use the URL printed by CCR, or stop the conflicting process and restart CCR.
### The UI opens but the gateway is unavailable
The management service can run without a usable gateway. Add a provider and model, create a client API key, then start or restart the gateway from **Server**. Check the foreground output from `ccr serve` when diagnosing startup errors.
### A profile cannot be found
Only enabled profiles are launchable. Names are matched without case and sanitized names are accepted, but ambiguous names require the profile ID. Re-save the profile if its generated launcher is missing.
### A background service uses old options
Stop and recreate it:
```sh
ccr stop
ccr start --host 127.0.0.1 --port 3458
```
## Docker
The repository also includes a Docker image for gateway and browser-UI deployments. It does not install the npm `ccr` command into the runtime image. See the [Docker deployment guide](https://github.com/musistudio/claude-code-router/blob/main/docker/README.md).
## License
This project is licensed under the [MIT License](LICENSE).
[MIT](LICENSE)
+141 -331
View File
@@ -1,374 +1,184 @@
<h1 align="center">Claude Code Router Desktop</h1>
# Claude Code Router CLI
<p align="center">
<a href="README.md"><img alt="English README" src="https://img.shields.io/badge/%F0%9F%87%AC%F0%9F%87%A7-English-000aff?style=flat" /></a>
<a href="https://discord.gg/rdftVMaUcS"><img alt="Discord" src="https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white" /></a>
<a href="https://x.com/musistudio2026"><img alt="X" src="https://img.shields.io/badge/X-@musistudio2026-000000?logo=x&logoColor=white" /></a>
<a href="https://github.com/musistudio/claude-code-router/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/musistudio/claude-code-router" /></a>
<a href="https://ccrdesk.top/"><img alt="文档" src="https://img.shields.io/badge/%E6%96%87%E6%A1%A3-ccrdesk.top-0ea5e9?style=flat" /></a>
</p>
[English](README.md) · [完整文档](https://ccrdesk.top/) · [GitHub](https://github.com/musistudio/claude-code-router)
<div align="center">
`@musistudio/claude-code-router` 是 Claude Code Router 的 Node.js 发行版。它通过 `ccr` 命令提供浏览器管理界面、本地模型网关和 Agent 配置启动能力,不需要安装 Electron。
<table width="100%">
<tr>
<td align="center">
<a href="https://www.kimi.com/code?aff=ccr">
<img src="https://gcdn.moonshot.cn/growth-cdn/sponsor/kimi-zh.png" width="960" alt="Kimi K2.7 Code 赞助横幅" />
</a>
<br />
<sub>
<a href="https://www.kimi.com/code?aff=ccr"><strong>Kimi Code 订阅</strong></a>
&nbsp;·&nbsp;
<a href="https://platform.kimi.com?aff=ccr"><strong>API 中文站</strong></a>
&nbsp;·&nbsp;
<a href="https://platform.kimi.ai?aff=ccr">API Global</a>
</sub>
</td>
</tr>
<tr>
<td align="left">
<p>
<strong>感谢 Kimi 赞助本项目!</strong>Kimi K2.7 Code 是 Moonshot AI 推出的编程专用开源智能体模型,在真实长程编程与复杂软件工程工作流中显著提升端到端任务成功率,同时优化推理效率,相比 K2.6 平均减少约 30% 的推理 token 消耗。在 CCR 中,Kimi 已作为内置供应商预设开箱即用:无论按量付费 API 还是 Kimi Code 订阅,一键导入即可把你的编程 Agent 请求路由到 Kimi,订阅端点原生直通、无需协议转换,API 端点自动适配,账户余额与订阅用量也能直接在 CCR 面板中查看。
</p>
<p align="center">
CCR 已内置 Kimi 供应商预设。前往 Kimi 开放平台(<a href="https://platform.kimi.com?aff=ccr">中文站</a><a href="https://platform.kimi.ai?aff=ccr">Global</a>)体验 API,或了解高性价比 <a href="https://www.kimi.com/code?aff=ccr">Coding Plan</a> 套餐。
</p>
</td>
</tr>
</table>
CLI 适合开发机和无桌面的服务器。如果你需要系统托盘、桌面通知、应用自动更新或桌面端专属的浏览器集成,请安装桌面应用。
</div>
## 环境要求与安装
Claude Code Router Desktop 是一个本地网关和桌面控制台,用来把 Claude Code、Codex、ZCode 以及兼容客户端的 Agent 请求路由到你真正想使用的模型服务。
- Node.js 22 或更高版本
- 一个可用的上游模型供应商,或 CCR 支持导入的本机 Agent 登录态
- 使用配置启动命令时,本机需要已经安装对应 Agent
<p align="center">
<img src="blog/images/claude-code-router.png" width="720" alt="Claude Code Router Desktop 项目截图" />
</p>
全局安装:
## 为什么使用 CCR
```sh
npm install -g @musistudio/claude-code-router
ccr --help
```
- 用一个本地入口连接多个 Agent 工具,不需要在每个客户端里重复配置 Provider。
- 在不改变工作流的情况下混用不同 Provider。CCR 支持 OpenAI 兼容 API、Anthropic Messages、Gemini Generate Content、OpenRouter、DeepSeek、SiliconFlow、Moonshot、Kimi Code、Mistral、Z.AI、百炼以及自定义 Provider。
- 通过 fallback 路由、API Key 轮换、用量统计和请求日志来控制成本和可靠性。
升级或卸载:
## 功能和特性
```sh
npm install -g @musistudio/claude-code-router@latest
npm uninstall -g @musistudio/claude-code-router
```
- **概览仪表盘**:查看系统状态、用量组件、账号余额、模型分布和分享卡片
- **Provider 管理**:添加预设或自定义端点,探测协议支持,检测模型连通性,管理凭据,并在可用时查看账号余额。
- **路由规则**:配置条件路由、模型前缀规则、失败降级和请求改写。
- **Agent配置**:为 Claude Code、Codex 和 ZCode 配置启动入口、模型、作用范围和多开 App 配置。
- **网关兼容层**:通过本地 CCR 模型网关转换支持的客户端请求。
- **代理模式**:通过本地代理捕获支持的 API 流量,可选系统代理和网络捕获。
- **Fusion 组合模型**:把基础模型与视觉、联网搜索或 MCP 工具组合成新的可选模型。
## 文档
完整文档见 [ccrdesk.top](https://ccrdesk.top/)。
## 下载和安装
1. 打开 [GitHub Releases 页面](https://github.com/musistudio/claude-code-router/releases)。
2. 按系统下载对应安装包:
- macOS Apple 芯片:`Claude-Code-Router_<version>-mac-Apple-Silicon-arm64.dmg``.zip`
- macOS Intel 芯片:`Claude-Code-Router_<version>-mac-Intel-x64.dmg``.zip`
- Windows`Claude Code Router_<version>.exe`
- Linux`Claude Code Router_<version>.AppImage`
3. 安装并启动 **Claude Code Router**
4. 首次启动后,CCR 会创建本地配置数据库:
- macOS/Linux`~/.claude-code-router/config.sqlite`
- Windows`%APPDATA%\Claude Code Router\config.sqlite`
CCR 的运行配置存储在 SQLite 中。旧版 `config.json` 只会在没有 SQLite 配置时作为迁移来源读取一次。
**服务** 页面启动后,CCR 默认监听 `http://localhost:8080`。**服务** 页面负责配置网关 `Host``Port`、代理模式、系统代理、网络捕获和 CA 证书状态。
卸载 npm 包不会删除 CCR 的本地配置和数据库
## 快速开始
CCR 可以完全通过桌面 UI 完成配置。首次使用建议按下面顺序操作。
启动后台服务并打开管理界面:
### 1. 添加 Provider
```sh
ccr ui
```
打开 **供应商**,点击 **添加供应商**,选择内置预设或 **其他 / 自定义 API 端点**。按表单填写 Provider 名称、基础 URL、协议、API Key 和模型列表。可用时先运行协议探测和模型连通性检查,然后保存 Provider。
然后按以下顺序配置:
### 2. 设置路由
1. 添加上游供应商和至少一个模型。
2.**API 密钥** 页面创建 CCR 客户端密钥。
3. 如果默认供应商 / 模型不够用,再配置路由规则。
4.**服务** 页面确认网关已经运行。
5. 把客户端指向界面显示的网关地址。网关默认是 `http://127.0.0.1:3456`,管理界面默认是 `http://127.0.0.1:3458`
打开 **路由**,添加条件规则,配置请求改写和失败降级
管理 Token 和 CCR 客户端 API Key 是两种不同凭据。管理 Token 保护浏览器 UI 和 RPC 接口,CCR 客户端 Key 用于验证发送到模型网关的请求
如果需要更细粒度控制,使用 **添加路由规则** 添加模型前缀、请求条件或规则级失败降级目标。
## 服务命令
### 3. 启动网关
| 命令 | 行为 |
| --- | --- |
| `ccr start` | 在后台启动管理服务和网关,并打印带认证信息的管理 URL。 |
| `ccr ui` | 复用或启动后台服务,然后打开管理界面。 |
| `ccr stop` | 停止由 `ccr start``ccr ui` 启动的后台服务。 |
| `ccr serve` | 在前台运行管理服务和网关;`ccr web` 是别名。 |
| `ccr <配置>` | 按名称或 ID 打开一个已启用的 Agent 配置。 |
打开 **服务**,点击 **启动**。页面显示运行中后,CCR 会在本机监听 `http://localhost:8080`。如果希望每次打开桌面应用时自动启动网关,可以启用自动启动。
### `ccr start`
### 4. 连接 Agent 工具
```text
ccr start [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
打开 **Agent配置**,选择要使用的客户端。配置 Claude Code、Codex 或 ZCode,选择目标模型和作用范围,然后应用配置。对于 App 入口,可以使用 **打开 Agent** 操作通过 CCR 打开目标应用
- `--host <host>`:管理服务监听地址,默认 `127.0.0.1`
- `--port <port>`:管理服务首选端口,默认 `3458`
- `--open` / `--no-open`:是否打开浏览器。
- `--gateway`:明确要求启动模型网关;这是默认行为。
- `--no-gateway`:只启动管理服务,不启动模型网关。
### 5. 日常查看和调整
### `ccr ui`
**设置 → 日志与观测** 打开请求日志和 Agent 观测。使用 **日志** 确认 `request model``resolved provider``resolved model`、状态码、tokens、耗时和错误;使用托盘窗口快速查看 Token 和账号状态。
```text
ccr ui [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
## 致谢
`ui` 默认会打开浏览器。在 SSH 或其他无桌面环境中使用 `--no-open`
对 Codex 的支持来自于 [musistudio/codexl](https://github.com/musistudio/codexl) 这个项目。
### `ccr serve`
## 支持与赞助
```text
ccr serve [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]
```
<div align="center">
`serve` 会留在当前终端并处理 `SIGINT` / `SIGTERM`,适合交给进程管理器托管。`ccr stop` 只管理后台服务;前台服务需要在终端或进程管理器中停止。
<p>如果你觉得这个项目有帮助,欢迎赞助项目开发。非常感谢你的支持。</p>
如果首选管理端口已被占用,CCR 会继续尝试后续端口并打印实际 URL。`start``ui` 复用已运行服务时,新传入的 Host、Port 和 `--no-gateway` 不会重配该进程;要修改这些选项,请先运行 `ccr stop`
<table>
<tr>
<td align="center" width="220">
<a href="https://ko-fi.com/F1F31GN2GM">
<img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="通过 Ko-fi 赞助" />
</a>
<br />
<sub>通过 Ko-fi 单次赞助</sub>
</td>
<td align="center" width="220">
<a href="https://paypal.me/musistudio1999">
<img src="https://img.shields.io/badge/PayPal-Sponsor-003087?logo=paypal&logoColor=white" alt="通过 PayPal 赞助" />
</a>
<br />
<sub>国际赞助通道</sub>
</td>
</tr>
</table>
## Agent 配置启动
<table>
<tr>
<td align="center" width="220">
<strong>支付宝</strong>
<br />
<img src="/blog/images/alipay.jpg" width="160" alt="支付宝收款码" />
</td>
<td align="center" width="220">
<strong>微信支付</strong>
<br />
<img src="/blog/images/wechat.jpg" width="160" alt="微信支付收款码" />
</td>
</tr>
</table>
先在 **Agent配置** 中创建并启用配置,然后按名称或 ID 启动:
</div>
```sh
ccr "Codex - Work"
ccr "Codex - Work" app
ccr "Claude - Review" cli -- --model sonnet
ccr profile-id -- --help
```
### 我们的赞助商
完整语法:
<div align="center">
```text
ccr <配置名称或 ID> [cli|app] [-- <Agent 参数>]
```
<p>非常感谢所有赞助商的慷慨支持。</p>
- `--cli``--app` 也可以代替位置形式的入口类型。
- Agent 自己的参数建议统一放到 `--` 后,避免被识别为 CCR 参数。
- 省略入口类型时,Claude Code、Codex、Grok CLI 默认使用 CLIZCode 默认使用 App。
- Grok 只支持 CLIZCode 只支持 App。Claude App 和 ZCode App 不接受额外 Agent 参数。
- 启动桌面 App 时,本机必须已安装对应应用,并且当前环境必须有图形会话。
- 大多数配置需要先启动 CCR 服务。Grok CLI 配置可以自动启动一个临时共享服务,并在最后一个受管会话退出后停止。
<table width="100%">
<tr>
<td align="center" width="330">
<a href="https://www.bigmodel.cn/claude-code?ic=FPF9IVAGFJ">
<img src="/docs/public/provider-icons/zhipu-cn-general.png" width="42" height="42" alt="智谱图标" />
<br />
<strong>Z智谱</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://aihubmix.com/">
<img src="https://www.google.com/s2/favicons?domain=aihubmix.com&amp;sz=128" width="42" height="42" alt="AIHubmix 图标" />
<br />
<strong>AIHubmix</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://ai.burncloud.com">
<img src="https://www.burncloud.com/favicon.png" width="42" height="42" alt="BurnCloud 图标" />
<br />
<strong>BurnCloud</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://share.302.ai/ZGVF9w">
<img src="https://www.google.com/s2/favicons?domain=302.ai&amp;sz=128" width="42" height="42" alt="302.AI 图标" />
<br />
<strong>302.AI</strong>
</a>
</td>
</tr>
<tr>
<td align="center" width="330">
<a href="https://runapi.co/register?aff=IX1t">
<img src="/docs/public/provider-icons/runapi.jpg" width="42" height="42" alt="RunAPI 图标" />
<br />
<strong>RunAPI</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://teamorouter.com/">
<img src="/docs/public/provider-icons/teamorouter.png" width="42" height="42" alt="TeamoRouter 图标" />
<br />
<strong>TeamoRouter</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://s.qiniu.com/AVjMVf">
<img src="/docs/public/provider-icons/qiniu-ai.png" width="42" height="42" alt="七牛云 AI 图标" />
<br />
<strong>七牛云 AI</strong>
</a>
</td>
<td align="center" width="330">
<a href="https://api.fenno.ai/register?redirect=/purchase?tab=subscription%26group=16&amp;aff=9HHHAB5QLAES">
<img src="/docs/public/provider-icons/fenno.jpg" width="42" height="42" alt="Fenno.ai 图标" />
<br />
<strong>Fenno.ai</strong>
</a>
</td>
</tr>
</table>
桌面应用会安装一个相关命令 `ccr-app`。桌面 Agent配置卡片复制出来的命令使用 `ccr-app`;本文介绍的 npm 包安装的是 `ccr`
<h4>社区赞助者</h4>
## 配置与运行文件
<table width="100%">
<tr>
<td align="center" width="220">@Simon Leischnig</td>
<td align="center" width="220"><a href="https://github.com/duanshuaimin">@duanshuaimin</a></td>
<td align="center" width="220"><a href="https://github.com/vrgitadmin">@vrgitadmin</a></td>
<td align="center" width="220">@*o</td>
<td align="center" width="220"><a href="https://github.com/ceilwoo">@ceilwoo</a></td>
<td align="center" width="220">@*说</td>
</tr>
<tr>
<td align="center" width="220">@*更</td>
<td align="center" width="220">@K*g</td>
<td align="center" width="220">@R*R</td>
<td align="center" width="220"><a href="https://github.com/bobleer">@bobleer</a></td>
<td align="center" width="220">@*苗</td>
<td align="center" width="220">@*划</td>
</tr>
<tr>
<td align="center" width="220"><a href="https://github.com/Clarence-pan">@Clarence-pan</a></td>
<td align="center" width="220"><a href="https://github.com/carter003">@carter003</a></td>
<td align="center" width="220">@S*r</td>
<td align="center" width="220">@*晖</td>
<td align="center" width="220">@*敏</td>
<td align="center" width="220">@Z*z</td>
</tr>
<tr>
<td align="center" width="220">@*然</td>
<td align="center" width="220"><a href="https://github.com/cluic">@cluic</a></td>
<td align="center" width="220">@*苗</td>
<td align="center" width="220"><a href="https://github.com/PromptExpert">@PromptExpert</a></td>
<td align="center" width="220">@*应</td>
<td align="center" width="220"><a href="https://github.com/yusnake">@yusnake</a></td>
</tr>
<tr>
<td align="center" width="220">@*飞</td>
<td align="center" width="220">@董*</td>
<td align="center" width="220">@*汀</td>
<td align="center" width="220">@*涯</td>
<td align="center" width="220">@*:-</td>
<td align="center" width="220">@**磊</td>
</tr>
<tr>
<td align="center" width="220">@*琢</td>
<td align="center" width="220">@*成</td>
<td align="center" width="220">@Z*o</td>
<td align="center" width="220">@*琨</td>
<td align="center" width="220"><a href="https://github.com/congzhangzh">@congzhangzh</a></td>
<td align="center" width="220">@*_</td>
</tr>
<tr>
<td align="center" width="220">@Z*m</td>
<td align="center" width="220">@*鑫</td>
<td align="center" width="220">@c*y</td>
<td align="center" width="220">@*昕</td>
<td align="center" width="220"><a href="https://github.com/witsice">@witsice</a></td>
<td align="center" width="220">@b*g</td>
</tr>
<tr>
<td align="center" width="220">@*亿</td>
<td align="center" width="220">@*辉</td>
<td align="center" width="220">@JACK</td>
<td align="center" width="220">@*光</td>
<td align="center" width="220">@W*l</td>
<td align="center" width="220"><a href="https://github.com/kesku">@kesku</a></td>
</tr>
<tr>
<td align="center" width="220"><a href="https://github.com/biguncle">@biguncle</a></td>
<td align="center" width="220">@二吉吉</td>
<td align="center" width="220">@a*g</td>
<td align="center" width="220">@*林</td>
<td align="center" width="220">@*咸</td>
<td align="center" width="220">@*明</td>
</tr>
<tr>
<td align="center" width="220">@S*y</td>
<td align="center" width="220">@f*o</td>
<td align="center" width="220">@*智</td>
<td align="center" width="220">@F*t</td>
<td align="center" width="220">@r*c</td>
<td align="center" width="220"><a href="https://github.com/qierkang">@qierkang</a></td>
</tr>
<tr>
<td align="center" width="220">@*军</td>
<td align="center" width="220"><a href="https://github.com/snrise-z">@snrise-z</a></td>
<td align="center" width="220">@*王</td>
<td align="center" width="220"><a href="https://github.com/greatheart1000">@greatheart1000</a></td>
<td align="center" width="220">@*王</td>
<td align="center" width="220">@zcutlip</td>
</tr>
<tr>
<td align="center" width="220"><a href="https://github.com/Peng-YM">@Peng-YM</a></td>
<td align="center" width="220">@*更</td>
<td align="center" width="220">@*.</td>
<td align="center" width="220">@F*t</td>
<td align="center" width="220">@*政</td>
<td align="center" width="220">@*铭</td>
</tr>
<tr>
<td align="center" width="220">@*叶</td>
<td align="center" width="220">@七*o</td>
<td align="center" width="220">@*青</td>
<td align="center" width="220">@**晨</td>
<td align="center" width="220">@*远</td>
<td align="center" width="220">@*霄</td>
</tr>
<tr>
<td align="center" width="220">@**吉</td>
<td align="center" width="220">@**飞</td>
<td align="center" width="220">@**驰</td>
<td align="center" width="220">@x*g</td>
<td align="center" width="220">@**东</td>
<td align="center" width="220">@*落</td>
</tr>
<tr>
<td align="center" width="220">@哆*k</td>
<td align="center" width="220">@*涛</td>
<td align="center" width="220"><a href="https://github.com/WitMiao">@苗大</a></td>
<td align="center" width="220">@*呢</td>
<td align="center" width="220">@d*u</td>
<td align="center" width="220">@crizcraig</td>
</tr>
<tr>
<td align="center" width="220">s*s</td>
<td align="center" width="220">*火</td>
<td align="center" width="220">*勤</td>
<td align="center" width="220">**锟</td>
<td align="center" width="220">*涛</td>
<td align="center" width="220">**明</td>
</tr>
<tr>
<td align="center" width="220">*知</td>
<td align="center" width="220">*语</td>
<td align="center" width="220">*瓜</td>
<td align="center" width="220"></td>
<td align="center" width="220"></td>
<td align="center" width="220"></td>
</tr>
</table>
| 平台 | 配置目录 |
| --- | --- |
| macOS / Linux | `~/.claude-code-router` |
| Windows | `%APPDATA%\claude-code-router` |
<sub>如果你的名字被打码,请通过我的主页邮箱联系我更新为 GitHub 用户名。</sub>
重要文件包括:
</div>
- `config.sqlite`:当前应用配置。
- `app-data/`:API Key、用量、请求日志、证书等运行数据库和文件。
- `service.json`:后台 CLI 服务的状态和私有 Token。
- `gateway.config.json`:生成的网关运行配置。
- `profiles/``bin/`:隔离的 Agent 配置和启动包装器。
CCR 写入 SQLite 时不要直接编辑或复制活跃数据库。优先使用 UI 导出;要做文件级备份,请先停止 CCR。
## 环境变量与安全
| 变量 | 说明 |
| --- | --- |
| `CCR_WEB_HOST` | 省略 `--host` 时使用的管理服务监听地址。 |
| `CCR_WEB_PORT` | 省略 `--port` 时使用的管理服务端口。 |
| `CCR_WEB_AUTH_TOKEN` | 固定管理 UI / RPC 的认证 Token;不设置时每个进程会生成随机 Token。 |
认证后的管理 URL 会在查询参数中包含 `ccr_web_token`。请把这个 URL 当作密码,不要复制到日志、工单或公开的 Shell 历史中。除非确实需要远程访问,否则监听地址应保持 `127.0.0.1`。远程访问时,应同时使用防火墙或私网,并在可信反向代理上启用 TLS。
不要在未创建 CCR 客户端 API Key 的情况下暴露网关。上游供应商凭据保存在 CCR 本地数据目录中,因此也要保护该目录及其备份。
## 常见问题
### 找不到 `ccr` 命令
确认 Node.js 不低于 22,并检查 npm 全局可执行目录是否在 `PATH`
```sh
node --version
npm prefix -g
```
如果 Shell 缓存了命令路径,安装后请打开一个新终端。
### 管理 URL 的端口发生变化
首选端口已被占用。请使用 CCR 打印的实际 URL,或停止占用端口的进程后重启 CCR。
### UI 能打开,但网关不可用
管理服务可以在没有可用网关时单独运行。请添加供应商和模型、创建客户端 API Key,然后从 **服务** 页面启动或重启网关。排查启动错误时,可以使用 `ccr serve` 查看前台输出。
### 找不到 Agent 配置
只有已启用的配置才能启动。名称匹配不区分大小写,也接受清理后的名称;如果多个名称产生歧义,必须使用配置 ID。生成的启动器缺失时,请重新保存配置。
### 后台服务仍使用旧参数
停止并重新创建服务:
```sh
ccr stop
ccr start --host 127.0.0.1 --port 3458
```
## Docker
仓库还提供面向模型网关和浏览器 UI 的 Docker 镜像。运行时镜像不会安装 npm 的 `ccr` 命令。请参阅 [Docker 部署文档](https://github.com/musistudio/claude-code-router/blob/main/docker/README.md)。
## 许可证
本项目基于 [MIT License](LICENSE) 发布。
[MIT](LICENSE)
+31 -11
View File
@@ -550,14 +550,21 @@ function printHelp(exitCode: number): void {
const command = cliCommandName();
const output = [
"Usage:",
` ${command} start [--host <host>] [--port <port>] [--open] [--no-gateway]`,
` ${command} ui [--host <host>] [--port <port>] [--no-gateway]`,
` ${command} start [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]`,
` ${command} ui [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]`,
` ${command} serve [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]`,
` ${command} stop`,
` ${command} <profile-name-or-id> [cli|app] [-- <agent args>]`,
"",
"Notes:",
` ${command} web is an alias for ${command} serve.`,
" --cli and --app are alternatives to the positional profile surface.",
" Put agent-specific arguments after --.",
"",
"Examples:",
` ${command} start`,
` ${command} ui`,
` ${command} serve --no-open`,
` ${command} stop`,
` ${command} Codex`,
` ${command} default-codex -- --model gpt-5-codex`,
@@ -572,16 +579,19 @@ function printStartHelp(exitCode: number): void {
const command = cliCommandName();
const output = [
"Usage:",
` ${command} start [--host <host>] [--port <port>] [--open] [--no-gateway]`,
` ${command} start [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]`,
"",
"Options:",
" --host <host> Management server host. Defaults to 127.0.0.1.",
" --port <port> Management server port. Defaults to 3458.",
" --host <host> Management server host. Defaults to CCR_WEB_HOST or 127.0.0.1.",
" --port <port> Management server port. Defaults to CCR_WEB_PORT or 3458.",
" --open Open the management page in the default browser.",
" --no-open Do not open the management page.",
" --gateway Start the configured model gateway (default).",
" --no-gateway Start only the web management server.",
"",
"Environment:",
" CCR_WEB_HOST Default management server host.",
" CCR_WEB_PORT Default management server port.",
" CCR_WEB_AUTH_TOKEN Use this token for management UI and RPC authentication."
].join("\n");
const stream = exitCode === 0 ? process.stdout : process.stderr;
@@ -593,17 +603,21 @@ function printUiHelp(exitCode: number): void {
const command = cliCommandName();
const output = [
"Usage:",
` ${command} ui [--host <host>] [--port <port>] [--no-gateway]`,
` ${command} ui [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]`,
"",
"Starts the background CCR service if needed and opens the management UI in the default browser.",
"",
"Options:",
" --host <host> Management server host. Defaults to 127.0.0.1.",
" --port <port> Management server port. Defaults to 3458.",
" --host <host> Management server host. Defaults to CCR_WEB_HOST or 127.0.0.1.",
" --port <port> Management server port. Defaults to CCR_WEB_PORT or 3458.",
" --open Open the management page (default).",
" --no-open Start or find the service and print the management URL without opening a browser.",
" --gateway Start the configured model gateway (default).",
" --no-gateway Start only the web management server when the service is not already running.",
"",
"Environment:",
" CCR_WEB_HOST Default management server host.",
" CCR_WEB_PORT Default management server port.",
" CCR_WEB_AUTH_TOKEN Use this token for management UI and RPC authentication."
].join("\n");
const stream = exitCode === 0 ? process.stdout : process.stderr;
@@ -628,15 +642,21 @@ function printWebHelp(exitCode: number): void {
const command = cliCommandName();
const output = [
"Usage:",
` ${command} serve [--host <host>] [--port <port>] [--open] [--no-gateway]`,
` ${command} serve [--host <host>] [--port <port>] [--open|--no-open] [--gateway|--no-gateway]`,
"",
`Runs in the foreground. ${command} web is an alias.`,
"",
"Options:",
" --host <host> Management server host. Defaults to 127.0.0.1.",
" --port <port> Management server port. Defaults to 3458.",
" --host <host> Management server host. Defaults to CCR_WEB_HOST or 127.0.0.1.",
" --port <port> Management server port. Defaults to CCR_WEB_PORT or 3458.",
" --open Open the management page in the default browser.",
" --no-open Do not open the management page (default).",
" --gateway Start the configured model gateway (default).",
" --no-gateway Start only the web management server.",
"",
"Environment:",
" CCR_WEB_HOST Default management server host.",
" CCR_WEB_PORT Default management server port.",
" CCR_WEB_AUTH_TOKEN Use this token for management UI and RPC authentication."
].join("\n");
const stream = exitCode === 0 ? process.stdout : process.stderr;