Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (openrouter-provider-shim) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
openrouter-provider-shim
Local npx-runnable shim that enforces OpenRouter provider routing (e.g., Fireworks-only) for AI agent tools that cannot configure it natively. Primarily for Claude Code and Droid - other tools like OpenCode and OpenHands have native OpenRouter provider support.
Why this shim exists
Some AI agent harnesses can point at an OpenAI-compatible base URL, but they cannot attach OpenRouter's per-request provider routing object. This includes Claude Code, which uses the Anthropic Messages API and has no way to specify provider preferences.
OpenRouter supports a provider object for routing preferences including only, order, ignore, sort (price, throughput, latency), performance thresholds, and max price. This shim injects these fields server-side, so end users do not need OpenRouter account-wide settings.
Note: Tools like OpenCode and OpenHands have native OpenRouter provider configuration and don't need this shim. See When You DON'T Need This Shim below.
Features
- Multi-protocol support: Anthropic Messages API, OpenAI Chat Completions, and OpenAI Responses API
- Provider routing enforcement: Merge, override, or strict modes for provider policies
- Flexible authentication: Passthrough or upstream-key auth modes
- Zero dependencies for runtime: Uses only Node.js built-ins
- Privacy-first logging: Logs metadata only, never prompt content
- Cross-platform: Works on macOS, Linux, and Windows
Installation
# Run without installing
npx openrouter-provider-shim serve --port 8787 --provider-only fireworks --sort throughput --no-fallbacks
# Or install globally
npm install -g openrouter-provider-shim
openrouter-provider-shim serve --port 8787Quick Start
Claude Code
Automatic key substitution
If you have both ANTHROPIC_API_KEY and OPENROUTER_API_KEY set, the shim will automatically detect and substitute your Anthropic key with your OpenRouter key:
export OPENROUTER_API_KEY="sk-or-v1-..."
export ANTHROPIC_MODEL="moonshotai/kimi-k2.5"
npx openrouter-provider-shim serve --port 8787 --provider-only fireworks --sort throughput --no-fallbacks &
export ANTHROPIC_BASE_URL="http://127.0.0.1:8787"
claudeKnown Limitations
Rate limiting: The shim includes automatic retry with custom backoff delays for Claude Code (detected by its use of the Anthropic Messages API). Retries use delays: 1s, 2s, 4s, 8s, 12s, 18s, 24s, 32s. If you hit rate limits:
- Add your own Fireworks API key to OpenRouter (BYOK) at https://openrouter.ai/settings/integrations
- Use the
--provider-orderoption to allow fallback providers - Wait a moment between requests and manually retry or prompt "Continue"
When You DON'T Need This Shim
Some AI tools have native OpenRouter provider routing support and don't need this shim:
OpenCode - Has built-in OpenRouter provider configuration. In ~/.config/opencode/opencode.json:
{
"provider": {
"openrouter": {
"models": {
"moonshotai/kimi-k2.5": {
"options": {
"provider": {
"order": ["fireworks"],
"allow_fallbacks": false
}
}
}
}
}
}
}OpenHands - Uses LiteLLM in-process and supports provider routing via LLM_LITELLM_EXTRA_BODY:
export LLM_LITELLM_EXTRA_BODY='{"provider":{"order":["fireworks"],"allow_fallbacks":false}}'
export LLM_API_KEY="$OPENROUTER_API_KEY"
export LLM_MODEL="openrouter/moonshotai/kimi-k2.5"
openhands --override-with-envsWhen You DO Need This Shim
Use this shim for tools that cannot configure OpenRouter's per-request provider routing:
Claude Code (Primary Use Case)
Uses Anthropic Messages API - cannot set OpenRouter provider routing. This is the primary use case for this shim.
export OPENROUTER_API_KEY="your-api-key"
npx openrouter-provider-shim serve --port 8787 --provider-only fireworks
export ANTHROPIC_BASE_URL="http://127.0.0.1:8787"
export ANTHROPIC_MODEL="moonshotai/kimi-k2.5"
claudeDroid (Factory) - When Tool Calls Fail
Droid supports OpenRouter via generic-chat-completion-api, but tool calls may not work reliably with native OpenRouter integration. If they ever address this, you should be able to simply configure a custom model with OpenRouter provider settings like this:
{
"model": "moonshotai/kimi-k2.5",
"id": "custom:Kimi-K2.5-[OR-->-Fireworks]-2",
"index": 2,
"baseUrl": "https://openrouter.ai/api/v1",
"apiKey": "sk-or-v1-REDACTED",
"displayName": "Kimi K2.5 [OR -> Fireworks]",
"maxOutputTokens": 131072,
"extraArgs": {
"provider": {
"order": [
"fireworks"
],
"allow_fallbacks": false
}
},
"noImageSupport": false,
"provider": "generic-chat-completion-api"
}For the time being, however, testing has shown tool calls to fail with the above setup, however. Use this shim for better compatibility.
1. Start the shim:
export OPENROUTER_API_KEY="sk-or-v1-..."
npx openrouter-provider-shim serve --port 8787 --provider-only fireworks2. Add to ~/.factory/settings.json in the customModels array:
{
"model": "moonshotai/kimi-k2.5",
"id": "custom:Kimi-K2.5-[shim-->-Fireworks]-2",
"index": 2,
"baseUrl": "http://127.0.0.1:8787/v1",
"apiKey": "sk-or-v1-REDACTED",
"displayName": "Kimi K2.5 [shim -> Fireworks]",
"maxOutputTokens": 131072,
"noImageSupport": false,
"provider": "generic-chat-completion-api"
}CLI Commands
serve (default)
Starts the local shim server.
npx openrouter-provider-shim serve \
--port 8787 \
--provider-only fireworks \
--sort throughput \
--no-fallbacks \
--auth-mode passthroughdoctor
Validates config and checks connectivity to OpenRouter.
npx openrouter-provider-shim doctor --provider-only fireworksprint-env
Prints copy-paste environment variables for Claude Code and OpenAI clients.
npx openrouter-provider-shim print-env --port 8787Configuration
Configuration can be provided via:
- CLI flags (highest priority)
- Environment variables
- Config file (lowest priority)
Authentication
The shim supports several authentication modes:
passthrough mode (default)
- Forwards the
Authorizationheader from the inbound request to OpenRouter - Smart substitution: If the inbound auth looks like an Anthropic API key (starts with
sk-ant-) and you haveOPENROUTER_API_KEYset, the shim automatically substitutes it with your OpenRouter key - This allows you to keep
ANTHROPIC_API_KEYset for other tools while using OpenRouter via the shim
upstream-key mode
- Always uses the configured OpenRouter API key, ignoring inbound auth
- Useful when you don't want clients to know the OpenRouter key
# Default passthrough with smart substitution
npx openrouter-provider-shim serve --port 8787
# Explicit upstream key (never use inbound auth)
npx openrouter-provider-shim serve --port 8787 --auth-mode upstream-key --upstream-key "sk-or-v1-..."CLI Options
| Option | Description |
|---|---|
--config <path> |
Path to config JSON file |
--host <host> |
Host to bind (default: 127.0.0.1) |
--port <port> |
Port to bind (default: 8787) |
--merge-mode <mode> |
Provider merge mode: merge, override, strict |
--provider-only <list> |
Comma-separated list of allowed providers |
--provider-order <list> |
Comma-separated provider priority order |
--provider-ignore <list> |
Comma-separated list of providers to skip |
--sort <sort> |
Sort by: price, throughput, latency |
--no-fallbacks |
Disable fallback providers |
--require-parameters |
Require providers to support all parameters |
--data-collection <allow|deny> |
Data collection policy |
--zdr |
Enforce Zero Data Retention |
--quantizations <list> |
Comma-separated quantization list |
--auth-mode <mode> |
passthrough or upstream-key |
--upstream-key <key> |
OpenRouter API key |
--local-api-key <key> |
Local authentication key |
Environment Variables
| Variable | Description |
|---|---|
OPENROUTER_API_KEY |
Your OpenRouter API key |
SHIM_HOST |
Host to bind |
SHIM_PORT |
Port to bind |
SHIM_AUTH_MODE |
passthrough or upstream-key |
SHIM_LOCAL_API_KEY |
Local authentication key |
SHIM_MERGE_MODE |
merge, override, or strict |
SHIM_PROVIDER_ONLY |
Comma-separated allowed providers |
SHIM_PROVIDER_ORDER |
Comma-separated provider order |
SHIM_PROVIDER_IGNORE |
Comma-separated ignored providers |
SHIM_PROVIDER_SORT |
price, throughput, or latency |
SHIM_PROVIDER_ALLOW_FALLBACKS |
true or false |
SHIM_PROVIDER_REQUIRE_PARAMETERS |
true or false |
SHIM_PROVIDER_DATA_COLLECTION |
allow or deny |
SHIM_PROVIDER_ZDR |
true or false |
SHIM_PROVIDER_QUANTIZATIONS |
Comma-separated quantizations |
SHIM_PROVIDER_PREFERRED_MIN_THROUGHPUT |
Number or JSON thresholds |
SHIM_PROVIDER_PREFERRED_MAX_LATENCY |
Number or JSON thresholds |
SHIM_PROVIDER_MAX_PRICE |
JSON: {"prompt":1.0,"completion":4.0} |
Config File
Create a shim-config.json:
{
"host": "127.0.0.1",
"port": 8787,
"merge_mode": "merge",
"policy": {
"only": ["fireworks"],
"sort": "throughput",
"allow_fallbacks": false
},
"auth_mode": "passthrough",
"log_level": "info"
}Run with: npx openrouter-provider-shim serve --config shim-config.json
Merge Modes
merge (default)
- If request has no
provider, inject the configured policy - If request has
provider, merge missing fields from policy without overriding
override
- Replace request
providerentirely with policyprovider(hard enforcement)
strict
- If request
providerexists and differs from policy for any enforced fields, reject with HTTP 422 - Useful for regulated enterprise policies
API Endpoints
| Endpoint | Description |
|---|---|
POST /v1/messages |
Anthropic Messages API |
POST /v1/chat/completions |
OpenAI Chat Completions API |
POST /v1/responses |
OpenAI Responses API |
GET /v1/models |
List available models (pass-through) |
GET /healthz |
Health check |
GET /version |
Version information |
GET /config |
Current configuration (sanitized) |
Testing
# Chat Completions
curl http://127.0.0.1:8787/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "moonshotai/kimi-k2.5",
"messages": [{"role":"user","content":"Say hello"}],
"stream": false
}'
# Anthropic Messages
curl http://127.0.0.1:8787/v1/messages \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "moonshotai/kimi-k2.5",
"max_tokens": 256,
"messages": [{"role":"user","content":"Hello from anthropic messages"}]
}'
# Responses API
curl http://127.0.0.1:8787/v1/responses \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "moonshotai/kimi-k2.5",
"input": "Hello from responses"
}'License
MIT