LunaRoute is a high-performance local proxy for AI coding assistants like Claude Code, OpenAI Codex CLI, and OpenCode. Get complete visibility into every LLM interaction with zero-overhead passthrough, comprehensive session recording, and powerful debugging capabilities.
# Start in 5 seconds (no API key needed!)
lunaroute-server
# Point Claude Code to itexport ANTHROPIC_BASE_URL=http://localhost:8081
# Or use with OpenAI Codex CLIexport OPENAI_BASE_URL=http://localhost:8081/v1
# Done! Start coding with full visibility
🎯 Why LunaRoute for Local Development?
See Everything Your AI Does
Stop flying blind. LunaRoute records every conversation, token, and tool call:
🔍 Debug AI conversations - See exactly what your AI assistant sends and receives
💰 Track token usage - Know where your money goes (input/output/thinking tokens)
🔧 Analyze tool performance - Which tools are slow? Which get used most?
📊 Measure proxy overhead - Is it the LLM or your code that's slow?
🔎 Search past sessions - "How did the AI solve that bug last week?"
# Linux/macOS: Extract and make executable
tar -xzf lunaroute-server-*.tar.gz
chmod +x lunaroute-server
./lunaroute-server
# Or add to PATH for global access
sudo mv lunaroute-server /usr/local/bin/
Option 2: Build from Source
# Clone the repo
git clone https://github.com/erans/lunaroute.git
cd lunaroute
# Build (one time only)
cargo build --release --package lunaroute-server
# Binary location: target/release/lunaroute-server# Add to PATH or run directly
Example 1: Passthrough for Claude Code
Zero-overhead passthrough with 100% API fidelity:
# Save as claude-passthrough.yamlhost: "127.0.0.1"port: 8081api_dialect: "anthropic"# Accept Anthropic formatproviders:
anthropic:
enabled: true# No api_key needed - Claude Code sends it via x-api-key headersession_recording:
enabled: false # Disable for maximum performancelogging:
level: "info"log_requests: true
Usage:
# Start server
lunaroute-server --config claude-passthrough.yaml
# Point Claude Code to proxyexport ANTHROPIC_BASE_URL=http://localhost:8081
# Use Claude Code normally - zero config needed!
Performance: ~0.1-0.2ms overhead, 100% API fidelity
Example 2: Passthrough for OpenAI Codex CLI
Works with your ChatGPT account via Codex authentication:
# Save as codex-passthrough.yamlhost: "127.0.0.1"port: 8081api_dialect: "openai"# Accept OpenAI formatproviders:
openai:
enabled: true# Special base URL for ChatGPT authenticationbase_url: "https://chatgpt.com/backend-api/codex"codex_auth:
enabled: false # Disabled for pure passthroughsession_recording:
enabled: falselogging:
level: "info"log_requests: true
Usage:
# Start server (reads auth from ~/.codex/auth.json)
lunaroute-server --config codex-passthrough.yaml
# Point Codex to proxyexport OPENAI_BASE_URL=http://localhost:8081/v1
# Use Codex normally with your ChatGPT account
codex exec"help me debug this function"
Note: Use base_url: "https://api.openai.com/v1" if you have an OpenAI API key instead.
Example 3: Dual-Dialect Passthrough (Both Claude Code & Codex)
Run a single proxy that accepts both OpenAI and Anthropic formats simultaneously:
# Save as dual-passthrough.yamlhost: "127.0.0.1"port: 8081api_dialect: "both"# Accept BOTH OpenAI and Anthropic formatsproviders:
openai:
enabled: true# For Codex with ChatGPT accountbase_url: "https://chatgpt.com/backend-api/codex"codex_auth:
enabled: true # Reads auth from ~/.codex/auth.json automatically# For OpenAI API instead, use: base_url: "https://api.openai.com/v1"anthropic:
enabled: true# No api_key needed - Claude Code sends it via x-api-key headersession_recording:
enabled: true# SQLite analytics - lightweight session statssqlite:
enabled: truepath: "~/.lunaroute/sessions.db"max_connections: 10# JSONL logs - full request/response recordingjsonl:
enabled: truedirectory: "~/.lunaroute/sessions"retention:
max_age_days: 30max_size_mb: 1024# Web UI for browsing sessionsui:
enabled: truehost: "127.0.0.1"port: 8082refresh_interval: 5logging:
level: "info"log_requests: true
Usage:
# Start server - ONE proxy for BOTH tools!
lunaroute-server --config dual-passthrough.yaml
# Point Claude Code to proxyexport ANTHROPIC_BASE_URL=http://localhost:8081
# Point Codex to proxy (in another terminal or project)export OPENAI_BASE_URL=http://localhost:8081
# Use both tools simultaneously - same proxy!# Claude Code → /v1/messages → Anthropic# Codex CLI → /v1/chat/completions → OpenAI# All sessions recorded to ~/.lunaroute/sessions/# Analytics stored in ~/.lunaroute/sessions.db# Browse sessions at http://localhost:8082
What happens:
LunaRoute accepts requests at both /v1/messages (Anthropic) and /v1/chat/completions (OpenAI)
Anthropic requests → passthrough to Anthropic provider
OpenAI requests → passthrough to OpenAI provider (with Codex auth)
Both formats work simultaneously with zero normalization overhead
Each tool gets native responses in its expected format
All sessions recorded with full request/response logs + SQLite analytics
Performance: ~0.5-1ms overhead (async recording), 100% API fidelity for both formats
Use Cases:
Use Claude Code and Codex in the same development environment
Single proxy for team using mixed AI tools
Consolidated logging and metrics for all AI interactions
Unified session recording across both OpenAI and Anthropic APIs
Visual session analysis through web UI
Simplified infrastructure (one proxy instead of two)
Example 4: Map Claude Code to Gemini (OpenAI dialect)
Translate Anthropic format to Gemini's OpenAI-compatible endpoint:
# Save as claude-to-gemini.yamlhost: "127.0.0.1"port: 8081api_dialect: "anthropic"# Accept Anthropic format from Claude Codeproviders:
openai:
enabled: true# Gemini's OpenAI-compatible endpointbase_url: "https://generativelanguage.googleapis.com/v1beta/openai"api_key: "${GOOGLE_API_KEY}"# Set via environment variableanthropic:
enabled: false # Don't route to Anthropicsession_recording:
enabled: true # Optional: track translationslogging:
level: "debug"log_requests: true
Usage:
# Set your Google API keyexport GOOGLE_API_KEY="your-gemini-api-key"# Start server
lunaroute-server --config claude-to-gemini.yaml
# Point Claude Code to proxyexport ANTHROPIC_BASE_URL=http://localhost:8081
# Claude Code sends Anthropic format, LunaRoute translates to Gemini!
What happens:
Claude Code sends request in Anthropic format
LunaRoute translates to OpenAI format
Request routes to Gemini's OpenAI endpoint
Response translates back to Anthropic format
Claude Code receives native Anthropic response
More examples: See examples/configs/ for PII redaction, routing strategies, and advanced features.
Controlling Session Recording
LunaRoute provides two independent recording modes that can be enabled/disabled separately:
SQLite Analytics (Session Stats)
Lightweight session statistics and metadata - perfect for tracking usage without storing full content:
What gets recorded: Session IDs, timestamps, token counts, model names, tool usage stats, durations
Storage: ~1-2KB per session
Use case: Track costs and performance without storing sensitive request/response data
JSONL Request/Response Logs
Complete request/response recording for debugging and analysis:
What gets recorded: Full request/response bodies, headers, streaming events, tool calls
Storage: ~10KB per request (varies with content size)
Use case: Debug conversations, replay sessions, analyze AI behavior
Both Enabled (Recommended)
Get the best of both worlds:
session_recording:
enabled: true# Quick queryable statssqlite:
enabled: truepath: "~/.lunaroute/sessions.db"# Full conversation logsjsonl:
enabled: truedirectory: "~/.lunaroute/sessions"retention:
max_age_days: 7# Keep full logs for 1 weekmax_size_mb: 512# Limit to 512MB
Use case: Analytics stay forever, but full logs are cleaned up after 7 days
Result: Bash commands are the bottleneck, not the LLM.
3. Search Past Conversations
Problem: "How did my AI assistant help me fix that TypeError last week?"
Solution:
# Search all sessions for "TypeError"
curl "http://localhost:8081/sessions?text_search=TypeError&days=7"# Get the full conversation
curl "http://localhost:8081/sessions/{session_id}"| jq
Result: Find the exact solution approach and reuse it.
Problem: Team shares one proxy but everyone has different API keys.
Solution: Run LunaRoute without configuring API keys:
providers:
anthropic:
enabled: true# No api_key field = use client headersopenai:
enabled: true# Codex users get automatic auth from ~/.codex/auth.json
Result:
Claude Code users send their own API keys via headers
Codex CLI users get automatic authentication from their profile
No shared secrets, everyone uses their own credentials
Problem: Need to log sessions but can't store PII.
Result: All PII auto-redacted before hitting disk. Compliance achieved.
🎯 Zero-Overhead Passthrough Mode
When your API dialect matches the provider (Anthropic→Anthropic), LunaRoute becomes a transparent proxy:
Sub-millisecond overhead (~0.1-0.2ms)
100% API fidelity (preserves all fields)
Optional session recording
No normalization layer
📊 Comprehensive Session Recording
Dual-format storage for maximum flexibility:
JSONL Format (Human-Readable):
{"session_id":"abc123","model":"claude-sonnet-4","started_at":"2025-01-06T10:30:00Z"}
{"session_id":"abc123","request":"Help me debug this...","input_tokens":150}
{"session_id":"abc123","response":"I'll help you...","output_tokens":420}
SQLite Format (Queryable):
SELECT*FROM sessions
WHERE model_used ='claude-sonnet-4'AND input_tokens >1000ORDER BY started_at DESC;
Features:
Session grouping (multi-turn conversations in one file)
# Full-text search
curl "http://localhost:8081/sessions?text_search=TypeError"# Filter by tokens
curl "http://localhost:8081/sessions?min_total_tokens=10000"# By model and date
curl "http://localhost:8081/sessions?model=claude-sonnet-4&days=7"# Failed requests
curl "http://localhost:8081/sessions?success=false"
🔒 PII Detection & Redaction
Protect sensitive data automatically:
Supported PII Types:
Email addresses, phone numbers, SSN
Credit card numbers (Luhn validation)
IP addresses (IPv4/IPv6)
Custom patterns (API keys, AWS secrets, etc.)
Redaction Modes:
Mask: [EMAIL], [PHONE], etc.
Remove: Delete completely
Tokenize: HMAC-based deterministic tokens (reversible with key)
Partial: Show last N characters
Before: My email is [email protected] and SSN is 123-45-6789
After: My email is [EMAIL:a3f8e9d2] and SSN is [SSN:7b2c4f1a]
Licensed under the Apache License, Version 2.0 (LICENSE).
Like the moon 🌕 guides travelers at night, LunaRoute illuminates your AI interactions. Every request, every token, every decision - visible and trackable.
Built with ❤️ for developers who want visibility, control, and performance.
LunaRoute provides first-class support for OpenAI's Codex CLI:
✅ Automatic authentication from ~/.codex/auth.json
✅ Account ID header injection for proper request routing
✅ Zero configuration - just point Codex at the proxy
✅ Full compatibility with all Codex commands
Works seamlessly with codex exec, codex chat, codex eval, and more!
LunaRoute includes a built-in web interface for browsing and analyzing sessions:
# The UI server starts automatically on port 8082
lunaroute-server
# Then open: http://localhost:8082
Features:
📊 Dashboard - View all sessions with filtering and search
🔍 Session Details - Inspect individual sessions with timeline view
📄 Raw Request/Response - View the complete JSON data
📈 Analytics - Token usage, tool statistics, and performance metrics
⌨️ Keyboard Shortcuts - Press ESC to close dialogs