keyrouter

mcp
Security Audit
Fail
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Fail
  • child_process — Shell command execution capability in .github/workflows/docker-publish.yml
  • exec() — Shell command execution in .github/workflows/docker-publish.yml
  • process.env — Environment variable access in .github/workflows/docker-publish.yml
  • fs module — File system access in .github/workflows/docker-publish.yml
  • process.env — Environment variable access in .github/workflows/publish-cli.yml
  • fs module — File system access in .github/workflows/tray-binaries.yml
  • child_process — Shell command execution capability in cli/cli.js
  • execSync — Synchronous shell command execution in cli/cli.js
  • exec() — Shell command execution in cli/cli.js
  • fs.rmSync — Destructive file system operation in cli/cli.js
  • os.homedir — User home directory access in cli/cli.js
  • process.env — Environment variable access in cli/cli.js
  • fs module — File system access in cli/cli.js
  • process.env — Environment variable access in cli/hooks/postinstall.js
  • child_process — Shell command execution capability in cli/hooks/sqliteRuntime.js
  • spawnSync — Synchronous process spawning in cli/hooks/sqliteRuntime.js
  • os.homedir — User home directory access in cli/hooks/sqliteRuntime.js
  • process.env — Environment variable access in cli/hooks/sqliteRuntime.js
  • fs module — File system access in cli/hooks/sqliteRuntime.js
  • child_process — Shell command execution capability in cli/hooks/trayRuntime.js
  • spawnSync — Synchronous process spawning in cli/hooks/trayRuntime.js
  • fs.rmSync — Destructive file system operation in cli/hooks/trayRuntime.js
  • os.homedir — User home directory access in cli/hooks/trayRuntime.js
  • fs module — File system access in cli/hooks/trayRuntime.js
  • child_process — Shell command execution capability in cli/scripts/build-cli.js
  • execSync — Synchronous shell command execution in cli/scripts/build-cli.js
  • exec() — Shell command execution in cli/scripts/build-cli.js
  • fs.rmSync — Destructive file system operation in cli/scripts/build-cli.js
  • process.env — Environment variable access in cli/scripts/build-cli.js
  • fs module — File system access in cli/scripts/build-cli.js
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

One endpoint for every AI you already pay for — self-hosted router for Claude Code, Codex, Cursor & 40+ providers.

README.md
KeyRouter logo

KeyRouter

One endpoint. Every AI you already pay for. Zero wasted tokens.

npm
Downloads
Docker Pulls
Publish
License
Stars

⚡ Quick Start · 🎯 Which install path? · 🔌 Connect a tool · ✨ Features · 🛠 CLI · ❓ FAQ


📌 At a glance

What it is A self-hosted router that sits between your AI coding tools and 40+ providers (100+ models)
Install npm i -g keyrouter — no account, no signup, no cloud lock-in
Endpoint http://localhost:20131/v1 — speaks OpenAI and Claude API
Runs on Node.js ≥ 22.23 (24 LTS recommended) · Linux · macOS · Windows · Docker amd64/arm64
Data 100% local in ~/.keyrouter (SQLite) — keys, logs, usage never leave your machine
Cost for the router itself Free, MIT-licensed. You keep paying (or not paying — free tiers work) your providers

[!TIP]
60-second try: npx keyrouter → dashboard opens → Providers → Kiro AI (free Claude, no login) → point Claude Code at http://localhost:20131/v1. That's it — you're routing.

# 1. route-all-the-things in one line
npx keyrouter

# 2. wire the CLI tools on this machine to it (backs up configs once as *.bak-keyrouter)
npx keyrouter connect http://localhost:20131 --tools claude,codex,cline

# 3. see what it changed
keyrouter show claude

🚀 Quick Start

Option 1 · npm (desktop, recommended)

npm install -g keyrouter
keyrouter
# → dashboard at http://localhost:20131 (default password: 123456 — change it)

Or skip the install entirely: npx keyrouter

Option 2 · Docker (server / VPS)

docker run -d --name keyrouter \
  -p 20131:20131 \
  -v "$HOME/.keyrouter:/app/data" \
  -e DATA_DIR=/app/data \
  keyzakyy/keyrouter:latest

Images for amd64 + arm64 on Docker Hub and GHCR. Version pinning, tags, and upgrades: DOCKER.md.

Option 3 · from source

git clone https://github.com/keyzakyy-dev/keyrouter.git
cd keyrouter && cp .env.example .env
npm install && npm run build
npm run start

Full contributor setup (tests, lint, dev server on :20127): docs/ARCHITECTURE.md.


🤔 Which install path do I need?

You are… Use Why
Coding on a laptop/desktop npm (Option 1) Auto-updates itself, tray icon, zero config
Deploying on a VPS/homelab Docker (Option 2) Persistent volume, restart policy, arm64 OK
Hacking on the router itself source (Option 3) Dev server, hot reload, tests
Just testing once npx keyrouter Nothing installed, throwaway

🔌 Connect a tool in 3 lines

Every tool that speaks the OpenAI or Claude API works out of the box:

Endpoint : http://localhost:20131/v1
API Key  : (copy from the dashboard → API Keys)
Model    : kr/claude-sonnet-4.5

Or let KeyRouter write the configs for you — it backs up each tool's file once as *.bak-keyrouter:

npx keyrouter connect http://localhost:20131                       # pick tools interactively
npx keyrouter connect http://localhost:20131 --tools claude,codex  # choose in advance
npx keyrouter connect --reset --tools claude,codex                 # undo
Supported tools for keyrouter connect (click to expand)

claude · codex · opencode · droid · crush · kilo · cline · pi · omp · all

Cursor and other GUI tools: paste the endpoint + key manually per the table above.


🧠 Why KeyRouter?

The problem you already have:

  • Subscription quotas expire monthly, even unused.
  • Rate limits hit mid-task; you wait or switch manually.
  • git diff / grep / ls output burns input tokens on every turn.
  • Every provider = another key, endpoint and config to babysit.

KeyRouter's answers:

🔥 RTK Token Saver Compresses tool output before it reaches the model — 20–40% fewer input tokens per request
🪜 3-tier fallback Subscription → cheap (GLM, MiniMax) → free (Kiro, OpenCode Free), automatically, mid-request
📊 Quota tracking Know what's left on every subscription; drain it before it resets
👥 Multi-account Several accounts per provider, load-spread
🔁 Auto token refresh OAuth stays alive in the background; no re-login marathons
🎛 Custom combos Unlimited kr/* model mixes with your own routing strategy

📸 Screenshots

Endpoint — base URL, remote access tunnel & API keys Providers — 40+ providers, multi-account with live status
Endpoint page Providers page
CLI — one-shot keyrouter connect wires 9 coding tools Prompt Injection — global, per-key, and chat-script variants
CLI tools page Prompt injection page

🗺 How it works

┌──────────────────┐
│   Your CLI tool  │   Claude Code, Codex, Cursor, Cline, Droid, Crush…
└────────┬─────────┘
         │  http://localhost:20131/v1
         ▼
┌─────────────────────────────────────────────┐
│              KeyRouter (router)             │
│  1. Auth your API key (+ per-key access)    │
│  2. RTK Token Saver compresses tool output  │
│  3. Translate format: OpenAI ↔ Claude ↔     │
│     Gemini ↔ Kiro ↔ Vertex ↔ Cursor         │
│  4. Log, meter and fall back as needed      │
└────────┬────────────────────────────────────┘
         │
         ├─→ Tier 1: subscription (Claude, Codex, Copilot)
         ├─→ Tier 2: cheap (GLM, MiniMax, …)
         └─→ Tier 3: free (Kiro, OpenCode Free, Vertex, …)

Deep dive (executors, streaming, OAuth flows, DB schema): docs/ARCHITECTURE.md. Full docs site: gitbook/content/en/.


✨ Features

Area What it does Why it matters
RTK Token Saver Compresses git diff, grep, ls and friends in-place 20–40% cheaper requests, fail-open (never breaks your call)
Format translation OpenAI ↔ Claude ↔ Gemini ↔ Kiro ↔ Vertex ↔ Cursor One endpoint into any CLI tool
Usage analytics Tokens, cost, latency per request — filterable, exportable See exactly where money goes
Per-key model access Restrict each API key to specific combos and models Share the endpoint without exposing every provider
Prompt injection System prompts / chat scripts per key, model or global Router-level personas, no tool config needed
Proxy pools Health checks, rotation, dead-pool cleanup Keeps big key fleets alive
Request log Live console with per-request detail and redaction Debug any call in seconds
Update button In-dashboard "update available" with copy-install command No surprise versions

🛠 CLI

keyrouter                    # start with defaults
keyrouter --port 8080        # custom port
keyrouter --no-browser       # don't open the dashboard
keyrouter --skip-update      # skip the auto-update check
keyrouter show claude        # inspect a tool's config (try --json)
keyrouter connect --help     # remote-connect options
keyrouter --help             # everything else

⚙️ Environment & Data

Environment variables (click to expand — defaults are fine for local use)
Variable Required Description
JWT_SECRET Yes Long random secret for session signing
INITIAL_PASSWORD Yes First dashboard password — change after login
DATA_DIR Yes Data directory (default ~/.keyrouter)
PORT No Server port (default 20131)
API_KEY_SECRET No Secret for API keys issued by the endpoint proxy
MACHINE_ID_SALT No Salt for machine identity
CLOUD_URL No Cloud sync endpoint — off unless you set it
BASE_URL No Public base URL of this instance
HTTP_PROXY / HTTPS_PROXY No Outbound proxy for upstream calls

Full list + examples: .env.example

Where my data lives? (click to expand)
  • macOS / Linux: ~/.keyrouter/db/data.sqlite
  • Windows: %APPDATA%/keyrouter/db/data.sqlite
  • Docker: /app/data/db/data.sqlite — mount $HOME/.keyrouter to persist it
  • Everything (keys, logs, usage, settings) is in that one SQLite file. Back it up = back up KeyRouter.
How updates work (click to expand)

The CLI and web assets update via src/lib/updater/ — when a new version exists, the dashboard shows an Update available button with a copy-install command; nothing auto-installs without your click. Docker users: pull the new tag and recreate the container (data stays in the mounted volume).


🩹 Troubleshooting

Symptom Fix
Port 20131 already in use keyrouter --port 8080 (and update the endpoint in your tools)
401 from KeyRouter Key mismatch — re-copy the API key from the dashboard
Tool can't connect after upgrade npx keyrouter connect --reset --tools <tools> then reconnect
OAuth token expired mid-use Shouldn't happen (auto-refresh); force reconnect the provider in Providers
Docker: data gone after recreate You didn't mount -v "$HOME/.keyrouter:/app/data" — data lives in the volume, not the image

More: gitbook/content/en/troubleshooting.md · Discussions


❓ FAQ

Do my API keys / prompts leave my machine?

No. KeyRouter is fully self-contained — requests go from your tools to your local (or your own VPS's) KeyRouter process straight to the provider. No telemetry, no middleman. The only network calls are the ones you configure: providers, optional proxy pools, and the optional CLOUD_URL sync (off by default).

Is kr/<model> special syntax?

Yes — kr/ prefixes a combo: a KeyRouter-defined model mix with its own fallback strategy (e.g. kr/claude-sonnet-4.5 → falls back to a cheaper Claude, then a subscription Codex, then a free tier). Build your own in the dashboard → Combos.

Can I run it on a shared server and keep it private?

Yes — that's exactly what per-key model access + INITIAL_PASSWORD + BASE_URL + HTTPS (put it behind nginx/Caddy) are for. Authentication is session-based for the dashboard and API-key-based for /v1.

Does it really work with free providers?

Yes — Kiro AI (free Claude) and OpenCode Free work without any login, as Tier-3 fallback or standalone. The dashboard marks every provider free/paid/subscription so the router picks in the right order.


🗺 Roadmap

  • keyrouter connect one-shot tool config
  • Per-key model access control
  • Trusted publishing (releases are provenance-signed from CI)
  • Cloud sync dashboard for multi-instance deployments (CLOUD_URL)
  • Request replay / diff between two providers for the same payload

🤝 Contributing

npm install
npm run dev                                  # hot-reload dev server on :20127
npm run build                                # production standalone build
npm run cli:pack                             # build the publishable CLI tarball
npm run release:dry                          # preview the next version bump (no writes)
node tests/__baseline__/verify-no-regression.mjs   # regression check vs baseline

# lint the files you touched (repo-wide eslint has pre-existing failures):
npx eslint path/to/changed-file.js

The test suite is intentionally not all-green on a bare checkout (~938 pass / ~64 known-fail, tracked in tests/__baseline__/known-fails.txt) — use verify-no-regression.mjs to judge your change, not the raw count. Unit tests for the embeddings endpoint live in tests/ (own package.json). Full conventions: CLAUDE.md & AGENTS.md.

Please read gitbook/content/en/faq.md for common questions before opening an issue, and docs/ARCHITECTURE.md before touching routing, fallback, OAuth or DB code. PRs that touch auth, keys, headers or SSRF surfaces will get extra scrutiny.

For bugs → Issues · Questions → Discussions


⚖️ KeyRouter vs 9Router vs 9Router Pro

9Router 9Router Pro KeyRouter
Positioning Origin — free AI router & token saver Pro fork — prompts & quotas Development fork — 9Router base + Pro features + extras
Token savers RTK, Headroom, Caveman, Ponytail Same Same + PXPIPE image compression
Prompt injection (global / per-key / per-model) ❌ ✅ ✅
Per-key control ❌ ✅ quotas & rate limits ✅ model access
Modalities Chat, image, speech, embeddings Same Same + video, search, web fetch
Extra tooling Proxy pools Proxy pools + health checks Proxy pools, MITM proxy, remote access, MCP plugins

📚 Documentation

Doc What's in it
DOCKER.md Docker & docker-compose, image tags, verified digests, publishing
docs/ARCHITECTURE.md Executors, streaming pipeline, OAuth, DB schema, env matrix
gitbook/content/en/index.md Full documentation site (EN, plus JA / ZH / ES / PT / FA)
CHANGELOG.md Every release, auto-generated from commits
npm https://www.npmjs.com/package/keyrouter

🙏 Acknowledgments

KeyRouter is a derivative and rebrand of 9Router by decolua, with ideas from 9Router Pro by Gienetic. Both released under the MIT license. The original copyright notice and license terms are preserved in LICENSE.

The token-saving pipeline builds on ideas from RTK (Rust token saver) and CLIProxyAPI (the Go implementation that inspired this JavaScript port). Many thanks to their authors.


📄 License

MIT — see LICENSE.

Reviews (0)

No results found