Claude Code Router with Nadir

Add prompt-aware model choice to Claude Code Router with a route script: Nadir sizes each auto turn and CCR sends it to the model you set for that tier.

Prompt-aware model choice for Claude Code Router (CCR), as a route script. CCR already sends Claude Code to the providers you configure. The script adds one question before each request whose model is auto: is this turn simple, medium or complex? CCR then sends it to the model you picked for that tier.

Nadir only returns the tier. Your provider keys stay in CCR and the completion never passes through Nadir.

Setup

1. Save the script

Save this as nadir.js in your CCR config directory. CCR runs route scripts in a sandboxed worker and passes the request summary as input.

nadir.js
// CCR Node.js route script body. Configure the environment before enabling.
// API contract: https://getnadir.com/docs/decision-api
if (api.env("CCR_NADIR_ROUTING_ENABLED") !== "1" || input.model !== "auto") return null;
if (input.summary.hasImage || !input.summary.lastUserText.trim()) return null;
const simple = api.env("CCR_NADIR_SIMPLE_MODEL");
const complex = api.env("CCR_NADIR_COMPLEX_MODEL");
if (!simple || !complex) return null;
// Without a medium model, medium prompts go to the complex model.
const targets = { simple, medium: api.env("CCR_NADIR_MEDIUM_MODEL") || complex, complex };
const key = api.env("NADIR_API_KEY");
const base = (api.env("CCR_NADIR_BASE_URL") || "https://api.getnadir.com").replace(/\/+$/, "").replace(/\/v1$/, "");
try {
  const response = await api.fetch(base + "/v1/bucket", {
    method: "POST",
    headers: { "content-type": "application/json", ...(key ? { "x-api-key": key } : {}) },
    body: JSON.stringify({ prompt: input.summary.lastUserText.slice(0, 8192), source: "claude-code-router" })
  });
  if (!response.ok) return null;
  const bucket = JSON.parse(response.body)?.bucket;
  if (typeof bucket !== "string" || !Object.hasOwn(targets, bucket)) return null;
  return { model: targets[bucket] };
} catch {
  return null;
}

2. Set the environment

Set these where CCR starts. Model values use CCR's provider/model form and must be models you have already configured in CCR.

Shell
export CCR_NADIR_ROUTING_ENABLED=1
export CCR_NADIR_SIMPLE_MODEL=deepseek/deepseek-chat
export CCR_NADIR_MEDIUM_MODEL=openrouter/anthropic/claude-sonnet-4.6   # optional
export CCR_NADIR_COMPLEX_MODEL=openrouter/anthropic/claude-opus-4.6
export NADIR_API_KEY=ndr_...                                          # optional

3. Add the rule

In CCR's Routing page, add a Node.js script rule, select nadir.js, and start with a 1500 ms timeout. Put a static rule for auto after it, so a request the script skips still has a model.

Then point Claude Code at CCR with the model auto. Request logs show the resolved model per turn.

Behavior

  • Only requests whose model is auto are classified. A model named explicitly is never changed.
  • Without CCR_NADIR_MEDIUM_MODEL, medium turns go to the complex model.
  • Images, empty turns, missing configuration, an unknown tier, an error or a timeout all return no decision, and CCR moves on to the next rule. The script fails open.
  • The script sends up to 8,192 characters of the latest user message and nothing else: no headers, system prompt, tools or earlier turns.

With or without a key

Without NADIR_API_KEY the script uses the free anonymous tier of api.getnadir.com. It is rate-limited per IP and keeps no per-request record, only aggregate counts. With a key, decisions appear in your Nadir dashboard. CCR_NADIR_BASE_URL points the script at a self-hosted Nadir deployment instead; a trailing /v1 is stripped.

See the Decision API for the full contract.

What Nadir is

Nadir is an LLM router. Nadir sends each prompt to the cheapest model that can handle it. A small decision model reads each prompt against your model menu and picks the lowest-cost model it expects to handle it. When the decision model is uncertain or unavailable, the request goes to the strongest model on the menu. The routing step makes no call to your model provider.

Nadir runs two ways. The decision API returns a model, reasoning-effort, cache, context, and policy recommendation without calling a model provider, beside the gateway you already run. That is how a shadow-mode evaluation works, and its projected savings stay advisory. The OpenAI compatible managed proxy executes the route, and migration is a two-line change: point the base URL at api.getnadir.com and set model to auto. On that path an optional verifier can score a complete non-streaming answer and escalate to a stronger model when it misses the configured bar. Streaming bypasses post-generation verification. BYOK is supported on every tier.

For coding agents, Nadir Auto is a terminal launcher for Claude Code or Codex that asks Nadir for the main-session model before each turn, with your configured model as the fallback and cost ceiling. Delegation integrations for Claude Code, Codex, or Cursor instead recommend a model tier for subagent work, and the agent decides; the Claude plugin can also move a main-thread turn to Haiku when Nadir's cache check prices it cheaper, unless its switch_main_model option is off. Either way inference runs on your own provider account, so Nadir holds no provider keys on that path.

What the numbers are, and what they are not

Nadir publishes each evaluation with its scope. On checkable code, run-check-escalate solved 392 of 395 common HumanEval and MBPP problems (99.2%), graded by running the canonical tests; that applies only to tasks with runnable deterministic tests. Nadir-Tumbler posts an arena_score of 72.3 on RouterArena's public scorer, 5th of 23 routers, which measures the routing decision on RouterArena's own model pool. A reference-assisted RouterBench evaluation over 11,420 held-out triples produced a 60% lower projected cost than always-Opus with about 98% retained quality and a 1.7% catastrophic-route rate. That experiment gave the verifier the expensive-model reference answer, which production does not have, so it is a research ceiling and not the deployed path.

None of these is a production guarantee, a universal savings rate, or a forecast for any particular workload. Customer savings are reported from measured execution against a declared baseline, and customer quality only from outcome-labelled traffic. Projected savings and realized savings are separate artifacts and are never blended.

Design-partner program

Three rungs, picked by risk appetite. Rung 0 Shadow runs advisory decision calls alongside live traffic and returns a projected receipt, with nothing in the request path changed. Rung 1 Hosted is the two-line swap on a production slice and returns a realized receipt. Rung 2 On-prem is a supervised six-week proof of concept inside the partner's VPC, where no prompt, response, or usage reaches Nadir. The commitments are the same at every rung. Apply for a rung directly: Rung 0 Shadow, Rung 1 Hosted, or Rung 2 On-prem. Not sure which fits? Start at getnadir.com/contact/?reason=design-partner.

Licensing

NadirClaw is the self-hosted core, source-available under the PolyForm Noncommercial License. Source-available is the correct label; NadirClaw is not open source. Nadir Route's hosted plan has no base fee and charges a variable fee only on measured savings from requests Nadir executed.

Pages on this site

Machine-readable summaries of this site: llms.txt and llms-full.txt.