Skip to content

Proxy Gateway

Swixter includes a local proxy gateway that can intercept and route API requests from AI coders. It supports automatic API format conversion, enabling Claude Code (Anthropic Messages API) to call OpenAI-compatible providers transparently.

Start the proxy server.

Terminal window
swixter proxy start

The proxy listens on a local port (default: auto-assigned) and forwards requests to the configured provider’s API. This lets you:

  • Inspect traffic: View request/response logs
  • Switch backends: Change the provider without restarting the coder
  • Add headers: Inject custom authentication or routing headers
  • Format conversion: Automatically convert between Anthropic Messages and OpenAI Chat Completions APIs

Options:

FlagDescription
--group <name>Use a specific failover group
--profile <name>Use a single profile (gateway mode, no failover)
--port <number>Custom listen port (default: auto-assigned)
--daemonRun as background service
--log-level <level>debug, info, warn, error

Stop the running proxy server.

Terminal window
swixter proxy stop

Check if the proxy is running.

Terminal window
swixter proxy status

Shows which coders are connected, the proxy port, and the active backend.

View proxy traffic logs.

Terminal window
swixter proxy logs

Shows recent requests with timing, status codes, and response sizes.

┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ AI Coder │ ──▶ │ Swixter Proxy│ ──▶ │ Provider API │
│ (client) │ │ (localhost) │ │ (remote) │
└──────────┘ └──────┬───────┘ └──────────────┘
┌────▼────┐
│ Logger │
└─────────┘

The proxy intercepts API calls from your AI coding assistant and forwards them to the actual provider. This enables transparent switching between providers without changing coder configuration.

Full proxy configuration in ~/.config/swixter/config.json:

{
"proxy": {
"port": 18721,
"host": "127.0.0.1",
"autoStart": false,
"logLevel": "debug",
"timeout": 30000,
"maxBodyLogSize": 4096,
"headers": {
"X-Custom-Header": "value"
}
}
}
OptionDescriptionDefault
portListen port (0 = auto-assign)0
hostListen address"127.0.0.1"
autoStartStart proxy on profile applyfalse
logLeveldebug, info, warn, error"info"
timeoutRequest timeout in ms30000
maxBodyLogSizeMax bytes to log per request/response body4096
headersAdditional headers to inject on all requests{}

The proxy automatically converts between API formats based on the request endpoint and the target provider’s supported format.

When Claude Code sends a request to /v1/messages (Anthropic Messages API) but the target provider expects OpenAI Chat Completions format, the proxy transparently converts:

Claude Code (Anthropic) ──▶ Proxy ──▶ Groq (OpenAI)
/v1/messages converts /v1/chat/completions
Anthropic format request OpenAI format
+ response

Supported conversions:

Client FormatTarget FormatDirection
Anthropic MessagesOpenAI Chat CompletionsRequest + Response + SSE Streaming

More conversions (OpenAI Responses, Gemini) will be added in future releases.

The proxy infers the target format automatically:

  1. Profile-level override — If apiFormat is set on the profile, it takes priority
  2. Provider wire_apichat → OpenAI Chat, responses → Anthropic Messages

To set a custom API format on a profile:

Terminal window
swixter claude create groq-local --provider groq --api-key $GROQ_KEY --api-format openai_chat

Or edit an existing profile:

Terminal window
swixter claude edit groq-local
# Select "API Format" and choose from the list

Use --profile to start the proxy with a single profile, bypassing group failover logic. This is useful when you want to route all traffic through one provider with format conversion.

3456/v1/messages
# Start proxy with a specific profile
swixter proxy start --profile groq-local --port 3456
# Proxy converts to OpenAI Chat Completions and forwards to Groq

This mode does not use groups or circuit breakers — it forwards directly to the specified profile.

Route different models to different backends:

{
"proxy": {
"routes": [
{
"match": { "model": "claude-*" },
"upstream": "https://api.anthropic.com"
},
{
"match": { "model": "gpt-*" },
"upstream": "https://api.openai.com/v1"
}
]
}
}

Each route has:

  • match: Criteria to match (model, provider)
  • upstream: URL to forward matching requests to

Add custom headers to proxied requests:

{
"proxy": {
"headers": {
"X-Environment": "development",
"X-Request-Source": "swixter-proxy"
}
}
}

Useful for:

  • API gateway routing keys
  • Usage tracking per environment
  • Custom authentication middleware
Terminal window
# Detailed debug output
swixter proxy start --log-level debug
# Production mode (errors only)
swixter proxy start --log-level error

Each request is logged with:

{
"timestamp": "2026-04-29T10:30:00.000Z",
"method": "POST",
"path": "/v1/messages",
"status": 200,
"duration_ms": 1234,
"request_size": 2048,
"response_size": 512
}
Terminal window
# Tail logs
swixter proxy logs --follow
# Filter by status code
swixter proxy logs --status 4xx
# Last 50 requests
swixter proxy logs --last 50

The proxy adds minimal overhead (~1-5ms latency):

  • Request/response body streaming (no buffering for large payloads)
  • Connection pooling for upstream requests
  • No TLS termination overhead (plain HTTP on localhost)
  • Proxy binds to 127.0.0.1 by default (localhost only)
  • No external network access
  • Headers are sanitized (Hop-by-hop headers removed)
  • Body logging truncation prevents sensitive data leaks in logs