cyberine
Providers

Command Code (CLI + Provider API)

Reference for Command Code (commandcode.ai): the cmd coding CLI and its OpenAI-compatible Provider API. Read this before any Command Code adapter, headroom or fleet work.

Every claim carries a tag. VERIFIED means measured on the developer machine on 2026-09-17 against a live individual GOAT subscription with CLI v1.54.2, unless the line names a later date. DOCS means vendor documentation or the shipped bundle, not exercised live. Where the two disagree, the measurement wins and the disagreement is recorded under Documented disagreements. The 2026-09-19 re-check of a second session's findings is its own section, 2026-09-19 re-verification.

No account state lives in this file: no key, no user name, no subscription id, no balance. The key is stored by the CLI in ~/.commandcode/auth.json (mode 0600) and mirrored into the repo's gitignored .env as CMD_API_KEY.

Official docs: https://commandcode.ai/docs, Provider API: https://commandcode.ai/docs/provider-api, changelog: https://commandcode.ai/changelog.

Two integration seams

SeamWireCyberine shapeStatus
Provider APIOpenAI Chat Completions at https://api.commandcode.ai/provider/v1LoopAgentAdapter (loop-commandcode-build)shipped 2026-09-17 (kd5f6)
cmd CLIheadless NDJSON (cmd -p --output-format json)CliAgentAdapter factory makeCommandCodeAdapter (command-code)surface VERIFIED; worker built 2026-09-17 after the km3ga bake-off (kd823), verified offline only

One account is one credit pool shared by both seams. A CLI worker and a loop worker draw on the same rolling windows.

Plans and entitlement

  • VERIFIED: the GOAT plan (planId: individual-goat) has Provider API access. Every endpoint below answered on it.
  • DOCS: every plan except Go has API access; a Go plan calling the API gets 403 upgrade_required.
  • VERIFIED: Anthropic models are NOT on GOAT. Calling one returns a permission_error with a MODEL_NOT_IN_PLAN: message (DOCS: Pro and above, or extra on-demand usage).
  • VERIFIED: GOAT caps are 14 credits per rolling 5 hours, 35 per rolling week, and a monthly pool of 70. The caps read back from the billing endpoint match the docs exactly.

Provider API

Endpoints and auth

EndpointShapeTag
POST /provider/v1/chat/completionsOpenAI Chat CompletionsVERIFIED
POST /provider/v1/messagesAnthropic MessagesVERIFIED (reachable; its models are off-plan on GOAT)
GET /provider/v1/models{id, object, created, owned_by, name, context_length} entriesVERIFIED
  • VERIFIED: Authorization: Bearer with the account key. x-api-key is also accepted on /messages.
  • VERIFIED: the same key authenticates the CLI and the API.
  • VERIFIED: responses carry x-trace-id on every call and are served through Cloudflare. They carry NO x-ratelimit-* headers and NO cost headers, so headroom must be polled or parsed out of a refusal.
  • VERIFIED: /provider/v1/usage, /credits, /me, /account, /key and /limits all return 404. The documented API has no billing surface.

Tool calling

  • VERIFIED: a tools + tool_choice: "auto" request to /chat/completions on a free model returned finish_reason: "tool_calls" with a well-formed message.tool_calls[] (id, type: "function", function.name, function.arguments as a JSON string). LoopAgentAdapter can run against this endpoint.
  • VERIFIED: non-standard extras appear in the payload and are tolerated by the openai SDK: choices[].delta: null on a NON-streaming reply, matched_stop, lastOne, and message.reasoning_content carrying the chain of thought.
  • VERIFIED 2026-09-17 through loop-commandcode-build: streaming (stream: true with stream_options.include_usage) and full multi-turn tool loops to completion. A one-file implement-task run on deepseek/deepseek-v4-flash finished all three steps (design, implement, review) with 965,446 input and 13,655 output tokens, 87-93% of input served from cache, and drew 0.0326 credits.
  • NOT TESTED: images (DOCS: accepted; audio, file and document parts are rejected by the schema).

Usage and cache accounting

  • VERIFIED: /chat/completions usage carries prompt_tokens_details.cached_tokens and cache_creation_input_tokens, so the cache-hit rate is measurable per request.

Error envelopes

CaseStatusBodyTag
Anthropic model on GOATerror{"type":"error","error":{"type":"permission_error","message":"MODEL_NOT_IN_PLAN: ..."}}VERIFIED
Claude id sent to /chat/completions400invalid_request_error, code: "unsupported_model", message says it must be called via /provider/v1/messagesVERIFIED
Unknown model id400invalid_request_error, code: "unsupported_model", message Model "..." is not supported on this endpoint.VERIFIED
Unregistered route404{"success":false,"status":404,"message":"404 Not found...","cause":"... is not a registered API route"}VERIFIED
Go plan calling the API403upgrade_requiredDOCS
Zero data retention with no ZDR upstream422cmd_zdr_no_providersDOCS
Usage window exhausted429RATE_LIMITED plus a rateLimit object (below)DOCS (read from the CLI bundle, never provoked live)

Classification rules an adapter must follow:

  • MODEL_NOT_IN_PLAN is a PERMISSION error, not a billing error. Treat the worker as unavailable for the whole run and never retry it.
  • unsupported_model means a wrong endpoint for the id (a claude-* id belongs on /messages) or an unknown id. Not retryable.
  • A 429 is a window exhaustion that reopens at a fixed timestamp named in the payload. Park until then; blind backoff wastes the interval.

The 429 payload

DOCS (from the CLI's own handler in its shipped bundle, not provoked live). The CLI keys on code === "RATE_LIMITED" or status 429 and then reads:

  • The bundle reads the fields below off the response body's error object (error.rateLimit), and the code from the transport error or error.code. Cyberine also accepts a top-level rateLimit by rewrapping such a body under error.
  • rateLimit.window: "fiveHour" or "weekly"; the bundle also recognises "daily".
  • rateLimit.reset: epoch SECONDS (the CLI multiplies it by 1000).
  • rateLimit.model: optional, present when the limit is per model (the CLI then says "today's limit on ").
  • When the object is missing it falls back to the human message: /usage limit for your plan/i names the window (weekly when the text says so, otherwise the 5-hour one), and resets at <ISO timestamp> gives the reset.

Undocumented /alpha billing endpoints

VERIFIED live, but found in the CLI bundle rather than in the docs. The /alpha prefix marks them unstable: every caller must degrade to headroom-unknown on a 404 or a shape change, never crash.

EndpointReturns
GET https://api.commandcode.ai/alpha/billing/creditscredits.{monthlyCredits, purchasedCredits, freeCredits, belowThreshold, creditThreshold} and windowLimits.{limited, exceeded, fiveHour, weekly}, each window {used, cap, exceeded, resetAt}
GET https://api.commandcode.ai/alpha/usage/summarytotalCount, totalCost, averageCost, successRate, completedCount, failedCount, totalTokensIn, totalTokensOut, totalTokens, totalCredits, totalFreeCredits, totalMonthlyCredits, totalPurchasedCredits, periodBasis
GET https://api.commandcode.ai/alpha/billing/subscriptionsstatus, planId, currentPeriodStart, currentPeriodEnd, cancelAtPeriodEnd, quantity, orgId, pendingPhase
  • VERIFIED: credits.monthlyCredits is REMAINING and counts DOWN from the pool; it moves at roughly 1e-10 precision, which makes per-run credit deltas exact.
  • VERIFIED: resetAt on the billing endpoint is epoch MILLISECONDS. UNIT TRAP: the 429 body's rateLimit.reset is SECONDS.

Cost model

  • VERIFIED on meituan/LongCat-2.0:free: a free model costs exactly zero credits. A full headless CLI run on it (51,610 input tokens, one tool call) left monthlyCredits and fiveHour.used byte-identical before and after.
  • VERIFIED 2026-09-17 (kp1nc) on all three free models through loop-commandcode-build: FLEET-BENCH batches of about 454,000, 765,000 and 661,000 input tokens left monthlyCredits and fiveHour.used byte-identical.
  • VERIFIED 2026-09-17 (kp1nc): the free daily cap is per model per account and is not specific to Ling. meituan/LongCat-2.0:free answered HTTP 429 with {"error":{"message":"You've used all 100 free LongCat 2.0 requests for today. Your quota resets at 2026-09-17T00:00:00.000Z. Run /model or -m to pick another model.","type":"rate_limit_error","code":"RATE_LIMITED"}}: no rateLimit object and no rate-limit headers, the reset only in the message text.
  • VERIFIED 2026-09-17 (kp1nc): poolside/laguna-s-2.1-free answered 429 Upstream model provider is temporarily unavailable. Please try again in a moment. on every request for stretches of more than ten minutes, with no reset time. Treat it as capacity, not quota.
  • DOCS: free models keep working after a paid window closes; inclusionai/ling-3.0-flash-sante:free is capped at about 100 requests a day; all free models are offered while capacity lasts.
  • Derived from the VERIFIED caps: on paid models the binding constraint for parallel work is the 14-credit rolling 5-hour window, shared by every worker on the account.
  • NOT TESTED: any concurrency or requests-per-minute ceiling (none documented, no header), and behaviour at an exhausted window.

Model catalog

The catalog rotates (deals carry expiry dates), so no model table is kept here. The live sources are GET /provider/v1/models and cmd --list-models.

Stable facts:

  • VERIFIED: the API lists 69 models and the CLI lists 70 on the same day. VERIFIED 2026-09-19: the API lists 71.
  • VERIFIED 2026-09-17: three models were free: meituan/LongCat-2.0:free, poolside/laguna-s-2.1-free, inclusionai/ling-3.0-flash-sante:free.
  • VERIFIED 2026-09-25 (kz9mk): DeepSeek's 2026-09-10 update retired V4 Flash upstream and only temporarily routes the legacy name deepseek-v4-flash to V4.1 Flash. Command Code lists deepseek/deepseek-v4.1-flash in both GET /provider/v1/models (81 models that day) and command-code --list-models (1.58.1), so CMD_MODEL and CYBERINE_COMMANDCODE_MODEL now default to it. deepseek/deepseek-v4-flash is still listed and still accepted when set explicitly.
  • VERIFIED 2026-09-19: the LongCat free tier is retired. The catalog lists only the paid meituan/LongCat-2.0, and a run on the :free id exits 4 with a result line whose error reads 403 The free LongCat 2.0 tier has been retired. LongCat 2.0 is now a paid model. Two free ids remain: poolside/laguna-s-2.1-free and inclusionai/ling-3.0-flash-sante:free. The CLI bundle's own model list still marks the retired id free, so it is stale for free-tier status; the free lane reads the live catalog and is unaffected.
  • VERIFIED: GOAT covers the open-model catalog (DeepSeek, Kimi, GLM, MiniMax, MiMo, Qwen and others) but no Anthropic model.
  • VERIFIED: ids are case-insensitive on input; the API echoes the canonical mixed-case id. Store the canonical form.
  • VERIFIED: the CLI also resolves a short name after the last / (cmd --model kimi-k2.5).

cmd CLI

Install and identity

  • VERIFIED: npm i -g command-code installs cmd, cmdc, command-code and commandcode, all pointing at one entry. Requires Node 22 or newer (engines.node).
  • VERIFIED: the package is licensed UNLICENSED (not open source as of 2026-09-17).
  • VERIFIED: the CLI self-updates by default; --no-auto-update disables that for one run. An orchestrated worker should always pass it.
  • VERIFIED 2026-09-19: the gate is shouldRunAutoUpdate: !skipCommands.has(cmd) && !args.includes("--no-auto-update") in the v1.54.2 bundle, so any invocation without the flag may start the background updater. It installs through whichever npm is first on PATH: on this machine it put 1.58.0 under /opt/homebrew/lib/node_modules/command-code with no bin links while the nvm copy on PATH stayed 1.54.2. With the flag, updates.json was left untouched across every probe, but each run still emits a notice event update available: v1.58.0 (installing in the background ...) read from the pending state, which is misleading: nothing installs.

Flags an adapter needs

FlagMeaningTag
-p, --print [query]non-interactive, exits after the answer. The value is optional, so a query in the next argv entry that starts with - is parsed as an option: -p "- say ok" exits 1 with No query provided, while --print=- say ok answers (VERIFIED 2026-09-17 on a free model). An adapter passes --print=<query>VERIFIED
--output-format text|jsonjson is an NDJSON event stream plus one final result lineVERIFIED
--max-turns <n>default 100; hitting the cap exits 8flag VERIFIED, exit code DOCS
-m, --model <model>full id or short nameVERIFIED
--skip-onboardingskips taste onboarding; required for automated runsVERIFIED
--permission-mode <m>default, standard, plan, auto-accept, dont-askdont-ask VERIFIED accepted (see disagreement 4); the rest DOCS
--yolobypass mode, alias --dangerously-skip-permissionsVERIFIED (km3ga bake-off: the only way a print-mode run writes files)
-t, --trustskips the first-run project trust promptVERIFIED accepted
-w, --worktree [name]runs inside a CLI-managed worktreeDOCS
--no-sessionin-memory only, nothing persistedVERIFIED accepted
--local-onlyBYOK only, no Command Code traffic (same as CMD_LOCAL_ONLY=1)DOCS
--list-modelsprints the catalogVERIFIED
--verboseprints session: <id> on stderrVERIFIED

Headless output

  • VERIFIED: a run emits NDJSON on stdout. Event types seen: run_start, turn_start, message_start, model_request_start, model_trace, thinking_start, thinking_delta, thinking_end, message_update, model_request_end, message_end, tool_queued, tool_running, tool_completed, turn_end, text_delta, run_end.
  • VERIFIED: the final line has keys type, subtype, sessionId, stopReason, usage, durationMs, finalText, with type: "result" and subtype: "success" on a clean run.
  • VERIFIED: usage is NOT the OpenAI shape. It is {inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens}. There is no cost field; cost comes from the billing endpoint.
  • DOCS: subtype, usage, durationMs and finalText are always present; sessionId and stopReason are OPTIONAL and absent on an early failure (auth, bad input). Ignore unknown type values; the event list grows.
  • VERIFIED 2026-09-17 offline (the real binary inside Cyberine's Seatbelt profile with the network denied, so nothing reached the service): every line before the result is a wrapper {"type":"event","event":{"type":"<name>",...}}, so the event names above are the INNER event.type. api_retry, run_error and run_end also appear. A failed run's result line is {"type":"result","subtype":"error",...,"finalText":"","error":"Error: ..."} and carries sessionId only when the harness had started: the no-credential run had none, the connection-refused run had one.
  • DOCS (read from the v1.54.2 bundle, classifyPrintModeError and classifyPrintOutcome): the result line's subtype is success, max_turns or error, and on a failure it adds an error string. The exit codes are 0 ok, 1 general error, 3 auth, 4 permission denied (including a spend cap), 5 rate limited (a usage window: the message names the window and says Resets in <duration>, with no ISO timestamp), 6 connection error, 7 server error, 8 max turns (subtype max_turns, usage kept), 9 no final text (subtype success), 10 insufficient credits, 130 interrupted.
  • VERIFIED 2026-09-17 offline: exit 3 with no credential (Error: Not authenticated. Please run "cmd login" first., no sessionId, zero usage, under a second) and exit 6 with a placeholder key and the network denied (seven api_retry events, then the result line). 0, 3 and 6 are the observed codes; the rest are the bundle's table.
  • VERIFIED: the system prompt plus repo context is large. A trivial read-only task consumed 51,610 input tokens, 16,000 of them cache reads.

Permission modes

DOCS. Rules live under permissions in settings.json as deny, ask and allow lists, checked in that order, with Claude-Code-shaped matchers such as Edit(src/**).

ModeReadsWritesShell
defaultfreepromptprompt
auto-acceptfreeallowedsafe filesystem commands only
planfreeblocked except a plan fileread-only
bypass (--yolo)freeallowedallowed
dont-askfreeallowlist onlyallowlist only

For an orchestrated worker, dont-ask with an allowlist is fail-closed (a call outside the list is denied instead of hanging on a prompt), while --yolo is fail-open. deny wins in every mode, ask denies under dont-ask, and ask_user_question, agent and run_command skip the lists.

VERIFIED 2026-09-17 on v1.54.2: in headless -p mode none of this unlocks writes. With --permission-mode dont-ask and a project .commandcode/settings.json allowing Edit(**), Write(**) and Bash(**), a write is still refused with Tool "write_file" requires permissions. Use --yolo (or --dangerously-skip-permissions) to enable file writes and shell commands in print mode. Only --yolo lets a print-mode run edit files or run shell commands, and --yolo has no path confinement (a bake-off run reached git outside its assigned worktree). The refused run still exits 0 with subtype: "success", and the model may claim it wrote the file, so a worker must judge the diff, never the result line. An orchestrated CLI worker therefore runs --yolo inside Cyberine's host sandbox.

Files and isolation

  • DOCS: user state lives under ~/.commandcode/ (auth.json, config.json, settings.json, providers.json, mcp.json, projects/, worktrees/, plans/). Project state lives under .commandcode/ (settings.json to commit, settings.local.json to ignore, agents/, skills/, taste/), plus AGENTS.md as project memory and .mcp.json.
  • VERIFIED: auth.json holds the key in plaintext at mode 0600.
  • DOCS: CLI-managed worktrees live OUTSIDE the repo at ~/.commandcode/worktrees/, on branch worktree-<name>. A .worktreeinclude file (gitignore syntax) copies untracked files such as .env into them.
  • VERIFIED 2026-09-17 on this machine and offline: a headless run with --no-session still writes ~/.commandcode/projects/<slug>/<sessionId>.meta.json and .checkpoints.jsonl (the slug is the lowercased, dash-joined cwd), and a run that edits files writes backups under ~/.commandcode/file-history/<sessionId>/. The bundle also writes updates.json, update.lock, telemetry-install-id, sessions/hooks-audit-*.jsonl and a scratchpad under /tmp/commandcode-<uid>/.
  • DOCS (bundle): ~/.commandcode/projects/<slug>/mcp.json is the LOCAL MCP scope, the highest-precedence one, and ~/.commandcode/mods/*.ts are code the CLI loads. A process that can write either controls what the operator's next interactive session executes.
  • DOCS (bundle, getCommandAuthKey): the CLI reads its key from COMMAND_CODE_API_KEY first and falls back to auth.json's apiKey. It never reads CMD_API_KEY; that name is Cyberine's own for the Provider API.
  • Integration rule: isolation has exactly one owner. A Cyberine CLI worker runs inside the worktree src/engine/worktreeSandbox.ts created and never passes -w.

Environment variables

DOCS (docs plus the shipped bundle): CMD_ZDR=1 (zero data retention), CMD_LOCAL_ONLY=1 (BYOK only, disables telemetry, billing checks and the catalog), DO_NOT_TRACK=1 (telemetry off), CMD_TOOLS_<TOOL>_ENABLE=true and CMD_TOOLS_ALL_ENABLE=true (re-enable tools a headless run withholds).

BYOK

DOCS. ~/.commandcode/providers.json points the CLI at our own OpenAI-compatible or Anthropic Messages endpoints, with the key referenced as $ENV_VAR or {env:VAR} rather than pasted. Requests then go straight to that endpoint, and --local-only removes all Command Code backend contact. BYOK models are outside the catalog, so context-window and cost metadata must be supplied in the config. The zero-credit claim is unverified; kjrrv measures it.

Documented disagreements

  1. Model-id casing. VERIFIED: cmd --list-models prints ids in lowercase (minimaxai/minimax-m3), while GET /provider/v1/models returns canonical mixed case (MiniMaxAI/MiniMax-M3). The API accepts both on input and echoes the canonical form, so an adapter may send either but should store the canonical one.
  2. GOAT API access. The launch blog said the Provider API needs "Pro plan or higher"; the docs said every plan except Go. VERIFIED on 2026-09-17: the docs were right, GOAT has API access.
  3. Model count. VERIFIED: 70 models from the CLI versus 69 from the API on the same day. Treat the API list as the dispatchable set.
  4. dont-ask permission mode. cmd --help lists only standard, plan, auto-accept for --permission-mode, while the docs and the shipped bundle implement dont-ask (the bundle's own description: never prompts, anything that would need approval is denied instead). VERIFIED on 2026-09-17: cmd -p ... --permission-mode dont-ask is accepted and exits 0 with subtype: "success", so the help text is stale as a list of valid modes. But accepted is not effective: in print mode an allowlist under dont-ask does not unlock writes (see Permission modes).

2026-09-19 re-verification

A second session (building a private command-code wrapper) measured eight facts on v1.54.2 on 2026-09-19. Each was re-run here the same day before it entered this file, on free models only or with a throwaway HOME and no credential, so the check drew zero credits.

FindingVerdictEvidence hereConsequence for Cyberine
The LongCat free tier is retiredVERIFIEDcatalog lists only meituan/LongCat-2.0 (paid); -m meituan/LongCat-2.0:free exits 4 with 403 ... tier has been retired in the result lineThe free lane reads the live catalog, so it already skips the id. Exit 4 now classifies as a named permission refusal instead of the generic failure. USAGE.md examples moved to live free ids
--effort persists into ~/.commandcode/config.json through an atomic config.json.tmp-*VERIFIEDwith a throwaway HOME, --effort high -m deepseek/deepseek-v4-flash wrote {"reasoningEffort":{"deepseek/deepseek-v4-flash":"high"}} although the run then exited 3 (no credential); -m alone wrote nothingThe worker never passes --effort: under its Seatbelt profile (config.json not writable) a network-denied --effort run exits 1 with no result line and empty stderr, where the same run without it reaches exit 6. The smoke now asserts the argv carries neither --effort nor --config. The operator's own reasoningEffort in config.json is read on every call, so a worker inherits it
First run on a fresh HOME writes config.json ({"installed": true})VERIFIED (new)a print run on a fresh HOME created config.json with that keyHarmless for the worker: under the Seatbelt profile the write is denied, the bundle's markAsInstalled catches it, and the free-model run answered OK with exit 0 and empty stderr. No grant added
Billing posts 1.5 to 4 s after the CLI exitsNOT RE-MEASURED (needs a paid run)the probe would draw credits; left as the other session's measurementNo per-run credit delta is computed anywhere: a run's costUsd is estimated from tokens, and headroom is read only BEFORE a run (commandCodeRunGate, 60 s cache). A read within seconds of another run can miss that run's charge, which the window gate tolerates because it acts only on a closed window, and a 429 closes it regardless
A write without --yolo produces tool_hook_blockedDISPUTEDa free-model run asked to write a file emitted tool_queued then tool_denied (no hookOutput), run_end.result.stopReason and the result line's stopReason were permission_denied, subtype stayed success, exit 0, no file. tool_hook_blocked exists in the bundle as the pre-tool-hook block path, so it can appear under a user hook configNone: the worker always passes --yolo. stopReason: "permission_denied" is the machine-readable sign of a refused write if that ever changes
SIGTERM exits 130VERIFIEDkill -TERM five seconds into a run: exit 130, stderr Terminated., NO result line (stdout ends mid-stream)Already classified as interrupted with no cooldown; the smoke now covers the no-result-line shape
The self-updater runs on any call without --no-auto-updateVERIFIEDbundle gate quoted under Install and identity; updates.json mtime unchanged across flagged runsThe worker passes the flag and checkCommandCode reads auth.json without spawning, so nothing in Cyberine triggers the updater. update-status is not in the writable set and needs no grant while the flag is passed
CLAUDE.md is never loadedVERIFIEDcanary runs: a repo with only CLAUDE.md answered NONE, a repo with only AGENTS.md answered its canary wordThe CLI worker gets no repo instructions in a CLAUDE.md-only repo, because Cyberine injects instruction files only into LoopAgentAdapter prompts. Filed as kx3gg rather than fixed here: the same gap applies to every CLI that reads only AGENTS.md
The operator's MCP servers and mods DO load in a worker runVERIFIED (2026-09-21, v1.58.0)canary in a throwaway HOME: ~/.commandcode/mcp.json declaring a stdio server that touches a marker, and ~/.commandcode/mods/canary.mjs that touches another, with the marker path under /tmp so the sandbox's write policy cannot mask the result. A -p run carrying the worker's exact flags (--skip-onboarding --no-auto-update --no-session --no-skills -t --yolo, free model poolside/laguna-s-2.1-free) started the MCP server AND loaded the mod. Under the worker's generated Seatbelt profile WITHOUT the new deny-read rules (positive control) both still loaded, so the sandbox alone did not close it; with the rules, neither loaded and the run still answered ok at exit 0, which is also the proof auth.json stayed readableClosed for sandboxed runs (kj3g0): seatbeltProfile.ts now denies READ on mcp.json and mods/ inside every known CLI config dir, emitted AFTER the own-config re-allow so last-match-wins keeps auth.json, sessions and settings readable. --help still offers no switch for either, so an UNSANDBOXED run (HOST_SANDBOX_MODE=off) still loads both -- documented as a Known Limitation in USAGE.md
--no-skills saves about 2.2k input tokensVERIFIEDa trivial prompt: 15,991 input tokens with skills, 13,887 with --no-skills (-2,104); inside the worker's generated Seatbelt profile with the real HOME and network allowed, 15,974 against 13,874, so the sandbox does not hide the skills. That run is also the first time the real binary answered a live prompt under the generated profile (free model, exit 0, empty stderr). The CLI discovers ~/.commandcode/skills, ~/.agents/skills and the project's .commandcode/skills / .agents/skillsAdopted: the worker now passes --no-skills, the same isolation from the operator's global config the Claude worker gets from --safe-mode (T492), because the CLI otherwise loads every skill under ~/.agents/skills (64 on this machine, the operator's private set). It also drops the target repo's own .commandcode/skills / .agents/skills; --help offers no switch that keeps project skills alone. The CLI has no flag to skip the operator's MCP servers or mods, so those still load (kj3g0)

Unsandboxed runs: decided, not overlooked (kdxmp, 2026-09-21)

The MCP-and-mods gap measured above is closed only when a sandbox wraps the worker. Unsandboxed (HOST_SANDBOX_MODE=none, or a trusted task on a host with no backend) the operator's MCP servers start and their mods are imported into the worker's process, and there is no flag that stops either.

The decision is to LEAVE that allowed rather than refuse a command-code worker without a sandbox:

  • HOST_SANDBOX_MODE=none is the documented full-host-access opt-in every CLI worker shares. Refusing this one worker would change a cross-worker contract in order to close a gap the operator explicitly opted into.
  • What the gap exposes is the operator's own config, running in the operator's own worker, on the operator's own machine -- a confinement gap, not a path to a third party.
  • The claude worker has the same shape: --safe-mode is flag-level isolation, not a sandbox rule, and nothing refuses it unsandboxed either.
  • kg7a3's refusal is a different case and stays: it fires only when a sandbox IS wrapping the worker but cannot express the nested carve-out that sandbox needs.

Recorded at the gate site in CliAgentAdapter.ts's command-code setup hook, so the next reader finds the reasoning where the refusal would have gone. The remaining half of kdxmp -- a smoke pinning the two deny-read rules and their ordering -- still needs a selftest grant.

Cyberine wiring

  • Env: CMD_API_KEY (enables), CMD_BASE_URL (default https://api.commandcode.ai/provider/v1), CMD_MODEL (default deepseek/deepseek-v4-flash). The CLI worker adds CYBERINE_COMMANDCODE_MODEL (default deepseek/deepseek-v4-flash), CYBERINE_COMMANDCODE_MAX_TURNS (default 60) and passes COMMAND_CODE_API_KEY through when set. The free lane adds CMD_FREE_MODEL (its preference order) and CMD_FREE_FALLBACK (0 disables the closed-window fallthrough).
  • Registry id: commandcode in src/core/providers.ts; availability flag commandcodeDirect (key present). This is the cyberine auth id for CMD_API_KEY and it stays commandcode (kv9y5): it names a credential, not a transport.
  • fleet.json provider keys (kv9y5): command-code is the CLI worker (command-code, key COMMAND_CODE_API_KEY or ~/.commandcode/auth.json), command-code-api is the Provider API worker (loop-commandcode-build, key CMD_API_KEY) and command-code-api-free is the zero-credit API lane (loop-commandcode-free-build). The pre-kv9y5 keys commandcode and commandcode-free still load and resolve to the new ones; cyberine fleet doctor prints one migration warning per old key, and when command-code-api is enabled with no CMD_API_KEY while the command-code CLI is installed and logged in, it calls the API provider optional instead of broken. Worker ids did not change.
  • Build worker: loop-commandcode-build, a sandbox-pinned LoopAgentAdapter implementer. Opt in with --fleet loop-commandcode-build, CYBERINE_BUILD_FLEET, or fleet.json. There is no compare-fleet (-direct) adapter.
  • Cost model: subscription. Spend draws on the plan's credit windows, never the daily money cap. src/core/commandCode.ts holds the two id rules: a :free / -free id records costUsd: 0 (VERIFIED against the credit balance), and a claude-* id skips the worker at registration.
  • Errors: is not supported on this endpoint, must be called via /provider/v1/messages and MODEL_NOT_IN_PLAN are classified as auth-failure in src/store/workerCooldown.ts, so the worker cools down instead of retrying (VERIFIED on an unknown id against the live endpoint).
  • Headroom (ky8b3, src/core/commandCodeHeadroom.ts): cyberine route reads GET /alpha/billing/credits on the CMD_BASE_URL host and prints remaining credits and both windows with their resets (commandCodeHeadroom in --json). The reading is a GET only, bounded by a 2.5 s timeout, cached for 60 s in $CYBERINE_HOME/commandcode-headroom.json under a hash of host and key, and never made without CMD_API_KEY. Dispatch paths refresh it too: the router in resolveBuildFleetRoute, orchestrate() and WorkflowEngine when the build fleet names a Command Code worker, and LoopAgentAdapter before its first request on a paid model.
  • Window gate: a window the endpoint reports exceeded (or used >= cap) drops every paid-model Command Code worker from the candidate set until its resetAt (ms), with a note, and an explicit build fleet skips it the same way. A free model id is exempt. A 404, a reshaped body or a timeout reads as headroom unknown and changes nothing.
  • 429 parking: the Command Code adapter's client marks a 429 non-retryable for the SDK (x-should-retry: false) and rewraps a top-level refusal body under error. recordCommandCodeRefusal parks the refused worker in the shared cooldown store until rateLimit.reset * 1000 (else the message's resets at time, else the response's Retry-After header, else the 30-minute rate-limit default; kg7a3 fixed a body-less 429 ignoring Retry-After) and, for an account window, records a closure every paid Command Code worker on the same key honours. A refusal scoped to one model (rateLimit.model, or the texts free ... requests for today, today's limit on, pick another model, Upstream model provider is temporarily unavailable) instead cools only the requested model under the cooldown key <worker>::<model> and records no closure (kg7a3): commandCodeRunGate parks a run only when the worker id is parked or every model in its chain is cooling, LoopAgentAdapter drops cooling models from its chain before the first request, and commandCodeWorkerPark keeps a single-model worker whose model is cooling out of the candidate set. A parked adapter returns its park note without a request, so an Orchestrator retry or a later workflow step does not reach the endpoint, and a circuit-breaker trip no longer shortens a longer park (recordCircuitCooldown keeps an active entry that ends later). VERIFIED against a local fake server in both payload shapes; never provoked live.
  • CLI worker (kd823): command-code (makeCommandCodeAdapter in src/adapters/CliAgentAdapter.ts), built after the km3ga bake-off measured the harness solving 3 of 3 real tasks at about 0.035 credits each where loop-commandcode-build solved 1 of 3. It spawns command-code --print=<prompt> --output-format json --model <CYBERINE_COMMANDCODE_MODEL, default deepseek/deepseek-v4-flash> --max-turns <CYBERINE_COMMANDCODE_MAX_TURNS, default 60> --skip-onboarding --no-auto-update --no-session --no-skills -t --yolo in the task worktree, never -w. Registered in BUILD_FLEET_CLI_BINARIES, cliBinaryForWorker, WORKER_PROFILES (costModel: 'subscription'), WORKER_PROVIDER_MAP (commandcode) and checkCommandCode (COMMAND_CODE_API_KEY, else a non-empty apiKey in auth.json; the value is never read out). Its provider label is commandcode:<model>, the same prefix as the loop worker, because both draw one pool.
  • CLI worker sandbox: --yolo because print mode refuses writes otherwise (Permission modes above), so the host sandbox is its only confinement. cliConfigDirsFor('command-code') is ~/.commandcode, which puts that directory on every worker's read deny-list and re-allows reading it for this worker only; cliWritablePathsFor('command-code') narrows the write grant to projects/, file-history/, sessions/, updates.json, update.lock and telemetry-install-id, and a Seatbelt regex denies writing projects/<slug>/mcp.json, settings.json and settings.local.json. Verified offline with a probe inside the generated profile: those grants allowed, and auth.json, providers.json, mcp.json, mods/, the per-project mcp.json, another CLI's auth.json and any path outside the worktree denied (EPERM). The real binary ran under that profile with the network denied and wrote only projects/<slug>/ session files, with no EPERM. The bubblewrap, container (docker, podman, gvisor) and Windows backends cannot express that nested carve-out, so the worker fails closed there (kg7a3): nestedWriteCarveOutGap in src/adapters/hostSandbox.ts drops it from the candidate set with an unavailable - host sandbox "<mode>" cannot keep ... note, the adapter's setup hook refuses before the run gate or any spawn, and resolveSandboxConfig throws HostSandboxError for any other caller whose writable paths reach projects/<dir>/. A trusted task with no sandbox (HOST_SANDBOX_MODE=none) is not refused: that is the full-host-access opt-in every CLI worker shares. The bind backends that remain for other workers bind writable paths with --bind-try (bubblewrap) or skip a missing one (docker, podman), so an absent optional state file such as updates.json neither fails a bwrap spawn nor makes docker create a root-owned directory in its place. Verified by the generated argv with a fake HOME (bwrap cannot run on macOS).
  • CLI worker exits: the last type: "result" line is parsed; usage maps inputTokens / outputTokens and cacheReadTokens to cacheHitTokens / cacheHitRatio; a non-success subtype, or exit 0 with no result line, is an error. Exit 3 records an auth-failure cooldown (never retried), 4 is a permission refusal naming the model (a retired free tier or a spend cap, 2026-09-19) with the usual cooldown, 130 (SIGTERM, no result line) is an error with no cooldown, 8 and 9 return partial with usage kept, 5 parks the worker until the Resets in time (and, with CMD_API_KEY set, closes that window through recordCommandCodeRefusal), except that a per-model limit (today's limit on <model>) cools only command-code::<model>, 10 and 6 cool down as out-of-credits and connection failure. A run checks commandCodeRunGate before spawning, so a parked worker returns its park note without starting the CLI. commandCodeWorkerBindings includes command-code, so a closed paid window drops it from routing like the loop worker; a free model is exempt.
  • Free lane (kp1nc, src/core/commandCodeFreeLane.ts): loop-commandcode-free-build is a second implementer bound to a zero-credit model. Its model is never named in code: the dispatch paths that prime headroom also read GET /provider/v1/models (30-minute cache in $CYBERINE_HOME/commandcode-catalog.json, a failed read retried after 60 s, the last good catalog kept), keep the ids isCommandCodeFreeModel accepts in catalog order, and bind the first as the model and up to three more as LoopAgentAdapter fallbacks. CMD_FREE_MODEL (comma-separated) sets a preference order among free ids the catalog still lists. A 429 or 5xx on one free model moves the run to the next and records a per-model cooldown the resolver skips on the next build (VERIFIED against a local fake server). A per-model refusal on the LAST model in the chain now cools that model too instead of parking the whole worker until that model's reset (kg7a3, VERIFIED against a local fake server: a daily-cap 429 on the last model left the other free model routable and its next run succeeded). The worker is exempt from window parking because every id it can bind is free.
  • Free lane routing: profile costModel: 'free', freeLaneKinds: ['qa', 'code-small']. The router picks it as the single qa worker only when no preferred-pool (subscription) worker is available, before any metered API (the bench graded code, not answers), races it with the preferred pool on code-small (alone, before any metered API, when no preferred-pool worker exists), and holds it back on code-large unless nothing else is available. The kinds come from the bench recorded in .local/research/commandcode/2026-09-17-free-lane-bench.m3max.md: print shape 15/16, 16/16 and 14/14 (two unrun) for the three free models against 16/16 for paid deepseek/deepseek-v4-flash, write-the-file shape 6/6 (two refused by the daily cap), 8/8 and 8/8 against 8/8, zero credits on every free batch, 0.0488 credits for both paid batches together. Multi-file implementation on a free model is unmeasured, and the daily request caps (below) rule out bulk implementation regardless.
  • Closed-window fallthrough: when loop-commandcode-build is parked (window closed, or an earlier refusal) an explicit build fleet naming it builds loop-commandcode-free-build instead, with a note, unless CMD_FREE_FALLBACK=0. A mid-run refusal still parks the paid adapter for the rest of that run.
  • Judge backends (kz13x, src/judges/judgeBackends.ts): loop-commandcode-free-build (the free lane, every resolved model a fallback) and loop-commandcode-build (CMD_JUDGE_MODEL, else CMD_MODEL) back llm-judge, adversarial, the research ClaimVerifier and SynthesizerReducer when enabled in fleet.json, after the direct providers by default or in the order fleet.json routing.judges names. Judge calls use the same commandCodeFetch (a 429 is not retried) and record refusals through recordCommandCodeRefusal, so a judge that spends a free model's daily cap cools that model for the implementers too. VERIFIED 2026-09-17: one LlmJudge verdict (two candidates, a strict-JSON answer) on inclusionai/ling-3.0-flash-sante:free took one request and named the correct candidate with a cited reason.
  • Not yet wired: a minimum-headroom threshold (only a closed window gates), a measured ranking among free models (catalog order today), and liveness funding evidence for the CLI row (cyberine doctor --liveness reports it funding-unknown).

This API-key path is compliant: an official key against a documented endpoint. It is not the subscription-OAuth-to-API pattern tombstoned in T42/T43/T44/ksmpy.

Changelog watch

Command Code is on CHANGELOG-WATCH.md. Its catalog, free-model list and deals rotate within days, and the CLI self-updates, so a stale reading here ships a wrong model id or a wrong flag.