xcb --json route is the machine contract for another program — typically a coding agent — to hand XCB one task and get back one settled, routed turn. For bounded tool-free text generation instead, see the application API.The route contract
Write one UTF-8 JSON document to stdin, close stdin, and read a bounded JSON document from stdout. Unknown fields are rejected; every field except version, workspace, and task is optional.
$ xcb --json route
{
"version": 1,
"workspace": "/absolute/path/to/project",
"task": "Fix the failing parser test and show the diff",
"provider": "claude", // optional pin
"account": "<account-id>", // optional pin
"model": "claude/sonnet/low", // optional pin, exact observed key
"timeoutMs": 1800000, // optional caller deadline
"dryRun": false // true selects a route without running
}provider, account, and model are eligibility constraints, not fallbacks. A provider that disagrees with the pinned account's provider is rejected. With no pins, XCB selects among admitted runtimes, credentialed enabled accounts that are idle and outside known quota windows, and observed fresh model entries — ranked by task class and relative quality, cost, and latency Pareto tiers, with an optional judge ordering only already-eligible routes.
A completed call returns status: "completed" only for a completed, joined, settled turn with no pending attention, and includes the selected route, the saved session id (reopen with xcb resume), the recorded outcome facts, and bounded text.
Failure codes
Failures exit nonzero with a closed object: invalid_request, unavailable (no eligible route, unknown account or model), busy (account custody held by live work), deadline (the caller's timeoutMs expired), cancelled, provider_error (including quota failures — outcome.failure carries the exact detail), custody_unproven (process exit could not be proven; do not retry blindly), and needs_input (the provider stopped with a question — text carries it, and the saved session can be resumed by a person).
When a request provably launched no provider process, the failure carries joined: true and effects: "none". SIGINT and SIGTERM request the same bounded cancellation and settlement path as timeoutMs; killing XCB does not prove the provider stopped.
Embedding with the SDK
The TypeScript compatibility source exports createSubscriptionRouter, which bundles an account lease store and qualified task adapters into one object. It is a source build — no @hraness/xcb package is published — and there is no bundled live adapter; the host supplies adapters and qualification evidence.
import { openAccountDatabase, SqliteAccountLeases, createSubscriptionRouter } from "@hraness/xcb";
const db = await openAccountDatabase("/private/path/to/router.sqlite");
const router = createSubscriptionRouter({
leases: new SqliteAccountLeases(db),
adapters: [claudeTaskAdapter],
});
const result = await router.run({
provider: "claude",
accountId: "a_…",
profile: { id: profile.id, version: profile.version, digest: profile.digest },
model: { id: "claude-sonnet-5", reasoningEffort: "low", serviceTier: null },
purpose: "respond",
prompt: "Summarize the diff in this workspace.",
limits: { maxRunMs: 60_000, maxCleanupMs: 10_000, maxOutputBytes: 65_536 },
}, broker);router.routes() lists the adapter-registered routes a caller can dispatch to — registration is not eligibility. router.run(request, broker) accepts provider-plus-authentication shorthand when exactly one adapter matches, defaults runId/workspaceId to the broker's binding, and still performs every admission, lease, deadline, and stop-evidence check.
For the complete schema, custody semantics, and selection rules, read the route contract and quota routing references in the repository.