Documentation | npm | GitHub
Transparent OS-level interception for Claude Code. Redirect any Claude model to CLIProxyAPI without modifying Claude Code itself.
sudo cmm claude-haiku-4-5 gemini-2.5-flash
That's it. Open Claude Code normally — haiku requests go to CLIProxyAPI, everything else passes through untouched.
Claude Code (unmodified)
│
│ HTTPS → api.anthropic.com:443
│
▼
┌──────────────────────────────────┐
│ cmm — Local HTTPS Server (:443) │
│ │
│ model matches source? │
│ YES → CLIProxyAPI (:8317) │
│ NO → Real api.anthropic.com │
└──────────────────────────────────┘
/etc/hostsredirectsapi.anthropic.comto127.0.0.1- cmm runs a local HTTPS server on port 443 with a trusted self-signed certificate
- Incoming requests are routed by model name:
- Matched model → forwarded to CLIProxyAPI on localhost:8317
- Other models → forwarded to real Anthropic API using cached IP
Claude Code sees normal Anthropic API responses. No env vars, no config changes, no patches.
- macOS (uses Keychain for certificate trust)
- Node.js 18+
- Claude Code installed and logged in
- CLIProxyAPI running on localhost:8317
npm install -g claude-model-mappingOr from source:
git clone https://github.com/erdinccurebal/claude-model-mapping.git
cd claude-model-mapping
npm install && npm run build && npm linkcmm setupThis will:
- Generate a Root CA + server certificate for
api.anthropic.com - Add the CA to macOS Keychain (requires password/Touch ID)
- Set
NODE_EXTRA_CA_CERTSin~/.zshrc
Open a new terminal after setup.
sudo cmm <source-model> <target-model>
# Or with defaults configured:
cmm config set DEFAULT_SOURCE_MODEL claude-haiku-4-5
cmm config set DEFAULT_TARGET_MODEL gemini-2.5-flash
sudo cmmExamples:
# Redirect haiku to Gemini 2.5 Flash
sudo cmm claude-haiku-4-5 gemini-2.5-flash
# Redirect haiku to Gemini 2.5 Pro
sudo cmm claude-haiku-4-5 gemini-2.5-pro
# Redirect sonnet to Gemini
sudo cmm claude-sonnet-4 gemini-2.5-proModel names use prefix matching — claude-haiku-4-5 matches claude-haiku-4-5-20251001 and any future versions.
Then open Claude Code normally in another terminal:
claudesudo cmm stop
# or press Ctrl+C in the cmm terminalRun cmm as a background service that auto-starts on boot and auto-restarts on crash. No terminal window required.
# Install as background service
sudo cmm service install claude-haiku-4-5 gemini-2.5-flash
# Check status
sudo cmm service status
# Stop / start / restart
sudo cmm service stop
sudo cmm service start
sudo cmm service restart
# Remove service
sudo cmm service uninstallService logs are written to ~/.cmm/cmm-service.log.
cmm statussudo cmm testManage CLIProxyAPI connection settings stored in ~/.cmm/.env without editing the file manually.
# List all settings
cmm config list
# Get a single value
cmm config get PROXY_API_KEY
# Set a value
cmm config set PROXY_API_KEY sk-abc123
# Delete a value (reverts to default)
cmm config delete PROXY_URLAvailable keys:
| Key | Default | Description |
|---|---|---|
PROXY_API_KEY |
(empty) | API key for CLIProxyAPI |
PROXY_URL |
http://localhost:8317/v1/messages |
CLIProxyAPI endpoint URL (supports http/https) |
DEFAULT_SOURCE_MODEL |
(empty) | Default source model (allows running sudo cmm with no args) |
DEFAULT_TARGET_MODEL |
(empty) | Default target model |
sudo cmm uninstallRemoves certificates, Keychain entry, NODE_EXTRA_CA_CERTS from .zshrc, and the ~/.cmm directory.
| Request model | Behavior | Destination |
|---|---|---|
Matches <source-model>* |
INTERCEPTED | CLIProxyAPI (target model) |
| Everything else | PASSTHROUGH | Real api.anthropic.com |
Non-messages endpoints (/v1/models, /api/oauth/*, etc.) always pass through.
Intercepted responses include an x-cmm-provider: cliproxyapi header. You can check it in logs or with curl:
curl -s -D- https://api.anthropic.com/v1/messages \
--cacert ~/.cmm/ca.crt \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model":"claude-haiku-4-5-20251001","max_tokens":50,"stream":false,"messages":[{"role":"user","content":"hi"}]}' \
2>&1 | grep x-cmm-providerLive logs appear in the terminal:
[2026-02-28 18:01:32] claude-opus-4-6 → PASSTHROUGH ✓
[2026-02-28 18:01:45] claude-haiku-4-5-20251001 → INTERCEPTED → gemini-2.5-flash ✓
[2026-02-28 18:02:01] GET /v1/models → PASSTHROUGH
Logs are also written to ~/.cmm/cmm.log (1 MB max, auto-rotated with 3 backups).
src/
├── index.ts # CLI entry point (setup/stop/status/test)
├── config.ts # Paths, constants, and proxy settings
├── types.ts # Anthropic API type definitions
├── certs.ts # Certificate generation + Keychain management
├── dns.ts # /etc/hosts manipulation
├── server.ts # HTTPS server on port 443
├── router.ts # Model-based request routing
├── logger.ts # File + console logging with rotation
├── service.ts # macOS launchd service management
├── e2e-test.ts # End-to-end integration test
└── providers/
├── anthropic.ts # Passthrough to real Anthropic API
└── proxy.ts # CLIProxyAPI handler (streaming + non-streaming)
~/.cmm/
├── ca.key # Root CA private key (chmod 600)
├── ca.crt # Root CA certificate
├── server.key # Server private key (chmod 600)
├── server.crt # Server certificate (signed by CA)
├── .env # Proxy configuration (chmod 600)
├── cmm.pid # PID file for running instance
├── cmm.log # Request log (1 MB max, 3 backups)
├── cmm-daemon # Compiled wrapper binary (service mode)
├── cmm-service.log # Service mode log (when using launchd)
└── anthropic-ip.cache # Cached real IP of api.anthropic.com
- The Root CA private key is stored with
chmod 600(owner-only read) /etc/hostsmodification and port 443 binding requiresudocmm stoporCtrl+Calways restores/etc/hosts(SIGINT/SIGTERM handlers)- Certificates are scoped to
api.anthropic.comonly
NODE_EXTRA_CA_CERTS is not set. Run cmm setup again or:
export NODE_EXTRA_CA_CERTS="$HOME/.cmm/ca.crt"cmm needs root to modify /etc/hosts and bind to port 443:
sudo cmm <source> <target>Another cmm instance is running. Stop it first:
sudo cmm stopMake sure CLIProxyAPI is running on localhost:8317.
Make sure you opened a new terminal after cmm setup (so NODE_EXTRA_CA_CERTS takes effect).
MIT