xcb
Install xcb
Theme
Appearance

Start here

How routing works

How xcb picks an account and model for each task: which accounts can take it, how models are ranked, and why the account stays held until the provider exits.

Every task goes through the same four steps, whether you type it in the thread, run xcb run, or send it with xcb --json route: xcb filters your accounts, ranks the models they offer, holds the chosen account while the provider works, and records how the run ended.

1. Find the accounts that can take the task

An account can take a task when all of these are true:

  • Its provider build is one xcb supports (see supported builds).
  • It is signed in and enabled. An account whose sign-in failed stays out until you sign in again.
  • It is idle: no other task is using it.
  • It is not at a known usage limit. When Claude reports 100% use of its five-hour or seven-day window, xcb skips that account until the reset the provider reported. Unknown usage stays unknown and does not block the account.
  • The model was seen recently in the provider’s model list.

Your constraints narrow the list first. A prompt that starts with Use Claude, Use Codex, or Use Devin requires that provider, and xcb run --account or a pinned provider, account, or model in a route request does the same. xcb never falls back outside a constraint.

2. Rank the models

xcb gives each model relative quality, cost, and latency scores and sorts the models into tiers: a model is in the first tier when no other model beats it on all three at once. It then scores the tiers for routine, balanced, or complex work.

The kind of task comes from the route reflex, a small classifier that learns from the model tiers you ask for. If you turn on the optional judge, its answers feed the same classifier. A prompt of at least 400 words or 8 KiB always gets the highest-quality model available, whatever its price. Remaining usage, your favorites in config.json, and the provider you usually pick for that project break ties.

The scores are heuristics, not measured quality or prices. When a usage limit rules out a stronger model, the chosen route says so.

3. Hold the account

Before the provider starts, xcb holds the account so no other task can use it. Each account runs one provider turn at a time, and tasks in the same project folder, or in a folder inside it, take turns. Tasks in different folders on different accounts run at the same time.

The provider runs in an operating-system sandbox: Seatbelt on macOS, bwrap on Linux. It gets xcb’s file tools for the task’s folder, no shell of its own, and network access to port 443 only. See security and privacy for what that covers.

4. Record how the run ended

When the provider process exits, xcb records the result: completed, needs your input, failed, or cancelled. If it can’t confirm that the provider stopped or what it changed, it records the run as uncertain, keeps the account held, and does not retry. xcb recover shows those runs; see troubleshooting.

In the thread, a turn that stops at a usage limit continues on another route the task hasn’t tried yet, and a turn cut off by a turn or token limit can continue on its own (up to three times in a row within ten minutes by default). An uncertain run never moves to another account. xcb --json route runs exactly one turn and leaves retries to the caller.

Preview a decision

xcb models route --task "fix a race in the scheduler"   # the route xcb would pick here, now
xcb models tiers --task "fix a race in the scheduler"   # every model's tier and scores

Neither command holds an account, and the choice can change before a task runs. A route request with "dryRun": true reports the same decision as JSON.

The TypeScript SDK does not rank or choose: your app names the account and model, and the SDK holds that account while the task runs. See TypeScript SDK.