A transparent logging proxy for LLM API traffic. Install once, and every request to Claude, ChatGPT, or other LLM providers is automatically logged for debugging, auditing, and analysis.
brew install prime-radiant-inc/tap/llm-proxy
brew services start llm-proxyRestart your shell, and you're done.
curl -fsSL https://raw.githubusercontent.com/prime-radiant-inc/llm-proxy/main/scripts/install.sh | shRestart your shell, and you're done.
All LLM traffic is now logged to ~/.llm-provider-logs/.
LLM Proxy sits between your LLM clients (Claude Code, Codex, API scripts) and the provider APIs. It:
- Logs every request and response to
~/.llm-provider-logs/ - Auto-configures your shell so clients use the proxy automatically
- Runs as a background service that starts at login
- Works with any client that uses
ANTHROPIC_BASE_URLorOPENAI_BASE_URL
~/.llm-provider-logs/
├── api.anthropic.com/
│ └── 2026-01-14/
│ └── 20260114-091523-a1b2c3d4.jsonl
├── api.openai.com/
│ └── 2026-01-14/
│ └── 20260114-102234-i9j0k1l2.jsonl
└── chatgpt.com/
└── 2026-01-14/
└── 20260114-111448-m3n4o5p6.jsonl
Each session is a JSONL file with request/response pairs, timing information, and metadata.
Optionally export logs in real-time to Grafana Loki for centralized observability. Useful for aggregating logs across ephemeral containers or multiple machines.
Add a [loki] section to ~/.config/llm-proxy/config.toml:
[loki]
enabled = true
url = "http://loki.example.com:3100/loki/api/v1/push"
auth_token = "" # Optional: Bearer token for authenticated endpoints
batch_size = 1000 # Entries per batch (default: 1000)
batch_wait = "5s" # Max time before flushing batch (default: 5s)
retry_max = 5 # Retry attempts on failure (default: 5)
use_gzip = true # Compress payloads (default: true)
environment = "production" # Label for filtering in GrafanaOr use environment variables:
| Variable | Description |
|---|---|
LLM_PROXY_LOKI_ENABLED |
Set to true or 1 to enable |
LLM_PROXY_LOKI_URL |
Loki push endpoint URL |
LLM_PROXY_LOKI_AUTH_TOKEN |
Bearer token for auth |
LLM_PROXY_LOKI_BATCH_SIZE |
Entries per batch |
LLM_PROXY_LOKI_BATCH_WAIT |
Duration before flush (e.g., 5s, 10s) |
LLM_PROXY_LOKI_RETRY_MAX |
Max retry attempts |
LLM_PROXY_LOKI_USE_GZIP |
Set to true or 1 for compression |
LLM_PROXY_LOKI_ENVIRONMENT |
Environment label |
- Non-blocking: Loki export runs asynchronously and doesn't add latency to proxied requests
- Graceful degradation: If Loki is unavailable, local file logging continues unaffected
- Buffered writes: Logs are batched and retried on failure; buffer is flushed on shutdown
- Session correlation: Logs include session IDs for querying all entries from a single session
llm-proxy --status # Check if running, show port and log location
llm-proxy --setup # Full setup (Linux only: installs systemd service)
llm-proxy --setup-shell # Configure shell only (adds eval line to .bashrc/.zshrc)
llm-proxy --uninstall # Remove service and shell config- Service runs in background on a dynamic port
- Port is written to
~/.local/state/llm-proxy/port - Shell sources the eval line:
eval "$(llm-proxy --env)" - Environment variables like
ANTHROPIC_BASE_URLpoint to the proxy - Clients use the proxy transparently - no client config needed
The --env flag checks if the proxy is running and outputs the appropriate exports. If the proxy isn't running, it outputs nothing, so your shell continues to work normally.
- Anthropic (Claude, Claude Code)
- OpenAI (ChatGPT, Codex, API)
- Any OpenAI-compatible API
The proxy auto-detects ChatGPT OAuth tokens and routes them to the correct backend.
If you prefer not to use the background service:
# Run proxy on a specific port
llm-proxy --port 12071
# Configure clients manually
export ANTHROPIC_BASE_URL=http://localhost:12071/anthropic/api.anthropic.com
export OPENAI_BASE_URL=http://localhost:12071/openai/api.openai.comllm-proxy can act as a signing proxy for AWS Bedrock, allowing Claude Code to use Bedrock without managing AWS credentials directly. The proxy receives unsigned Bedrock-format requests, SigV4-signs them, forwards to Bedrock, and decodes the binary eventstream responses for logging while streaming raw bytes back to the client.
Set BEDROCK_REGION when starting the proxy:
BEDROCK_REGION=us-west-2 llm-proxy --port 9999The proxy uses the standard AWS SDK credential chain (~/.aws/credentials, env vars, instance role, etc.). Your credentials need bedrock:InvokeModel and bedrock:InvokeModelWithResponseStream permissions.
Point Claude Code at the proxy instead of real Bedrock:
export CLAUDE_CODE_USE_BEDROCK=1
export ANTHROPIC_BEDROCK_BASE_URL=http://localhost:9999
export CLAUDE_CODE_SKIP_BEDROCK_AUTH=1
claudeCLAUDE_CODE_SKIP_BEDROCK_AUTH=1 tells Claude Code to skip its own SigV4 signing since the proxy handles it.
curl http://localhost:9999/health/bedrock
# {"status":"ok","region":"us-west-2","decode_errors":0}- Claude Code sends Bedrock-format requests (binary eventstream) to the proxy
- The proxy extracts the model ID from the URL path, validates it, and SigV4-signs the request
- The response is streamed back to Claude Code as raw bytes (no transformation)
- A TeeReader captures the stream for decoding — eventstream frames are parsed, base64-decoded, and fed through the normal logging pipeline (file, Loki, session tracking)
All existing features (session tracking, fingerprinting, Loki export, log explorer) work with Bedrock traffic. Bedrock entries get a transport=bedrock label in Loki to distinguish them from direct API traffic.
Browse and search your LLM logs with a web UI:
llm-proxy --explore # Opens browser to http://localhost:12071
llm-proxy --explore --explore-port 9000 # Use specific portFeatures:
- Session list grouped by date with message counts
- Filter by provider (Anthropic, OpenAI, etc.)
- Conversation view with thinking blocks and tool calls
- Full-text search across all logs
- Raw JSON view for debugging
# macOS
brew services stop llm-proxy
brew uninstall llm-proxy
llm-proxy --uninstall
# Linux
llm-proxy --uninstall
rm /usr/local/bin/llm-proxy # or ~/.local/bin/llm-proxyLogs are preserved in ~/.llm-provider-logs/. Delete manually if desired.
go build -o llm-proxy .# Unit tests
go test -v -short
# Live E2E tests (requires API key in ~/.amplifier/keys.env)
go test -v -run TestLiveMIT