NiftyTechFinds · Implementation Kit

Claude Code + OmniRoute Complete Setup Kit

Connect Claude Code to OmniRoute, configure model routing, and get a production-ready setup with copy/paste configurations. Modules unlock one at a time — tick each step as you finish it and the guide advances you automatically.

Version 1.0.0 Last verified 2026-09-13 ≈ 35 minutes Skill level: Beginner–Intermediate
Your progress is saved automatically in this browser.
0/0 steps · 0% · 0/0 modules

Every click after this is a node on that diagram. When in doubt, trace where you are on it.

Your OmniRoute Base URL and a token/API key, from your OmniRoute account. Everything else you need is in this guide. Never share these with anyone, and never paste a real value while someone else watches your screen live.

We use claude-sonnet-4-6 as the worked example. If your OmniRoute dashboard names a different route/model, note it now and substitute it in Module 05.

Claude Code is the CLI you talk to. OmniRoute sits between it and the model providers. Claude Code sends every request to OmniRoute; OmniRoute decides which model answers, tracks usage, and keeps provider keys off your machine.

Claude Code treats OmniRoute as a gateway. A gateway is simply an address (ANTHROPIC_BASE_URL) plus a credential (ANTHROPIC_AUTH_TOKEN). No OmniRoute files to install — it’s two variables. The entire kit is making those two variables true and proving it.

Follow the diagram: access → connect → choose → verify → run. The decision node is your checkpoint at Module 05.

ACCESS
Get OmniRoute access
dashboard → key
CONNECT
Point Claude Code at OmniRoute
ANTHROPIC_BASE_URL + token
CHOOSE
Pick models & routing
/model · discovery · headers
CHECKPOINT
Does the curl test pass?
Module 05
No → jump to Module 07 troubleshooting
Fix it
symptom → check → fix
RUN
Launch a routed Claude Code session
you’re live
Why this matters Once you’ve made these two variables true on one machine, you can reproduce them on any machine in minutes — that’s the “complete setup kit” part. This guide makes it repeatable, not memorized.

Go to the OmniRoute dashboard and sign in. If you don’t yet have an account, sign up and finish onboarding.

Follow the dashboard’s API keys section. Copy the key once — most providers show it only a single time. Save it in your password manager, not a scratch note.

NAV I can’t find an “API keys” section at all.

Why. OmniRoute’s dashboard is a cloud service and changes without notice; the button may live under a different name (Settings, Account, Developers, Billing → Keys).

Fix it. Trust the dashboard, not this guide. Open its docs or search the dashboard for “key”, “token” or “API” and follow whatever label the site actually uses.

Dashboard usually shows it near API keys or in the docs. It looks like https://… with no trailing slash. If your dashboard shows one sample endpoint per provider, note the OmniRoute-specific one.

OmniRoute may expose named routes (e.g. a smart router for Claude models) or plain model ids (e.g. claude-sonnet-4-6). Note exactly which string you’ll test with.

Honesty note — unverified worksheet OmniRoute is a cloud service whose dashboard changes. We deliberately did not hard-code its endpoint or button names here (they become obsolete fast — the docs rule for this kit). What is verified (2026-09-13) is the Claude Code side, in Modules 03–07. If your dashboard names differ from our labels, trust the dashboard and fill the worksheet with what it actually shows.

Run claude --version in your terminal. If it errors, install Claude Code first (see the README), then return here.

CMD claude: command not found

You’ll see. Your shell replies zsh: command not found: claude (or the equivalent in PowerShell).

Fix it. Install Claude Code following the README in this package — e.g. npm install -g @anthropic-ai/claude-code. Then close and reopen your terminal and run claude --version again.

ANTHROPIC_BASE_URL = your OmniRoute Base URL. ANTHROPIC_AUTH_TOKEN = your API key (this is the bearer-token credential). Each variable maps to one HTTP header — the token travels as Authorization: Bearer …. If your OmniRoute key is meant to be sent as x-api-key instead, swap ANTHROPIC_AUTH_TOKENANTHROPIC_API_KEY.

Paste the block below. Replace https://omniroute.example.com with your real Base URL and sk-your-token with your real key. This proves OmniRoute answers before Claude Code is involved.

terminal
export ANTHROPIC_BASE_URL=https://omniroute.example.com
export ANTHROPIC_AUTH_TOKEN=sk-your-token

curl -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":1,"messages":[{"role":"user","content":"hi"}]}'
Success looks like a JSON object with an id and a content array. A non-JSON page, an HTML login page, or a timeout means the address/network is the problem — that’s Module 07 material.
Two details from live testing (see the “verified” flag below) (1) This curl command was run against a real OmniRoute gateway on 2026-09-13: it returned 200 with the expected reply. OmniRoute routed the claude-sonnet-4-6 request to a different contributor model and answered correctly — the model name in the response may differ from the one you requested; that is the router doing its job. (2) The gateway returned HTTP 415 unless Content-Type: application/json was sent explicitly — that header is now in the command and is the difference between success and 415.
401 Unauthorized — OmniRoute rejects your token.

You’ll see. curl prints HTTP 401 and the gateway does not accept the token (Claude Code may later report “not authorized”).

Most likely. The credential is in the wrong variable. ANTHROPIC_AUTH_TOKEN sends Authorization: Bearer; ANTHROPIC_API_KEY sends x-api-key. OmniRoute only reads one of them.

Fix it. Switch to the other variable (or use x-api-key: $ANTHROPIC_API_KEY in the curl command) and retry. Re-copy the token string completely — no line breaks, no trailing space.

Full remedy in Module 07 →
415 HTTP 415 “Content-Type must be application/json”.

You’ll see. HTTP 415 in the terminal.

Why. curl’s -d flag defaults to application/x-www-form-urlencoded; this gateway requires JSON. Observed live on an OmniRoute gateway, 2026-09-13.

Fix it. Ensure the header -H "Content-Type: application/json" is present and re-run. The command above already includes it.

Full remedy in Module 07 →
NET Connection refused / “Can’t reach the API server” (ENOTFOUND).

You’ll see. curl fails immediately — Connection refused, ENOTFOUND, or a timeout.

Most likely. Nothing is answering at the Base URL: a typo, http vs https, a trailing slash, or a VPN/firewall blocking the path to the gateway.

Fix it. Copy the exact Base URL from your OmniRoute dashboard and open it in your browser first. Only then retry curl.

Full remedy in Module 07 →
200 Empty or malformed response (HTTP 200) — often an HTML page.

You’ll see. The call “succeeds” but the body isn’t Claude API JSON — often an HTML login page served with status 200.

Most likely. The route is pointing at a proxy, an auth wall, or a wrong path that answers with something other than the API.

Fix it. Run the curl test and inspect the raw body. Fix whatever answers with a non-API response (wrong path, proxy in the way, auth wall).

Full remedy in Module 07 →

Shell exports die with the terminal. Put both variables in the env block of your user-level settings file so every new terminal picks them up. Open ~/.claude/settings.json and add the block below.

~/.claude/settings.json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://omniroute.example.com",
    "ANTHROPIC_AUTH_TOKEN": "sk-your-token"
  }
}
JSON settings.json is rejected as invalid.

You’ll see. Claude Code warns that ~/.claude/settings.json failed to parse.

Fix it. Remove any trailing commas and make sure quotes are straight (", not smart quotes). Validate the file: node -e "JSON.parse(require('fs').readFileSync(process.env.HOME+'/.claude/settings.json'))" — it exits silently when the JSON is valid.

ENV The variables aren’t picked up in a fresh terminal.

Most likely. The block was added to a project settings.json, or to shell config that isn’t loaded by your terminal.

Fix it. Use the user-level ~/.claude/settings.json. Confirm the key is exactly env with the two variable names spelled correctly, then open a brand-new terminal window (not a new tab in the old one).

Put the credential in user-level settings only (~/.claude/settings.json), or in a shell export. Never commit a credential to a project’s .claude/settings.json — that file can be shared with the repo. When both a shell export and the settings env block set a variable, the settings block wins.

About your subscription While a gateway credential variable is active, your claude.ai subscription is not used — you’re billed per token by whoever owns the credential OmniRoute forwards. Confirm with your OmniRoute plan before sending heavy traffic.

Inside an active session, type /model. Built-in Claude models appear. If your gateway serves model names that aren’t in the built-in list and you want them in the picker, do step 2 first.

Set CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 anywhere Claude Code reads it (shell or the env block). At startup Claude Code then queries OmniRoute’s model list and adds those names to the picker, labeled “From gateway”.

~/.claude/settings.json
{
  "env": {
    "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
  }
}

To confirm discovery ran: start with claude --debug and look for [gatewayDiscovery] in ~/.claude/debug/<session-id>.txt.

Some gateways route or tag requests with a custom header (tenant, routing key, environment). Use ANTHROPIC_CUSTOM_HEADERS with one Name: Value pair per line — inside JSON, separate pairs with \n.

~/.claude/settings.json
{
  "env": {
    "ANTHROPIC_CUSTOM_HEADERS": "X-OmniRoute-Route: fast\nX-Tenant: acme"
  }
}

Quit and relaunch claude (or open a fresh terminal) so it re-reads settings and re-runs discovery.

Run the Module 03 curl block again in a fresh terminal. JSON in = the plumbing is good.

ENV A fresh terminal still says “command not found” or the URL/key are empty.

Why. The exports in the code block above are terminal-session only when typed directly — they don’t survive a restart unless they’re in your settings file or shell profile.

Fix it. Add both variables to ~/.claude/settings.json (Module 03, step 4) or your shell profile, then open a brand-new terminal.

Run claude. If it opens straight to a session, your credential was picked up. If it asks you to log in instead, your env isn’t being read — see Module 07 “asks to log in even though curl works.”

LOGIN Claude Code asks you to log in even though curl succeeds.

Why. A reachable Base URL alone isn’t a credential. A project-level env block only applies after the first-run wizard and trust prompt, so the CLI still has no credential of its own.

Fix it. Set ANTHROPIC_AUTH_TOKEN somewhere Claude Code reads before first-run setup: a shell export, or the env block in ~/.claude/settings.json. Then relaunch.

Full remedy in Module 07 →

Open Claude Code’s status view and confirm it reports your OmniRoute Base URL as the active endpoint, not the default Anthropic API.

URL The Status panel still shows the default Anthropic API endpoint.

Most likely. A project-level env overrides your user-level value, or the running session started before you edited settings.

Fix it. Confirm your user-level settings hold the Base URL, check no project .claude/settings.json overwrites it, then fully quit and relaunch claude.

Type a tiny prompt: “Reply with exactly: routed ok”. Confirm the reply arrives and, ideally, that your OmniRoute dashboard shows one request for this session.

403 “403 Forbidden” — OmniRoute’s logs show no request received.

Most likely. A firewall or reverse proxy in front of the gateway blocked the request body. Short curls pass, but real Claude Code prompts contain XML-ish tags that match cross-site-scripting body rules.

Fix it. Exempt the gateway’s /v1/messages path from body inspection (e.g. AWS WAF’s CrossSiteScripting_Body, or the equivalent OWASP CRS rules). This is an OmniRoute-side/hosting change.

Full remedy in Module 07 →

Start claude --debug. Look at ~/.claude/debug/<session-id>.txt for gateway auth and model discovery lines. This is your most direct evidence of what Claude Code is trying to reach.

Still failing? Stop experimenting. Jump to Module 07, find your symptom in the matrix, work the check column, then the fix. One symptom → one row — that’s the whole process.
Read the screenshot like a checklist The request asked for claude-sonnet-4-6; the response model field shows the router served it via muse-spark-1.2-contributor-free. Difference between requested and served = the router doing its job. Your dashboard will show the same request in its usage log.

Never commit ~/.claude/settings.json or any file containing ANTHROPIC_AUTH_TOKEN. If you must store config in a repo, use placeholders (YOUR_OMNIROUTE_TOKEN) and document how it maps to the real value.

A project’s .claude/settings.json and .claude/settings.local.json apply only after first-run setup and trust prompts — and the project file can ride into a repo. Both reasons: user-level or shell only for secrets.

Revoke and reissue from the OmniRoute dashboard when a key leaks or a teammate leaves. If your provider issues short-lived credentials, set up an apiKeyHelper (a command Claude Code runs to fetch the credential instead of a static variable) — covered further in the troubleshooting/notes section of this package.

Debug logs and error reports can contain headers. Clean ~/.claude/debug/ before sharing a log for support, and scrub Authorization lines.

80% of gateway failures are the same curl test failing. Run the Module 03 curl block first, always. Its result picks the right row below.

401curl fails using your token, or Claude Code says “not authorized”
Check

Which credential variable did you set? ANTHROPIC_AUTH_TOKEN sends Authorization: Bearer; ANTHROPIC_API_KEY sends x-api-key. A credential in the wrong variable reaches OmniRoute in a header it doesn’t read.

Fix

Switch to the other variable (or use x-api-key: $ANTHROPIC_API_KEY in the curl command) and retry. Verify the token string itself was copied completely — no line breaks, no trailing space.

NETConnection refused / “Can’t reach the API server” (ENOTFOUND)
Check

Nothing is answering at the Base URL: the address is wrong, or a VPN/firewall blocks the path to the gateway. The curl test fails immediately with the same cause.

Fix

Confirm the exact Base URL from the OmniRoute dashboard (look for typos, http vs https, trailing slash) and confirm your network can reach it — try in your browser first.

200API returned an empty or malformed response (HTTP 200)
Check

The gateway or an intermediate proxy answered with a non-API response — often an HTML page or a login screen, served with status 200.

Fix

Run the curl test and inspect the raw body. Fix the route that answers with something other than a Claude API response (wrong path, proxy in the way, auth wall).

LOGINClaude Code asks you to log in even though curl succeeds
Check

The CLI has no credential of its own. A reachable Base URL alone isn’t a credential — and a project-level env block applies only after the first-run wizard and trust prompt.

Fix

Set ANTHROPIC_AUTH_TOKEN somewhere Claude Code reads before first-run setup: a shell export, or the env block in ~/.claude/settings.json. Then relaunch.

403“403 Forbidden” — OmniRoute’s own logs show no request received
Check

A web application firewall or reverse proxy in front of the gateway blocked the request body before it reached the gateway. Claude Code prompts contain XML-style tags and source code that match cross-site-scripting body rules, so a short curl passes while a real session doesn’t.

Fix

Exempt the gateway’s /v1/messages path from request-body inspection (e.g. AWS WAF’s CrossSiteScripting_Body managed rule, or the equivalent OWASP CRS rules on nginx/ModSecurity). This is an OmniRoute-side/hosting change.

TLSCertificate / TLS errors, but curl succeeds
Check

Claude Code’s runtime isn’t trusting the same certificate authority curl uses — common behind corporate TLS-inspection proxies.

Fix

Set NODE_EXTRA_CA_CERTS to your CA bundle path and restart Claude Code. See the CA certificate store section of the Claude Code docs.

415curl returns HTTP 415 “Content-Type must be application/json”
Check

curl’s -d flag defaults to application/x-www-form-urlencoded; this gateway requires JSON. (Observed live on an OmniRoute gateway, 2026-09-13.)

Fix

Add -H "Content-Type: application/json" to the curl command and retry. The fixed command in Module 03 includes it.

MODELThe model in the response differs from the one you requested
Check

The router redirected your request to a contributing/serving model (observed live: claude-sonnet-4-6 request answered by muse-spark-1.2-contributor-free). This is routing working as designed, not an error.

Fix

No fix needed. Verify against the routing intent in your OmniRoute dashboard; change the model/route you request if you want a specific target.

MODELModel name not found / route unknown
Check

The model string you’re requesting isn’t one OmniRoute serves from that credential, or model discovery isn’t enabled so the picker shows only built-ins.

Fix

Use the exact model/route id from your dashboard; enable CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 and check the picker for “From gateway” entries.

HEADERA custom routing header isn’t being applied
Check

ANTHROPIC_CUSTOM_HEADERS formatting: one Name: Value per line; inside JSON, pairs separated by \n. Routing/tenant headers count as headers that need approval in the approval dialog.

Fix

Verify the header string exactly (spell the header name as OmniRoute expects), relaunch, and approve the header when prompted.

Claude Code and OmniRoute change fast. Set a quarterly calendar reminder to run the curl test once and skim the changelog in this package. Update the “Last verified” date when you do.

The package ships with changelog.md. Check it before upgrading Claude Code or an OmniRoute plan change — known breakages are listed there first.

When any variable changes, prove it on one machine (Module 05 all green) before reproducing on the rest. That’s the whole update discipline.

What this kit does and does not claim The Claude Code gateway instructions in Modules 03–08 were verified against the official Claude Code docs on 2026-09-13, and the connection pattern (curl through ANTHROPIC_BASE_URL + token, including the Content-Type fix) was tested live against a running OmniRoute gateway the same day. OmniRoute is a third-party service Anthropic does not endorse or audit, and it changes without notice — the OmniRoute-specific values for Module 02 (your Base URL, key, route names) must be read from your own dashboard, and may differ from what you’ve seen here. If a step here seems wrong, the official docs win.

Same two variables, same settings file, same curl test. Ten minutes the second time — that’s the payoff of a written procedure.