CLI
Routeplane ships as one static binary, routeplane, with no dependencies to install. It runs the local router your agent talks to, and gives you a scriptable command-line surface to control it.
The local endpoint
Section titled “The local endpoint”Your agent never talks to a remote API directly. It points at the binary running locally, by default on http://127.0.0.1:4356. Everything else in these docs (the four model protocols, the MCP and ACP gateways) is served from that one endpoint.
You run it as a daemon and control its lifecycle:
routeplane serve: run the router in the foreground.routeplane start/stop/restart/status. Manage it as a background daemon.routeplane reload: hot-reload the config and routing table without a restart.
Everyday commands
Section titled “Everyday commands”routeplane init # scaffold ./routeplane.yamlrouteplane providers list # every configured provider + auth statusrouteplane providers login <provider> # interactive credential setup (OAuth device-code or key)routeplane providers logout <provider> # clear stored credentialsrouteplane models # list routable modelsrouteplane route <model> # resolve a model through the routing tablerouteplane status # daemon identity, config health, serving evidencerouteplane observe status # OTel exporter stateEvery command accepts --json (the default; agent-native) or --human for a readable rendering.
Also in the binary: routeplane config (config validation against the published schema), routeplane doctor (loud pre-boot preflight of config + environment — the first failing check names itself and exits non-zero), routeplane key (virtual-key management), routeplane policy, routeplane tools (MCP server introspection), routeplane agents / agent-proxy (ACP), routeplane spawn (launch a coding-agent harness pointed at the local daemon), routeplane skills, routeplane mcp, routeplane catalog (local provider-catalog snapshots), routeplane model-directory (evidence-scoped model export), and routeplane verify (TEE attestation for confidential models). Run any of them with --help for details.
Answer “what happened” from the insight log
Section titled “Answer “what happened” from the insight log”Three commands read the on-disk insight log directly — no daemon needed:
routeplane insight --since 24h # which upstream served what, success rate, latencyrouteplane explain <request-id> # one request's dialled-hop timeline + terminal verdictrouteplane budget --human # settle declared allowance windows against real spendexplain takes the pipeline request id stamped on insight lines and reconstructs why that
request went where it did. budget settles operator-declared windows (budget: in
routeplane.yaml) against recorded traffic — observe-only, and honest about its limits: an
unmeasured window renders UNMEASURED, a window whose declaration cannot settle renders its
own ERROR row instead of hiding the rest, and a refusal (402/429) observed in a window marks
it exhausted only until a later success proves the seat serves again.
Inspect and reset routing breakers
Section titled “Inspect and reset routing breakers”When a provider trips a routing-influence breaker (credit exhaustion, rate limits, 5xx streaks),
breakers status shows which seats and models are cooling and for how long — read-only,
inspecting never changes routing. After fixing one seat (topping up one subscription, say),
clear just that seat instead of losing every other cooldown:
routeplane breakers status --humanrouteplane breakers reset --provider <id> --account <label> # one seatrouteplane breakers reset --model <model-id> # one model's streaksrouteplane breakers reset # everythingRead daemon status without guessing
Section titled “Read daemon status without guessing”routeplane status reports more than process liveness. Its JSON output includes:
| Field | How to read it |
|---|---|
degraded |
false means no provider was disabled over an unresolved environment variable; true names disabled providers in providers_disabled; null means the daemon cannot answer, not that it is healthy. |
binary_replaced |
true means the executable on disk changed after this process started, so the daemon is serving old code; false means it is still running the binary it started with; null is unknown. |
last_upstream_success_secs_ago |
Seconds since the last successful upstream response, derived from Insight. null means there is no readable success evidence. |
last_upstream_attempt_secs_ago |
Seconds since the last recorded upstream attempt. Read it beside the success age: an old success on an idle daemon is normal, while an old success beside a recent attempt points to a serving failure. null means there is no recorded upstream attempt or the daemon could not provide the field. |
upstream_failures_since_success |
Failed attempts recorded after the latest success. 0 means none were recorded after that success only when last_upstream_success_secs_ago is present; an empty log can also report 0. null means the daemon could not provide the field. |
These serving fields are observations from real traffic, not synthetic health probes. Use
--human for the operator summary; use the default JSON when a script needs the tri-state values.
Operational reports
Section titled “Operational reports”report spend reads the local metering database and groups estimated charges by provider, model,
or virtual-key id:
routeplane report spend --since 24h --by provider --humanrouteplane report spend --since 7d --by modelrouteplane report spend --db sqlite:///var/lib/routeplane/routeplane.db --by keyThe default grouping is provider. --since accepts windows such as 30m, 24h, and 7d;
--config locates the configured database, while --db overrides it. The charges are estimates
from configured prices and recorded token counts, not provider invoices. Subscription traffic is
reported as zero marginal cost; a metered request with missing pricing is reported separately as
pricing unknown.
Virtual keys
Section titled “Virtual keys”Routeplane’s database-backed virtual keys can be inspected and revoked without restarting the daemon:
routeplane key list --humanrouteplane key revoke brvk_id_0123456789abcdefkey list shows key ids and whether each key is active, but never prints the stored hash or the
one-time plaintext secret. Pass the brvk_id_... id from that list to key revoke, not the
brvk_... secret. Revocation takes effect on the next request and reports one of revoked,
already_revoked, or not_found rather than treating a mistyped id as success. Use key sign
to mint a new key; it prints the plaintext once.
Launch a coding harness without editing its config
Section titled “Launch a coding harness without editing its config”routeplane spawn launches Claude Code, Codex, Kimi, OpenCode, or Grok with routing injected into
the child process. It does not write the harness’s normal config files. Everything after -- is
forwarded to that harness:
routeplane spawn -a claude -- -p "summarize this repository"routeplane spawn -a grok -m openai/gpt-5.4 -- -p "review this diff"Grok, Codex, Kimi, and OpenCode require -m provider/model; Claude may use its configured default.
For Grok, Routeplane sets the local proxy, disables feedback, and uses a temporary isolated
GROK_HOME so a warm model cache cannot bypass the router. The temporary home is removed when the
child exits, and Routeplane does not write ~/.grok/config.toml. Use --no-start to refuse daemon
auto-start and --no-install to fail with the official install command when a harness is missing.
There is no Routeplane Cloud
Section titled “There is no Routeplane Cloud”There is no Routeplane Cloud. The cloud surface was removed from the binary,
routeplane cloud is not a command, and no hosted service is planned. The local
binary is the whole product surface.