cc-gateway
A local multi-provider gateway that impersonates the Anthropic Messages API for Claude Code, so you can switch between models from different backends at any point in any session.
It forwards the Anthropic dialect only. Every backend must expose an Anthropic-compatible endpoint; there is deliberately no OpenAI translation layer.
Providers
| provider | endpoint | auth |
|---|---|---|
coconut |
http://127.0.0.1:8787 (local daemon) |
Bearer coconut |
glm |
https://open.bigmodel.cn/api/anthropic |
x-api-key, $GLM_API_KEY |
mimo |
https://token-plan-cn.xiaomimimo.com/anthropic |
x-api-key, $MIMO_API_KEY |
Install
Requires Python 3.11+ (tomllib is stdlib there).
uv tool install ccgw
# or
pipx install ccgw
Run
The gateway reads its provider registry from a config.toml, looked up in
this order: $CCGW_CONFIG, ./config.toml, ~/.config/ccgw/config.toml.
export GLM_API_KEY=... # never stored in this repo
export MIMO_API_KEY=...
ccgw # listens on 127.0.0.1:8788
ccgw --port 9000 # or --config /path/to/config.toml
A source checkout can run the same entry point directly:
pip install -r requirements.txt
python serve.py
Point Claude Code at it in ~/.claude/settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8788",
"ANTHROPIC_AUTH_TOKEN": "ccgw",
"ANTHROPIC_API_KEY": "",
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
}
}
Claude Code may request built-in Opus, Sonnet, or Haiku ids for background
work. Keep those mappings explicit under [routing.aliases]; any unlisted model
fails closed instead of silently running an arbitrary provider.
Model naming
Public ids keep the v0.1.0 form: claude-<slug(upstream)> plus a [1m]
suffix for models with a 1M context window. Both parts are load-bearing:
- Claude Code's gateway discovery drops any id that does not contain
claudeoranthropic, so the prefix is mandatory for a model to appear in/model. - Claude Code infers a 1M window from a
[1m]substring, which is how the gateway communicates window size./v1/modelscannot carry it: Claude Code's parser keeps onlyidanddisplay_name.
The suffix is presentation only. It is stripped before the request goes
upstream, because neither GLM nor MiMo accepts a [1m] model name on these
endpoints (both reject it outright), even though their Coding Plan docs
describe the suffix.
Behaviour worth knowing
Transparent by default. Request history and parameters are forwarded unless
a [providers.<name>.compat] option explicitly enables an adapter. Unknown
models return 404 rather than silently running the first configured model;
[routing.aliases] provides auditable mappings for Claude Code background model
ids.
Thinking provenance. Same-route history is preserved. Once a session has switched model routes, provider-bound thinking blocks are stripped from later replays. A provider may also explicitly enable one retry without thinking after a thinking-shaped 400.
Tool repair is opt-in. compat.repair_tools = true normalises invalid tool
ids and supplies interrupted tool results. Tool names and tool inputs are never
rewritten.
Errors. Upstream failures are re-shaped into the Anthropic envelope while preserving their message. Retry, request-id, and rate-limit response headers are relayed to Claude Code.
Streaming. The upstream is requested without content compression and read through a decoding iterator. Complete SSE events are relayed as units, so the 15-second keepalive ping cannot split an event.
Token counting. /v1/messages/count_tokens follows the selected model to
its upstream endpoint. Unsupported providers return their real error so Claude
Code can use its own fallback; the gateway never invents a tokenizer estimate.
Tests
python tests/selftest.py
The self-test uses loopback stub servers only; it needs no provider credentials or external network.
License
Metadata
Release files for ccgw 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ccgw-0.1.1.tar.gz | 26.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ccgw-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.6 kB
Release files / ccgw-0.1.1.tar.gz
| Download URL | ccgw-0.1.1.tar.gz |
|---|---|
| Size | 26.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f3fc7ea6225f7a3594c4082dcf8b3999b0b57564ab6fd5debc008e819fc7495f
|
|
BLAKE2b-256 checksum How to use checksums |
f8ce63f1da12ed579ce353902def4238d9c55a65a240402b0e9313b73f3888bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.
Transparency logRelease files / ccgw-0.1.1-py3-none-any.whl
| Download URL | ccgw-0.1.1-py3-none-any.whl |
|---|---|
| Size | 23.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b991c115b516d4ad64f2374216b6f6e9d4f032086f9b74ce6b147cff0b91482
|
|
BLAKE2b-256 checksum How to use checksums |
4ca98edf0dc42d37a324f780ba83646b873324f25e4d598d6dce2573d044ef89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.
Transparency log