Model Gateway
mur-model-gateway is a companion service that gives your agents one local
endpoint for Anthropic, OpenAI, and Gemini — and lets them reuse the
credentials you already have (including your Claude Code subscription login)
instead of a separate metered API key.
# install a released binary, then run it as a background service
mur-model-gateway install
mur-model-gateway status
It lives in its own repository: github.com/mur-run/mur-model-gateway.
How it works
The gateway listens on 127.0.0.1:8088 and routes by path:
| Path | Upstream |
|---|---|
/v1/messages* | api.anthropic.com |
/v1/chat/completions*, /v1/embeddings* | api.openai.com |
/v1beta/models/* | generativelanguage.googleapis.com |
Requests that already carry auth are forwarded untouched. Requests without auth get credentials attached from the configured token source — by default the OS keychain entry Claude Code maintains, so agents ride the plan you already pay for.
Use it from MUR
Point a model registry entry's base_url at the gateway:
# ~/.mur/models.yaml
models:
- alias: sonnet
provider: anthropic
model: claude-sonnet-5
base_url: http://127.0.0.1:8088
Every agent using that alias now goes through the gateway. Nothing else in MUR changes — pricing, routing, and the Model Library all keep working.
ChatGPT Subscription (no API key)
MUR Hub can connect a ChatGPT Plus/Pro plan through Codex CLI, so agents run on the subscription instead of a usage-billed API key.
Model Library → Add Provider → ChatGPT Subscription
1. Sign in with ChatGPT (codex login — the browser flow Codex owns)
2. Install gateway (consent card, then install --token-source-codex codex)
3. Pick the models on your plan
Who owns what:
| Concern | Owner |
|---|---|
| Sign-in and the credential on disk | Codex CLI |
| Account / plan / model status | MUR Hub, via a short-lived codex app-server session |
| Attaching and refreshing the token, Responses-API translation | mur-model-gateway |
| Registry entries and agent assignment | MUR |
MUR never reads or copies the Codex credential file; the Hub only sees "signed in as email on plan X" and model ids.
Each picked model becomes a registry entry with provider: codex, billing: subscription and no secret:
chatgpt_gpt_5_6_sol:
provider: codex
model: gpt-5.6-sol
base_url: http://127.0.0.1:8088/codex/v1
billing: subscription
catalog_verified: true
The runtime sends authless requests only to that loopback /codex/v1 route — a remote host, https, or a secret on the entry is refused at startup, so a typo cannot land on OpenAI Platform billing. GET /__mur/health reports whether the gateway has the Codex hook and which kind of credential it sees (chatgpt, apikey, missing); the Hub treats only chatgpt as ready.
Billing safety. Pickers and fallback-chain rows show a billing label (Subscription, Usage billed, Local, or Billing unknown — unknown is never shown as free). A 429 from the subscription does not make MUR spend money: it never inserts a usage-billed OpenAI model behind a ChatGPT model on its own, and the chain editor warns if you add one yourself.
Disconnect vs sign out. Disconnect MUR removes the subscription entries from models.yaml and leaves the Codex login alone. Sign out of ChatGPT runs codex logout after a confirmation, because it signs out every Codex client on the machine — CLI and IDE extensions included.
If model/list cannot be read, the panel offers Advanced: add an unverified model ID; the entry is marked catalog_verified: false and badged Unverified.
Claude Subscription (no API key)
The same shape as ChatGPT Subscription, for a Claude Pro/Max plan through Claude Code. The CLI is Claude Code and the gateway route is /v1.
Model Library → Add Provider → Claude Subscription
1. Sign in with Claude (claude auth login --claudeai)
2. Install gateway (consent card)
3. Pick models (from the models.dev catalog)
Who owns what:
| Concern | Owner |
|---|---|
| Sign-in and the credential on disk | Claude Code |
| Account status | MUR Hub, via claude auth status --json |
| Attaching and refreshing the token | mur-model-gateway |
| Registry entries and agent assignment | MUR |
MUR never reads the Claude Code credential. The Hub keeps three fields from claude auth status — signed in or not, which login kind, and the email — and drops the rest. Only authMethod: "claude.ai" is a subscription: an Anthropic Console login is the API and reads as "signed in, but not this provider".
Each picked model becomes a registry entry with provider: claude, billing: subscription and no secret:
claude_opus_5:
provider: claude
model: claude-opus-5
base_url: http://127.0.0.1:8088/v1
billing: subscription
catalog_verified: true
The runtime sends Anthropic Messages requests with no x-api-key header at all — absent, not empty, because the gateway decides what to do by whether an auth header is present. It accepts only that loopback /v1 shape: a remote host, an https URL, or a secret on the entry is refused at startup. GET /__mur/health reports claudeCredential (oauth or missing — a kind, never a token); the Hub treats only oauth as ready.
Already using provider: anthropic with the gateway? It keeps working. The difference is what the entry guarantees: provider: anthropic is the same route with no protection, so one base_url edit to api.anthropic.com turns it into a metered API entry and nothing objects. mur model doctor points at the entries that could carry the explicit label; it stays quiet about one that has a secret, because what that entry does depends on the token inside and doctor does not read secrets.
Disconnect vs sign out. Disconnect MUR removes the subscription entries from the registry and leaves the Claude Code login alone. Sign out of Claude runs claude auth logout after a confirmation, because it signs Claude Code out everywhere on this machine — terminal sessions and IDE extensions included.
Configuration
| Env var | Default | Meaning |
|---|---|---|
MUR_MODEL_GATEWAY_BIND | 127.0.0.1:8088 | Listen address |
MUR_MODEL_GATEWAY_TOKEN_SOURCE | keychain | keychain, off, env:<VAR>, file, or file:<path> |
MUR_MODEL_GATEWAY_COMPRESS | off | 1 enables tool_result wire compression |
Upstreams are overridable per provider
(MUR_MODEL_GATEWAY_UPSTREAM_ANTHROPIC / _OPENAI / _GEMINI).
Notes
- Loopback-only by default — it is a local outlet, not a shared server.
- macOS release binaries are Developer-ID signed and notarized, so the keychain "Always Allow" you grant once survives every update.
- Formerly known as
cc-proxy; renamed when it grew beyond Claude Code to cover OpenAI and Gemini.