CCRelay

CCRelay is a VSCode extension with a built-in API proxy server that allows you to seamlessly switch between different AI providers without losing conversation context. Fully compatible with Claude Code and other Anthropic API clients.
Website: https://ccrelay.inflab.org
中文文档 (Chinese Documentation)
Table of Contents
Core Features
- Built-in API Proxy Server: Runs a local HTTP server (default:
http://127.0.0.1:7575) that proxies requests to different AI providers
- Multi-Instance Coordination: Leader/Follower mode for multiple VSCode windows - only one instance runs the server
- WebSocket Sync: Real-time provider synchronization between Leader and Followers via WebSocket
- Status Bar Indicator: Shows current provider, role (Leader/Follower), and server status
- Quick Provider Switching: Click the status bar or use commands to switch providers
- Provider Modes:
passthrough - Preserves original authentication headers for official API
inject - Injects provider-specific API Key
- Model Mapping: Automatically translates Claude model names to provider-specific models with wildcard support (e.g.,
claude-* → glm-4.7)
- Vision Model Mapping: Separate model mapping for visual/multimodal requests (
vlModelMap)
- OpenAI Format Conversion: Automatically converts Anthropic API format to OpenAI format, supporting Gemini, OpenRouter, and other OpenAI-compatible APIs
- Request Logging: Optional SQLite/PostgreSQL request/response logging with Web UI viewer
- Concurrency Control: Built-in request queue and concurrency limits to prevent API overload
- Auto-start: Automatically starts the proxy server when VSCode launches
Requirements
- VSCode version 1.80.0 or higher
- Node.js (for development)
Installation
Install from VSIX
- Download the latest
.vsix file
- In VSCode, press
Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux)
- Type
Extensions: Install from VSIX...
- Select the downloaded
.vsix file
Build from Source
# Clone the repository
git clone https://github.com/inflaborg/ccrelay.git
cd ccrelay
# Install dependencies
npm install
# Build the extension
npm run build
# Package VSIX
npm run package
Development Mode
# Install dependencies
npm install
# Compile
npm run compile
# Press F5 in VSCode to open Extension Development Host window
Quick Start
export ANTHROPIC_BASE_URL=http://127.0.0.1:7575
claude
CCRelay uses a YAML configuration file (~/.ccrelay/config.yaml by default). The file is auto-created with defaults on first launch.
Edit the config file to add your providers:
providers:
glm:
name: "Z.AI-GLM-5"
baseUrl: "https://api.z.ai/api/anthropic"
mode: "inject"
apiKey: "${GLM_API_KEY}" # Supports environment variables
modelMap:
- pattern: "claude-opus-*"
model: "glm-5"
- pattern: "claude-sonnet-*"
model: "glm-5"
- pattern: "claude-haiku-*"
model: "glm-4.7"
enabled: true
defaultProvider: "glm"
3. Switch providers
- Click the CCRelay icon in the VSCode status bar at the bottom
- Or use Command Palette:
CCRelay: Switch Provider
Usage Guide
Basic Setup
- Install and enable the extension
- The config file (
~/.ccrelay/config.yaml) is auto-created with defaults
- Edit the config file to add your providers
- The server will auto-start (configurable via
server.autoStart in config)
- Click the status bar to switch providers or access the menu
Multi-Instance Mode
When multiple VSCode windows are open:
- One instance becomes the Leader and runs the HTTP server
- Other instances become Followers and connect to the Leader via WebSocket
- Leader broadcasts provider changes to all Followers in real-time
- Followers can request provider switches through the Leader
- If the Leader closes, a Follower automatically becomes the new Leader
- Status bar shows your role:
$(broadcast) for Leader, $(radio-tower) for Follower
Provider Modes
Passthrough Mode (Official Claude API)
- Preserves original authentication headers
- Used for official Claude API with OAuth sessions
- No API key required
Inject Mode (Third-party Providers)
- Replaces authentication with provider-specific API Key
- Requires API key configuration
- Supports GLM, OpenRouter, and other Claude-compatible APIs
Model Mapping
Supports wildcard pattern matching for model names using array format:
modelMap:
- pattern: "claude-opus-*"
model: "glm-5"
- pattern: "claude-sonnet-*"
model: "glm-4.7"
- pattern: "claude-haiku-*"
model: "glm-4.5"
Vision Model Mapping: For requests containing images, you can configure vlModelMap separately:
modelMap:
- pattern: "claude-*"
model: "text-model"
vlModelMap:
- pattern: "claude-*"
model: "vision-model"
📋 Feature Note: OpenAI format conversion enables CCRelay to work with OpenAI-compatible providers (Gemini, OpenRouter, etc.). This feature handles bidirectional conversion between Anthropic and OpenAI API formats. If you encounter any compatibility issues, please report them on GitHub.
CCRelay supports OpenAI-compatible providers (like Gemini):
gemini:
name: "Gemini"
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai"
providerType: "openai"
mode: "inject"
apiKey: "${GEMINI_API_KEY}"
modelMap:
- pattern: "claude-*"
model: "gemini-2.5-pro"
Conversion process:
- Request: Anthropic Messages API format → OpenAI Chat Completions format
- Response: OpenAI format → Anthropic format
Web UI Dashboard
CCRelay has a built-in Web UI dashboard that provides:
- Dashboard: Server status, current provider, request statistics
- Providers: View and switch providers
- Logs: Request/response log viewer (requires enabling log storage)


Access methods:
- Command Palette:
CCRelay: Open Dashboard
- Browser:
http://127.0.0.1:7575/ccrelay/
Configuration
CCRelay uses a YAML configuration file (~/.ccrelay/config.yaml by default). The file is auto-created with defaults on first launch.
VSCode Settings
| Setting |
Default |
Description |
ccrelay.configPath |
~/.ccrelay/config.yaml |
Path to the YAML configuration file |
YAML Configuration File
Server Configuration
| Setting |
Default |
Description |
server.port |
7575 |
Proxy server port |
server.host |
127.0.0.1 |
Bind address |
server.autoStart |
true |
Auto-start server when extension loads |
Provider Configuration
| Setting |
Default |
Description |
defaultProvider |
official |
Default provider ID |
providers |
{...} |
Provider configurations |
Each provider supports:
name - Display name
baseUrl - API base URL
mode - passthrough or inject
providerType - anthropic (default) or openai
apiKey - API key (inject mode, supports ${ENV_VAR} environment variables)
authHeader - Authorization header name (default: authorization)
modelMap - Model name mappings (array of {pattern, model}, supports wildcards)
vlModelMap - Vision model mappings (for multimodal requests)
headers - Custom request headers
enabled - Whether enabled (default: true)
Routing Configuration
| Setting |
Default |
Description |
routing.proxy |
["/v1/messages", "/messages"] |
Paths routed to current provider |
routing.passthrough |
["/v1/users/*", "/v1/organizations/*"] |
Paths always going to official API |
routing.block |
[{path: "/api/event_logging/*", ...}] |
Paths returning custom response in inject mode |
routing.openaiBlock |
[{path: "/v1/messages/count_tokens", ...}] |
Block patterns for OpenAI providers |
Concurrency Control
| Setting |
Default |
Description |
concurrency.enabled |
true |
Enable concurrency queue |
concurrency.maxWorkers |
3 |
Maximum concurrent workers |
concurrency.maxQueueSize |
100 |
Maximum queue size (0 = unlimited) |
concurrency.requestTimeout |
60 |
Request timeout in queue (seconds, 0 = unlimited) |
concurrency.routes |
[] |
Per-route queue configuration |
Logging Storage
| Setting |
Default |
Description |
logging.enabled |
false |
Enable request log storage |
logging.database.type |
sqlite |
Database type (sqlite or postgres) |
SQLite Configuration:
| Setting | Default | Description |
|---------|---------|-------------|
| logging.database.path | "" | Database file path (empty = ~/.ccrelay/logs.db) |
PostgreSQL Configuration:
| Setting | Default | Description |
|---------|---------|-------------|
| logging.database.host | localhost | Server host |
| logging.database.port | 5432 | Server port |
| logging.database.name | ccrelay | Database name |
| logging.database.user | "" | Username |
| logging.database.password | "" | Password (supports ${ENV_VAR}) |
| logging.database.ssl | false | Enable SSL connection |
Complete Configuration Example
# CCRelay Configuration
# Docs: https://github.com/inflaborg/ccrelay#configuration
# ==================== Server Configuration ====================
server:
port: 7575 # Proxy server port
host: "127.0.0.1" # Bind address
autoStart: true # Auto-start server when extension loads
# ==================== Provider Configuration ====================
providers:
official:
name: "Claude Official"
baseUrl: "https://api.anthropic.com"
mode: "passthrough" # passthrough | inject
providerType: "anthropic" # anthropic | openai
enabled: true
glm:
name: "Z.AI-GLM-5"
baseUrl: "https://api.z.ai/api/anthropic"
mode: "inject"
apiKey: "${GLM_API_KEY}" # Supports environment variables
authHeader: "authorization"
modelMap:
- pattern: "claude-opus-*"
model: "glm-5"
- pattern: "claude-sonnet-*"
model: "glm-5"
- pattern: "claude-haiku-*"
model: "glm-4.7"
enabled: true
gemini:
name: "Gemini"
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai"
providerType: "openai"
mode: "inject"
apiKey: "${GEMINI_API_KEY}"
modelMap:
- pattern: "claude-*"
model: "gemini-2.5-pro"
enabled: true
# Default provider ID
defaultProvider: "official"
# ==================== Routing Configuration ====================
routing:
# Proxy routes: Forward to current provider
proxy:
- "/v1/messages"
- "/messages"
# Passthrough routes: Always go to official API
passthrough:
- "/v1/users/*"
- "/v1/organizations/*"
# Block routes (inject mode): Return custom response
block:
- path: "/api/event_logging/*"
response: ""
code: 200
# OpenAI format block routes
openaiBlock:
- path: "/v1/messages/count_tokens"
response: '{"input_tokens": 0}'
code: 200
# ==================== Concurrency Control ====================
concurrency:
enabled: true # Enable concurrency queue
maxWorkers: 3 # Maximum concurrent workers
maxQueueSize: 100 # Maximum queue size (0=unlimited)
requestTimeout: 60 # Request timeout in queue (seconds)
# Per-route queue configuration
routes:
- pattern: "/v1/messages/count_tokens"
name: "count_tokens"
maxWorkers: 30
maxQueueSize: 1000
# ==================== Logging Storage ====================
logging:
enabled: true # Enable request log storage
database:
type: "sqlite" # sqlite | postgres
path: "" # Empty = ~/.ccrelay/logs.db
# PostgreSQL configuration
# type: "postgres"
# host: "localhost"
# port: 5432
# name: "ccrelay"
# user: ""
# password: "${POSTGRES_PASSWORD}"
# ssl: false
Note: YAML config supports both camelCase and snake_case keys.
API Endpoints
The proxy server exposes management endpoints at /ccrelay/:
| Endpoint |
Method |
Description |
/ccrelay/api/status |
GET |
Get current proxy status |
/ccrelay/api/providers |
GET |
List all available providers |
/ccrelay/api/switch/{id} |
GET |
Switch to a provider by ID |
/ccrelay/api/switch |
POST |
Switch provider (JSON body) |
/ccrelay/api/queue |
GET |
Get queue statistics |
/ccrelay/api/logs |
GET |
Get request logs (when logging enabled) |
/ccrelay/ws |
WebSocket |
Real-time sync for Followers |
/ccrelay/ |
GET |
Web UI dashboard |
All other requests are proxied to the current provider.
Commands
| Command |
ID |
Description |
| CCRelay: Show Menu |
ccrelay.showMenu |
Show main menu |
| CCRelay: Switch Provider |
ccrelay.switchProvider |
Open provider picker |
| CCRelay: Start Server |
ccrelay.startServer |
Manually start the server |
| CCRelay: Stop Server |
ccrelay.stopServer |
Stop the server |
| CCRelay: Open Settings |
ccrelay.openSettings |
Open extension settings |
| CCRelay: Show Logs |
ccrelay.showLogs |
View output logs |
| CCRelay: Clear Logs |
ccrelay.clearLogs |
Clear output logs |
| CCRelay: Open Dashboard |
ccrelay.openWebUI |
Open dashboard panel |
Development
# Compile TypeScript
npm run compile
# Watch for changes and recompile
npm run watch
# Run ESLint
npm run lint
# Auto-fix lint issues
npm run lint:fix
# Format code
npm run format
# Run unit tests
npm run test
# Run integration tests
npm run test:integration
# Run all tests
npm run test:all
# Run tests with coverage
npm run test:coverage
# Build VSIX package
npm run package
# Development build
npm run build:dev
# Production build
npm run build:prod
Project Structure
ccrelay/
├── src/
│ ├── extension.ts # Extension entry point
│ ├── api/ # API endpoint handlers
│ ├── config/ # Configuration management
│ ├── converter/ # Anthropic ↔ OpenAI format conversion
│ ├── database/ # Database drivers (SQLite/PostgreSQL)
│ ├── queue/ # Concurrency control and request queue
│ ├── server/ # HTTP server and routing
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions
│ └── vscode/ # VSCode integration (status bar, log viewer)
├── web/ # Web UI (React + Vite)
├── tests/ # Test files
└── assets/ # Extension assets
File Locations
| File |
Location |
Description |
| YAML Config |
~/.ccrelay/config.yaml |
Main configuration file (auto-created) |
| Log database |
~/.ccrelay/logs.db |
Request/response logs (when enabled) |
Contributing
Issues and Pull Requests are welcome!
Acknowledgments
This project is 100% AI-generated code. Special thanks to:
- Claude Code - The AI coding assistant that wrote all the code
- GLM - GLM models (glm-4.7, later glm-5) served as the backend provider
License
MIT License
Copyright (c) 2026 inflab.org