Appearance
Start a Session on Another Model
A session normally runs on the Claude subscription. With --route openrouter it runs on a model you name, through OpenRouter, paid from the account's prepaid credits and capped by a monthly limit on this machine's own key. Without the flag nothing changes. The full rules are in the Model Routes reference.
Before you start
- The OpenRouter management key is in this machine's keychain as
OPENROUTER_MANAGEMENT_KEY. - This machine's entry in the operator repo's
machines.jsondeclares its limit:"routes": { "openrouter": { "monthly_limit_usd": 15 } }.
1. Mint this machine's key (once)
See what would be created. Nothing is changed.
bash
bob route mint --machine macbook-pro-16You should see: DRY RUN: would create bob-macbook-pro-16 — limit $15.00 monthly.
Broken looks like: declares no OpenRouter limit (the limit is not in machines.json) or no OpenRouter management key on this machine.
Then create it:
bash
bob route mint --machine macbook-pro-16 --applyYou should see: minted bob-macbook-pro-16 — limit $15.00 monthly — stored at keychain:OPENROUTER_API_KEY. The key itself is never printed.
Broken looks like: was created but could not be stored. The key was deleted again; nothing is left to spend. Run the command again.
2. Start a session on the route
bash
claude --route openrouterYou should see, before the session opens: BoB: route openrouter — model anthropic/claude-sonnet-5.5 — key bob-macbook-pro-16 ($0.00 used of $15.00).
To choose the model, add its slug after a colon:
bash
claude --route openrouter:anthropic/claude-haiku-4.5Broken looks like, each one before any session starts:
| Message | Meaning |
|---|---|
lists no model '<slug>' | The slug is not one OpenRouter serves. The message prints the command that lists valid slugs. |
is at its limit | This machine's key has spent its monthly limit. |
is client tenant <id>'s project | A client project is never routed through your account. |
no OpenRouter working key on this machine | Step 1 has not been done here. |
The same flag works for a headless groom:
bash
bob groom --route openrouter3. See what the key has spent
bash
bob route statusYou should see: openrouter: key bob-macbook-pro-16 — $0.04 used of $15.00 (monthly), $14.96 left.
Replace a key
A key's value cannot be read back from OpenRouter. If this machine has lost its key, or you want a new one, delete and mint again in one step:
bash
bob route mint --machine macbook-pro-16 --apply --replaceYou should see: replaced bob-macbook-pro-16.
Keep a headless run going when a model fails
A route pins one model. A role names the kind of model a job needs and lists several, in order. When the first fails with a model failure — the usage limit, a 429, an overloaded API, a retired model — the job is started again on the next. A failing test or a GitHub rate limit is not a model failure and never moves a run. The rules are in Roles and failover.
See the roles and their order:
bash
bob route rolesYou should see each role with its alias and candidates, starting with default (alias sonnet):, then 1. subscription sonnet, then 2. openrouter anthropic/claude-sonnet-5.5.
Run a headless groom on a role:
bash
bob groom --role defaultYou should see bob groom: role default first. The verdict line ends — role default on subscription sonnet. When it failed over, it ends with (fallback: see bob route failovers) and a BoB: failover — … line names what failed and why.
Broken looks like: --role default refused (an unknown role, or scripts/route/routing.json does not load), or every model failed over (every candidate failed: see the next command).
See what failed over on this machine:
bash
bob route failoversTest failover without an outage
Mark the subscription down for one command. Nothing is sent to it:
bash
BOB_ROUTING_DOWN=subscription bob route run --role default -- claude -p "say ok"You should see this line, then the answer from OpenRouter:
BoB: failover — role default: subscription sonnet failed (simulated: BOB_ROUTING_DOWN=subscription) — trying openrouter anthropic/claude-sonnet-5.5 (candidate 2 of 2)This spends a few cents of this machine's OpenRouter limit.
Broken looks like: route_refused: no OpenRouter working key (step 1 has not been done on this machine) or is at its limit.
To test without spending anything, mark both routes down. Nothing runs and nothing is spent:
bash
BOB_ROUTING_DOWN=subscription,openrouter bob route run --role default -- claude -p "say ok"; echo "exit=$?"You should see two failover lines, then every candidate failed over, then exit=3.
To switch a provider off for one run, use BOB_ROUTING_DISABLE=openrouter. To switch it off for good, set "enabled": false on its route in scripts/route/routing.json.