Metadata-Version: 2.5
Name: ccgw
Version: 0.1.0
Summary: Local multi-provider Anthropic-protocol gateway for Claude Code: coconut, GLM and MiMo in one /model menu.
Project-URL: Homepage, https://github.com/XuNeo/ccgw
Project-URL: Repository, https://github.com/XuNeo/ccgw
Project-URL: Issues, https://github.com/XuNeo/ccgw/issues
Author: XuNeo
License-Expression: MIT
License-File: LICENSE
Keywords: anthropic,claude,claude-code,gateway,glm,llm,mimo,proxy
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx>=0.27
Requires-Dist: uvicorn[standard]>=0.32
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Description-Content-Type: text/markdown

# 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).

```bash
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`.

```bash
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:

```bash
pip install -r requirements.txt
python serve.py
```

Point Claude Code at it in `~/.claude/settings.json`:

```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"
  }
}
```

Do **not** set `ANTHROPIC_DEFAULT_*_MODEL` or `ANTHROPIC_SMALL_FAST_MODEL`:
the gateway serves every model from one catalogue, and pinning those variables
would route background traffic around the router.

## Model naming

Public ids are generated as `claude-<provider>-<slug>` 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 `claude`
  or `anthropic`, 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/models` cannot carry it: Claude Code's
  parser keeps only `id` and `display_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

**History sanitisation.** Every request has `thinking` and `redacted_thinking`
blocks stripped from the history, unconditionally. Thinking signatures are
bound to the model and credentials that produced them, and Claude Code replays
the full history verbatim when you switch models, so a stale signature is a 400
that can wedge a session permanently. Stripping is stateless, matches
Anthropic's own guidance for switching models, and is a no-op for backends that
ignore thinking anyway. The top-level `thinking` parameter is removed in
lockstep, since removing the blocks alone is itself a 400.

**Tool repair.** Tool ids are normalised to `^[a-zA-Z0-9_-]+$` and dangling
`tool_use` blocks get a synthetic error result, both of which are otherwise
400s after an interrupted turn.

**Errors.** Upstream failures are re-shaped into the Anthropic envelope but the
upstream message text is preserved verbatim, because Claude Code matches on it
to drive automatic capability downgrade and retry.

**Streaming.** Upstream bytes are relayed unbuffered, with a `ping` injected
every 15 seconds of silence to stay under Claude Code's 300 second stream
watchdog.

**Token counting.** `/v1/messages/count_tokens` is answered locally and never
proxied; coconut does not implement it, and Claude Code falls back to its own
estimate anyway.

## License

[MIT](LICENSE)
