Claude Relay Service: what the compose file, five cooldown variables, and the v1.1.248 advisory tell you
CRS - a self-hosted Claude Code mirror and all-in-one open-source relay service that unifies access to Claude, OpenAI, Gemini and Droid subscriptions, supports shared/pooled subscriptions to split costs more efficiently, and works seamlessly with native tools.
At a glance
- What is it?
- Wei-Shaw's JavaScript relay puts several Claude Code Max accounts behind one endpoint and hands each user a separate key. Its own files are unusually candid about the sharp parts: an unauthenticated admin panel in every release up to v1.1.248, an installer that runs a script from the vendor's own site, and cost tracking that converts token usage at official prices.
- Who is it for?
- Use this relay if you are splitting one Max subscription with a handful of people you trust and you can run Node.js 18, Redis 6, and a server that reaches the Anthropic API without tripping Cloudflare. Skip it if your region already has clean access to Claude, if you cannot absorb the terms of service risk the project warns about, or if you want the authors' own current recommendation, since they point new deployments at CRS 2.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- Wei-Shaw/claude-relay-service12,808 ★ · +188
| Repository | 2026-09-15 | 2026-11-14 |
|---|---|---|
| Wei-Shaw/claude-relay-service | 12.6k | 12.8k |
188 Stars in the last 60 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Every release up to v1.1.248 has an unauthenticated admin panel
The project opens with a CAUTION block stating that v1.1.248 and earlier carry a serious admin authentication bypass, letting attackers reach the admin panel without authorization, and it tells you to move to v1.1.249 or later, or migrate to the successor project CRS 2.0 at github.com/Wei-Shaw/sub2api. Read that twice, because it is the author steering new deployments somewhere else rather than a routine advisory. The tree is still active: tags v1.1.313 on 2026-07-10, v1.1.314 on 2026-07-23, and v1.1.315 on 2026-09-10, with the last push dated 2026-10-31. If a copy is running, the version check comes before every other task, because an open admin panel leaks keys and usage records rather than merely returning errors.
Both installers execute a shell script fetched from pincc.ai
The recommended install is one line that downloads and runs a script hosted on the project's own site:
curl -fsSL https://pincc.ai/manage.sh -o manage.sh && chmod +x manage.sh && ./manage.sh installIt leaves you with a crs command set covering install, start, stop, restart, status, update, and uninstall. The Docker route repeats the pattern with a different file, then starts a stack:
curl -fsSL https://pincc.ai/crs-compose.sh -o crs-compose.sh && chmod +x crs-compose.sh && ./crs-compose.shdocker-compose up -dNeither path pins a checksum, a signature, or a tag, so what executes is whatever that host serves at that moment. The manual path is fully spelled out and starts from a clone, though the URL carries a doubled slash:
git clone https://github.com/Wei-Shaw//claude-relay-service.gitNothing here breaks the auditable route, it just makes the fast one the default. Save the script and read it before running it, since the same script installs Node.js 18 and Redis and then starts a network service on a port you type in.
Five cooldown variables decide how long a failed account sits out
When the upstream misbehaves, the service suspends an account from routing, and the duration is set by five names in .env.example: UPSTREAM_ERROR_503_TTL_SECONDS, UPSTREAM_ERROR_5XX_TTL_SECONDS, UPSTREAM_ERROR_OVERLOAD_TTL_SECONDS, UPSTREAM_ERROR_AUTH_TTL_SECONDS, and UPSTREAM_ERROR_TIMEOUT_TTL_SECONDS. The admin panel adds per-account overrides for Claude official OAuth accounts: a switch to disable temporary cooldown for that account, plus separate 503 and 5xx second fields where a blank value follows the global setting and 0 turns that cooldown off for the account. Precedence runs from the account disable switch, to the account second values, to a TTL supplied at call time, down to the environment defaults. The account list names the reason a pool is unroutable, with the error type, HTTP status, total cooldown, remaining time, and estimated recovery, and a reset action labeled `重置状态` clears it.
Sticky sessions last one hour, and the renewal comment contradicts its own value
The shipped .env.example sets STICKY_SESSION_TTL_HOURS=1 and STICKY_SESSION_RENEWAL_THRESHOLD_MINUTES=15, then annotates the second line with a comment saying the default is 0 minutes, meaning no renewal. The comment and the assigned value disagree, so check which one applies when the variable is missing from your environment. TTLs and renewal thresholds are what keep a coding client attached to one Claude account instead of bouncing across the pool mid task, so this is not a cosmetic line. The panel's unroutable reason display shows why an account has dropped out of routing. Read the value in your own .env before blaming the model.
The compose file persists logs and data but bakes configuration into the image
docker-compose.yml builds from the repository Dockerfile and maps exactly two paths, ./logs to /app/logs and ./data to /app/data, while every setting arrives as an environment variable. The published port is `${BIND_HOST:-0.0.0.0}:${PORT:-3000}:3000`, so the default binds every interface and the file's own comment asks production to set BIND_HOST=127.0.0.1 behind a reverse proxy. Meanwhile the Dockerfile copies config.example.js to config.js at build time only when no config.js is already present, and it creates logs, data, and temp during the build, which means anything you edit inside a running container is erased by the next image rebuild. Two required values dominate that setup: JWT_SECRET at least 32 characters and an ENCRYPTION_KEY of exactly 32 characters, with ADMIN_USERNAME and ADMIN_PASSWORD optional and auto generated into data/init.json otherwise. The runtime is node:18-alpine with dumb-init, a 60 MB request body cap, and a health check that curls http://localhost:3000/health every 30 seconds. There is no config volume, so keep configuration in env vars and treat any in container edit as temporary.
Per key limits cover rate, concurrency, model, and client, but nobody gets a bill
Creating a key in the API Keys tab issues a prefixed value, since API_KEY_PREFIX defaults to cr_, and offers four optional limits: a rate limit over request count and token usage per time window, a concurrency cap on simultaneous requests, a model allowlist, and a client restriction naming values such as ClaudeCode and Gemini-CLI. That is enough to stop one member from draining the pool and enough to see who spent what. It is not enough to settle up. Cost is reported by converting usage at official prices, and the price table is maintained by scripts that are named but not explained: npm run update:pricing and npm run init:costs. The project also states plainly that using it may violate Anthropic's terms of service, that it is offered for technical study and research, and that the author accepts no liability for account bans or interruption. Settle the method and the acceptable risk before keys go out, not after.
Gemini and Antigravity OAuth secrets live in the code unless you override them
In .env.example the Gemini and Antigravity OAuth entries are all commented out: GEMINI_OAUTH_CLIENT_ID, GEMINI_OAUTH_CLIENT_SECRET, GEMINI_OAUTH_REDIRECT_URI, the matching ANTIGRAVITY client id and secret, ANTIGRAVITY_API_URL, and ANTIGRAVITY_USER_AGENT. The accompanying note says unset values fall back to defaults compiled into the code, and that overriding them here is how you customize behavior or keep a client secret out of the source. That is a candid constraint rather than a hidden one, and it has a practical edge: the Antigravity redirect URI defaults to http://localhost:45462, used, per .env.example, to avoid redirect_uri_mismatch. Routing splits by path, with /api going to the Claude account pool, /antigravity/api to Antigravity OAuth, and /gemini-cli/api to Gemini CLI OAuth, and .env.example notes this path split needs no extra environment variable. The Claude side pins CLAUDE_API_VERSION=2023-06-01 and a fixed CLAUDE_BETA_HEADER listing four beta flags, including oauth-2025-04-20 and interleaved-thinking-2025-05-14. All four live in a single comma separated variable, so changing the set is a config edit.
Editorial conclusion
Use this relay if you are splitting one Max subscription with a handful of people you trust and you can run Node.js 18, Redis 6, and a server that reaches the Anthropic API without tripping Cloudflare. Skip it if your region already has clean access to Claude, if you cannot absorb the terms of service risk the project warns about, or if you want the authors' own current recommendation, since they point new deployments at CRS 2. Before the first key is handed out, confirm the running version is v1.1.249 or later, read the manage.sh you are about to execute instead of piping it straight to a shell, and decide how the group's token spend gets divided.
Frequently asked questions
Who uses relay services?
The project positions itself for people who cannot reach Claude Code from their region, who do not want a third-party mirror reading their conversations, who want to split a Claude Code Max subscription with friends, and who are frustrated by third-party mirrors that slow down or hang at peak hours.
What is relay communication?
Nothing in this repository frames it that way. Here a relay is an HTTP forwarder: CLAUDE_API_URL defaults to https://api.anthropic.com/v1/messages, and path based routing sends /api to the Claude account pool, /antigravity/api to Antigravity OAuth, and /gemini-cli/api to Gemini CLI OAuth.
What is relay coding?
On this project's terms it means pointing a coding client at your own relay instead of the vendor, by exporting ANTHROPIC_BASE_URL="http://127.0.0.1:3000/api/" on the machine running Claude Code, or the Gemini CLI equivalent, so requests pass through the server you control.
Is Claude a free service?
The project never claims it is. Its cost section lists a lightweight server at 30 to 60 yuan per month plus a Claude subscription split however you divide it, and the warning at the top says use may violate Anthropic's terms of service, with the author accepting no responsibility for bans or interruption.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wei-shaw-claude-relay-service)Star history chart for your README
[](https://hysenlabs.com/projects/wei-shaw-claude-relay-service)Was this useful?