Skip to content

Repository files navigation

claude-code-gateway

Go Release Tests Docker License

Self-hosted AI gateway in pure Go for Claude Code and any OpenAI/Anthropic-compatible client. One binary, zero heavy dependencies, multi-provider routing with key rotation, fallbacks, budgets, semantic cache, guardrails, and an MCP control surface.

Inspired by the best: OmniRoute · claude-code-router · LiteLLM · one-api · Bifrost · Portkey — all credited in Credits.

Features

Core

  • 6 provider types: anthropic, anthropic-compat, openai, bedrock (SigV4 + event-stream), vertex (api-key / bearer / service-account), antigravity (free Claude Opus 4.5 via Google OAuth)
  • Full Anthropic ↔ OpenAI protocol translation, both directions, including streaming SSE
  • Dual protocol: POST /v1/messages (Anthropic) + POST /v1/chat/completions (OpenAI) — works with Claude Code, OpenCode, Cursor, Aider, Continue, any OpenAI SDK
  • Key rotation: round-robin or fill-first, cooldown with exponential backoff, Retry-After respect
  • Fallback chains + circuit breaker (5 consecutive failures → 2 min pause)
  • Load balancing: weighted / least_busy / latency (EMA) strategies

Routing

  • Scenario routing (from claude-code-router): long_context / image / thinking — route to different chains based on request content
  • Combo models: one alias → chain of different models with fallback
  • Session-sticky routing by metadata.user_id
  • Prefix-based rules with model mapping and stripping

Client management

  • Virtual keys (LiteLLM-style): named clients with USD budgets (daily/weekly/monthly), allowed_models glob patterns, TPM limits
  • Per-request headers (Cloudflare AI Gateway-style): x-ccg-skip-cache, x-ccg-cache-ttl, x-ccg-cache-key, x-ccg-collect-log, x-ccg-max-attempts, x-ccg-metadata

Observability

  • Web dashboard: charts (24h + 14d), per-provider/model breakdowns, live request feed, YAML config editor with validation + rollback
  • Prometheus /metrics: requests, tokens, cost, latency histogram, per-provider/model
  • Usage webhooks with HMAC signatures
  • TTFT (time-to-first-byte) per streamed request
  • CSV export

Security

  • Guardrails: block/redact regex patterns on request and response, PII presets (email, phone, card), prompt-injection detection, denied tools, streaming scan
  • Response cache: exact + semantic (embeddings-based), per-request TTL override
  • Rate limiting: RPM + TPM per client token
  • Distributed state: Redis or Postgres for multi-replica deployments

Extensibility

  • MCP server (HTTP + stdio): manage the gateway from Claude — stats, logs, models, budgets, reload, cost estimation
  • Request transformers: max_tokens_cap, set:key=value, reasoning_effort, drop_keys, system_prefix
  • Price auto-sync from OpenRouter API
  • Hot config reload (POST /admin/reload) — no restart needed
  • YAML config editor with validation + backup + rollback

Quick start

git clone https://github.com/Mukller/claude-code-gateway.git
cd claude-code-gateway
cp .env.example .env   # add your provider keys
docker compose up -d --build

Point Claude Code at the gateway:

export ANTHROPIC_BASE_URL=http://localhost:8090
export ANTHROPIC_AUTH_TOKEN=ccg-local-dev-token
export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
claude

Or use a pre-built binary:

# Download from Releases
chmod +x cc-gateway-linux-amd64
./cc-gateway-linux-amd64 -config config.yaml

Or Docker:

docker run -d -p 8090:8090 \
  -v ./config.yaml:/app/config.yaml:ro \
  -v ./data:/app/data \
  -e NINE_ROUTER_KEY=sk-... \
  ghcr.io/mukller/claude-code-gateway:latest

Connect any tool

The gateway exposes both Anthropic and OpenAI protocols simultaneously:

Tool Protocol Base URL
Claude Code Anthropic http://localhost:8090 (no /v1)
OpenCode OpenAI http://localhost:8090/v1
Cursor OpenAI http://localhost:8090/v1
Aider OpenAI http://localhost:8090/v1
Zed OpenAI http://localhost:8090/v1
Continue OpenAI http://localhost:8090/v1
Windsurf OpenAI http://localhost:8090/v1
Any OpenAI SDK OpenAI http://localhost:8090/v1

OpenCode config (~/.config/opencode/config.json):

{
  "provider": {
    "gateway": {
      "apiKey": "ccg-local-dev-token",
      "baseUrl": "http://localhost:8090/v1",
      "models": {
        "claude-sonnet-4-5": { "name": "Sonnet 4.5 (gateway)" },
        "claude-opus-4-5": { "name": "Opus 4.5 (gateway)" }
      }
    }
  },
  "model": "gateway/claude-sonnet-4-5"
}

Cursor (Settings → Models → OpenAI API Key):

  • API Key: ccg-local-dev-token
  • Base URL: http://localhost:8090/v1

Aider:

export OPENAI_API_BASE=http://localhost:8090/v1
export OPENAI_API_KEY=ccg-local-dev-token
aider --model gateway/claude-sonnet-4-5

curl:

curl http://localhost:8090/v1/chat/completions \
  -H "x-api-key: ccg-local-dev-token" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hello"}]}'

Provider examples

Anthropic (direct)
providers:
  - name: anthropic
    type: anthropic
    base_url: "https://api.anthropic.com"
    keys: ["${ANTHROPIC_API_KEY}"]
OpenRouter
providers:
  - name: openrouter
    type: openai
    base_url: "https://openrouter.ai/api/v1"
    keys: ["${OPENROUTER_KEY}"]
    discover_models: true
DeepSeek
providers:
  - name: deepseek
    type: openai
    base_url: "https://api.deepseek.com/v1"
    keys: ["${DEEPSEEK_KEY}"]
    models:
      - deepseek-chat
      - deepseek-reasoner
Groq
providers:
  - name: groq
    type: openai
    base_url: "https://api.groq.com/openai/v1"
    keys: ["${GROQ_KEY}"]
    discover_models: true
Mistral
providers:
  - name: mistral
    type: openai
    base_url: "https://api.mistral.ai/v1"
    keys: ["${MISTRAL_KEY}"]
    discover_models: true
Together AI
providers:
  - name: together
    type: openai
    base_url: "https://api.together.xyz/v1"
    keys: ["${TOGETHER_KEY}"]
    discover_models: true
xAI (Grok)
providers:
  - name: xai
    type: openai
    base_url: "https://api.x.ai/v1"
    keys: ["${XAI_KEY}"]
Cerebras
providers:
  - name: cerebras
    type: openai
    base_url: "https://api.cerebras.ai/v1"
    keys: ["${CEREBRAS_KEY}"]
Fireworks AI
providers:
  - name: fireworks
    type: openai
    base_url: "https://api.fireworks.ai/inference/v1"
    keys: ["${FIREWORKS_KEY}"]
Ollama (local)
providers:
  - name: ollama
    type: openai
    base_url: "http://localhost:11434/v1"
    keys: ["ollama"]
    models:
      - llama3:70b
      - codellama:34b
AWS Bedrock
providers:
  - name: bedrock
    type: bedrock
    region: us-east-1
    keys: ["${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}"]
Google Vertex AI
providers:
  - name: vertex
    type: vertex
    auth_style: api-key
    keys: ["${VERTEX_API_KEY}"]
Antigravity (free Claude Opus 4.5)
providers:
  - name: antigravity
    type: antigravity
    antigravity_auth_file: "~/.local/share/opencode/auth.json"

Requires opencode auth login → Google → Antigravity (one-time).

Free tier providers

These 6 providers offer free models (registration + API key required, no payment needed). All expose OpenAI-compatible endpoints so use type: openai in the gateway config.

Provider Free models Notes
OrcaRouter orcarouter/free, deepseek/deepseek-v4-flash-free, deepseek/deepseek-v4-pro-free, qwen/qwen3.8-27b-free No key, no card
TeamoRouter deepseek-v4-flash-free, deepseek-v4-pro-free 1M context, $0 in/out
AgentRouter claude-opus-4-8, claude-opus-5, gpt-5.6-sol $125 credits on sign-up (GitHub account age matters)
Token Harbor mimo-v2.5:free, deepseek-v4-flash:free Email confirmation, 7-day free window
NaraRouter agnes-2.0-flash, agnes-2.5-flash, laguna-s-2.1, mistral-large, mistral-medium-3-5, tencent-hy3-free 7M tokens/day, 10 req/min — needs Telegram
FreeRouter qwen3.8-max No account needed, 100 req/min

Only-free routing

To enforce a strictly free model policy (return 403 on any non-free model request), enable the gateway-level gate:

routing:
  free_only: true
  free_models:
    - "openai/*"
    - "deepseek/*"
    - "qwen/*"
    - "mistral/*"

Any request to a model outside this list (e.g. anthropic/claude-opus-4) returns 403 forbidden: model X is not in free_models list. Pattern syntax: only the suffix * is supported (e.g. openai/*, deepseek/*).

Example: dual-purpose setup (free + paid)

providers:
  - name: orcarouter
    type: openai
    base_url: "https://www.orcarouter.ai/api/v1"
    keys: ["${ORCAROUTER_KEY}"]
  - name: teamorouter
    type: openai
    base_url: "https://teamorouter.com/api/v1"
    keys: ["${TEAMOROUTER_KEY}"]
  - name: nara
    type: openai
    base_url: "https://router.bynara.id/api/v1"
    keys: ["${NARA_KEY}"]

routing:
  rules:
    - prefix: "free/"
      strip_prefix: true
      chain: [orcarouter, teamorouter, nara]

clients:
  - name: dima
    token: "${DIMA_TOKEN}"
    allowed_models:
      - "deepseek/*"
      - "qwen/*"
    # 0 budget = blocked immediately, can be bumped at runtime via
    #   curl -X POST -H "x-api-key: $ADMIN" -H "Content-Type: application/json" \
    #        -d '{"name":"dima","budget_usd":5}' http://localhost:8090/admin/tokens/update
    budget_usd: 0
    budget_period: monthly

Configuration

Full config example
server:
  listen: ":8090"
  keepalive_seconds: 15
  shutdown_timeout: 60s

auth:
  require_auth: true
  tokens:
    - "${GATEWAY_TOKEN}"
  admin_token: "${GATEWAY_ADMIN_TOKEN}"

clients:
  - name: anton
    token: "${GATEWAY_TOKEN}"
  - name: teammate
    token: "${TEAM_TOKEN}"
    budget_usd: 50
    budget_period: monthly
    allowed_models: ["glm*", "deepseek*"]
    tpm: 200000

providers:
  - name: anthropic
    type: anthropic
    base_url: "https://api.anthropic.com"
    keys: ["${ANTHROPIC_API_KEY}"]

  - name: openrouter
    type: openai
    base_url: "https://openrouter.ai/api/v1"
    keys: ["${OPENROUTER_KEY}"]
    discover_models: true
    weight: 3

routing:
  alias_claude_prefix: true
  default_chain: [anthropic, openrouter]
  rules:
    - prefix: "combo/fast"
      targets:
        - { provider: openrouter, model: "meta-llama/llama-4-scout" }
        - { provider: anthropic, model: "claude-haiku-4-5" }
    - prefix: "anthropic/"
      strip_prefix: true
      chain: [anthropic]
  scenarios:
    long_context:
      threshold_tokens: 80000
      chain: [anthropic]
    image:
      chain: [anthropic]

cache:
  enabled: true
  ttl: 30m

guardrails:
  request:
    pii_presets: [email]
    injection_detection: block

pricing_sync:
  enabled: true
  interval: 6h

state:
  redis_url: "redis://localhost:6379"

API endpoints

Endpoint Description
POST /v1/messages Anthropic Messages API (streaming + non-streaming)
POST /v1/messages/count_tokens Token estimation
GET /v1/models Model catalog (?format=openai for OpenAI shape)
GET /healthz Health check
GET /metrics Prometheus metrics
POST /mcp MCP server (HTTP transport)
GET /admin/dashboard Web dashboard
GET /admin/stats Usage statistics
GET /admin/logs?limit=N Recent request log
GET /admin/tokens Client budgets and spend
GET /admin/keys Provider key pool status
GET /admin/config Sanitized config snapshot
GET /admin/config/yaml Raw config.yaml
POST /admin/config/yaml Update config (validated + backed up)
POST /admin/config/rollback Rollback to previous config
POST /admin/reload Hot reload providers/routing/pricing
POST /admin/flush-cache Clear response cache
GET /admin/export.csv Export usage log as CSV
GET /admin/inflight Current in-flight request count

Graceful shutdown

The gateway waits for in-flight requests to complete before exiting. On SIGTERM / SIGINT:

  1. Stops accepting new connections
  2. Drains in-flight requests (up to server.shutdown_timeout, default 30s)
  3. Logs all in-flight requests completed or graceful drain deadline reached, N request(s) may have been cut

Configure the drain timeout:

server:
  shutdown_timeout: 60s   # give long-running streams more time

Monitor the current in-flight count at any time:

curl -H "x-api-key: $ADMIN" http://localhost:8090/admin/inflight
# {"in_flight": 3}

MCP server

The gateway exposes itself as an MCP server — Claude can manage it natively:

# HTTP transport
claude mcp add --transport http ccg http://localhost:8090/mcp --header "x-api-key: ccg-admin-token"

# stdio transport
claude mcp add ccg -- ./bin/gateway -config config.yaml -mcp

Tools: gateway_stats, gateway_logs, gateway_models, gateway_providers, gateway_tokens, gateway_reload, estimate_cost.

Architecture

cmd/gateway             entry point + claude launcher
internal/core           Anthropic/OpenAI types, protocol translation (req/resp/SSE)
internal/provider       key pool, request execution, routing registry, SigV4, event-stream
internal/server         HTTP handlers, dashboard, MCP, metrics, guardrails
internal/cache          LRU+TTL exact cache
internal/logstore       JSONL usage log + aggregates
internal/pricing        glob pricing table, cost calculation
internal/ratelimit      per-client RPM/TPM limiter
internal/state          Redis/Postgres/memory state backends
internal/config         YAML + env expansion

Development

make test          # go test ./...
make vet           # go vet ./...
make fmt           # gofmt -w .
make run           # local start
make docker-up     # build + run in docker

Credits

Ideas and inspiration from the best in class:

Project What we borrowed
claude-code-router Scenario routing, transformers, model aliases
LiteLLM Virtual keys, budgets, allowed_models, TPM
OmniRoute MCP server, fallback chains, model discovery, dashboard
one-api / new-api Channel weights, circuit breaker, CSV export, runtime key management
gpt-load Key pool health probes
uni-api Per-key rate limits in YAML
Helicone TTFT metric
Bifrost Semantic cache via embeddings
Portkey Gateway Guardrails on request and response
Cloudflare AI Gateway Per-request headers, cache control
CLIProxyAPI SSE keep-alive, session affinity, fill-first
Habr: 6 free AI routers list of free-tier providers, promoted to the "Free tier providers" section

Free tier providers recommended in the article: OrcaRouter, TeamoRouter, AgentRouter ($125 credits), Token Harbor, NaraRouter (7M tokens/day), FreeRouter. All use OpenAI-compatible endpoints and are configured as type: openai providers.

Support

If you find this project useful, consider supporting its development:

  • GitHub Sponsors — @Mukller
  • Star the repo — helps visibility
  • Report issues — bugs, feature requests, docs improvements
  • Contribute — PRs welcome (see CONTRIBUTING.md)

License

MIT

About

Anthropic-compatible gateway for Claude Code: multi-provider (Anthropic/Bedrock/Vertex/OpenAI-compat), key rotation, fallback chains, cost tracking, dashboard

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages