Cursor, Claude Code, Codex, and Gemini CLI each keep their own base URL and secret. Once you add providers, rate limits and “this one returned 429 today” scatter across those configs. OmniRoute collapses that into one OpenAI-compatible endpoint on your machine. Clients remember http://127.0.0.1:20128/v1. Claude, GPT, Gemini, DeepSeek, and the rest of the catalog attach in the dashboard. The license is MIT. The release line this walkthrough follows is release/v3.8.53. Ports, commands, and routing rules below match that README. Provider counts move with the version.
“Free” means the gateway software has no license fee. Quota lives on the provider accounts you connect. The project publishes a /dashboard/free-tiers estimate of third-party free tiers and states that the figure is an aggregate, not a token grant from OmniRoute. Subscriptions you already pay for can use the same base URL through their own account flow. If you are comparing list prices, see the monthly coding-tool bill and the OpenRouter pricing notes. OpenRouter is a hosted router. OmniRoute is the gateway on your machine.
Where the gateway sits
Think of it as a socket that runs only on your machine. Upstream is still OpenAI, Anthropic, Google, DeepSeek, or another catalog provider. Downstream is any client that speaks OpenAI Chat Completions or Responses. The v3.8.53 docs cite about 375 providers and about 1,475 raw model IDs, some of them flagged for free-tier discovery. Those counts are re-audited and belong to the live dashboard catalog, not to an old screenshot.
- You hold two keys. The provider API key or OAuth session stays inside OmniRoute. Cursor and scripts use the gateway key from Dashboard → Endpoints.
- Model ids exist after you connect. Call
/v1/modelsfirst. README examples look likeopenai/gpt-5.4andglm/glm-5.2— provider, slash, model. Use the id your list actually returns. - The client list is wide. The project names Claude Code, Codex, Cursor, Cline, Continue, OpenCode, Copilot, OpenClaw, and others. Anything with a custom OpenAI base URL only needs the address.
omniroute runlaunches seven of the CLIs for you.
The README’s line is bring your own provider accounts. A free tier may require signup, approval, or a payment method, and it can close. Providers marked tos: avoid stay out of auto by default. Connecting the account does not flip that policy.
Install from zero: npm and Docker
You need Node.js on the machine. The short path:
npm install -g omniroute
omniroute
npm warn ERESOLVE and peer-dependency warnings are called out in the docs as safe to ignore at first. The dashboard opens at http://127.0.0.1:20128. The API is http://127.0.0.1:20128/v1. For a proxy without the dashboard, run omniroute serve --headless or set OMNIROUTE_HEADLESS=1.
npm 11 must allow install scripts
npm 11 can block package lifecycle scripts. OmniRoute’s postinstall has to run so the native runtime files are in place. The allow-list printed for 3.8.53 is:
npm install -g --allow-scripts=omniroute,keytar,onnxruntime-node,@parcel/watcher,@swc/core,protobufjs,esbuild omniroute
If npm names a different set, use that warning’s package list. Allowing scripts means those packages’ install scripts will execute — do it after you trust the source. On CI or a slow machine, OMNIROUTE_SKIP_POSTINSTALL=1 skips only the native SQLite warm-up. The binary copy step still runs.
Size Docker for a coding agent
The image name in the docs is still diegosouzapw/omniroute. :latest tracks the highest published stable SemVer. It does not track git main. Pin a version for anything you keep. The published example binds loopback:
docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \
-e OMNIROUTE_MEMORY_MB=8192 --memory=10g \
-p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latest
The image defaults the heap to 1024MB, enough for the dashboard and short chat. Claude Code and Codex call POST /v1/responses. The docs say those long contexts need a larger V8 heap or the process hits a fatal out-of-memory error. One coding agent is the 8192 heap and at least 10g container in the command above. Two overlapping long requests move to a 10240–12288 heap and a 12–16g container. Apple Silicon uses the image’s arm64 build. The omniroute-data volume holds secrets. Back it up and delete it as confidential data.
Connect Claude, GPT, Gemini, and DeepSeek
Open Providers, pick one you are allowed to use, and paste an API key or finish that provider’s account flow. OmniRoute does not open the lab accounts for you:
| Provider | What you bring | Where it goes |
|---|---|---|
| OpenAI (GPT) | An API key from platform.openai.com | Providers → OpenAI |
| Anthropic (Claude) | A key from console.anthropic.com, or the account flow for a Claude subscription you already pay for | Providers → Anthropic / that OAuth |
| Gemini | A key from Google AI Studio, or Gemini CLI OAuth | Providers → Gemini |
| DeepSeek | An API key from platform.deepseek.com | Providers → DeepSeek |
Free tiers are a separate list. They are not synonyms for those four keys. The first-run wizard can offer “set up free providers.” It builds the list from the current no-auth catalog and creates a connection only after you confirm each one. Names that have appeared there include Pollinations, Cloudflare AI, and SiliconFlow’s DeepSeek free tier. Terms, region, and whether the tier still exists belong to that provider. An older “keyless Claude” write-up does not enter auto when the provider is marked tos: avoid. Read the Free Tiers page for that day’s eligibility before you rely on it.
Web-cookie providers such as Gemini Web also need a browser runtime. The npm package includes Playwright and not the Chromium binary. Follow the repo’s Playwright Chromium note before the first call, or the request fails in the browser layer.
One address for the IDE and the CLI
Copy the gateway key from Endpoints. Then:
Base URL: http://127.0.0.1:20128/v1
API Key: (Dashboard → Endpoints)
Model: auto
Confirm the model list before the IDE talks:
curl http://127.0.0.1:20128/v1/models \
-H "Authorization: Bearer YOUR_KEY"
curl http://127.0.0.1:20128/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"auto","messages":[{"role":"user","content":"Hello"}]}'
Cursor, Cline, Continue, and any plugin with a custom OpenAI base URL take those three lines. Clients that cannot send a custom header can use the tokenized compatibility URL, for example http://127.0.0.1:20128/vscode/YOUR_KEY/chat/completions. When the client can send a header, prefer Authorization: Bearer.
You do not have to hand-edit every CLI config. The one-command launcher injects credentials into that process. Qwen and Gemini also get a throwaway isolated home:
omniroute run claude --model auto
omniroute run codex --model auto
omniroute run gemini --model auto
omniroute configure codex
omniroute run covers Claude Code, Codex, Aider, Goose, OpenCode, Qwen Code, and Gemini CLI. configure writes the provider and model into that tool’s own config. Documented targets include codex, claude, opencode, qwen, aider, goose, gemini, cline, continue, and kilo. --dry-run prints the environment and arguments it would use. --api-key-env NAME keeps the secret in an environment variable name so it stays out of shell history.
auto, fallback, and who stays out
auto chooses among connections that are already connected and eligible. A fresh install with nothing attached can have no eligible target. That is expected. The chosen strategy, provider, and latency come back in X-OmniRoute-Decision. Read that header before the client log.
- Quota-aware fallback. When one connection is exhausted, scheduling can move to another that still has room. v3.8.53 adds a strategy weighted by leftover quota and tries to keep one conversation on the same connection.
- A subscription route can fail closed. The documented subscription combo spends only the subscription quota you already pay for. If that quota is gone, the request stops. It does not spill onto a different key that bills you. Keep paid API keys and subscription keys out of one “fallback anywhere” combo.
tos: avoidstays out by default. A successful connect is not membership inauto. To pin one gateway key to one model, set that key’sforcedModelinstead of hard-coding an upstream URL in the client.
Compression is an optional pipeline and transparent to the client. The docs describe it as composable engines. The set that actually ran is in the X-OmniRoute-Compression response header. Savings depend on the model and the request. Treat the range on the README as a project claim, not a per-call guarantee. Memory is off by default. Credential masking is opt-in.
On a Cloud Mac: loopback plus SSH
The gateway fits a Mac that stays on: listen on loopback port 20128, and SSH-forward that port to your laptop. A Cloud Mac has a fixed region and SSH, and Apple Silicon can run the official arm64 image. Do not bind the admin UI to 0.0.0.0.
ssh -N -L 20128:127.0.0.1:20128 user@your-cloud-mac
After the tunnel is up, Cursor or omniroute run on the laptop still uses http://127.0.0.1:20128/v1. It looks local. The bytes land on the cloud Mac’s loopback. Provider secrets stay in the cloud volume or the user directory, not in Git. If OpenClaw is already on that Mac, point its model base URL at the same /v1 and leave a single copy of the provider keys in the gateway.
When the dashboard needs a login, the docs offer optional OIDC. Password login remains available. Remote control also has scoped tokens (connect, contexts, tokens) under the project’s Remote Mode. Use that path. Do not publish the dashboard on a public IP to save a step.
What to check when it stalls
/v1/modelsis empty. No provider connection succeeded, or the client used the provider key where the gateway key belongs.autoreports no route. The only connections are excluded, or today’s free tier is not eligible. Use a paid key you know works, or put a concrete id from/v1/modelsin the model field.- The global install cannot find a native module. Reinstall with npm 11’s
--allow-scriptsand the package names from that warning. - A coding agent dies mid-request in Docker. Raise
OMNIROUTE_MEMORY_MBand--memoryto the coding-agent tier. Leave the 1024MB default for the dashboard only. - The first web-provider call fails. Install Playwright’s Chromium, then retry. Change the routing policy after that succeeds.
- The counts look stale. 375 providers and 1,475 model IDs are the v3.8.53 doc figures. After an upgrade, trust the dashboard and the README.
FAQ
Short version: the software is free and the quota is the provider’s; the address is /v1 on local port 20128; auto uses eligible connections only; coding agents in Docker need more memory; leave the port on loopback and SSH-forward it. The full Q&A is in the FAQ structured data in the page head.