wbx CLI
The canonical Workbooks command-line tool. One Rust crate, two build targets
(native + wasm32-wasip1): the binary is named wbx (crate wb-cli).
The binary is
wbx, notwb. The legacy Elixir escript (runtime/host/cli.ex) and the dead npm@work.books/cliare superseded; this crate is canonical. :SRC: cli/Cargo.toml#bin (name = "wbx", line 10) · cli/SPEC.md:6
Two execution classes (see each verb's Where it runs column):
LOCAL — kernel ops, assembly, provenance, orchestration; needs no runtime.
ENGINE — a thin RCP call into a running runtime (it owns the compilers, wasmtime, the tenant library). Engine verbs fail with exit 3 + a "no runtime — try =wbx deploy local=" hint when none is reachable.
:SRC: cli/src/main.rs:3 · cli/src/mode.rs:67
Global flags & the mode model
| flag | sets mode | behaviour |
| (none) | auto | stdout is a TTY → Human · piped/redirected → Agent |
--agent | Agent | never prompts, no ANSI, stable shapes |
--json | Json | Agent + one JSON envelope on stdout |
Both flags are global = true (accepted before or after the verb).
:SRC: cli/src/main.rs:27 (--agent) · :30 (--json). Detection precedence
--json > --agent=/=WBX_AGENT=1 > TTY → Human → Agent: cli/src/mode.rs:23-33.
Json envelope (success): { "ok": true, "verb": "<path>", "data": … }. If the
verb already emitted JSON it is embedded structurally, else wrapped as
{"text": …}. Error: { "ok": false, "verb", "error": {code, message, hint, retryable} }.
:SRC: cli/src/mode.rs#renderok (:92-107) · #rendererr (:110-135).
Verb introspection — wbx help --json (either order) prints the whole verb
tree as JSON so agents introspect the surface instead of scraping help. Agent-mode
bare wbx also folds the tree into the health payload.
:SRC: cli/src/main.rs#verbtree (:212) · main intercept :233 · landing :257-266.
Exit-code map
Stable contract for agent branching.
| code | meaning | const |
| 0 | ok | — |
| 1 | everything else | (fallthrough) |
| 2 | usage (clap parse) | clap-emitted |
| 3 | engine unreachable | EXIT_ENGINE (mode.rs:35) |
| 4 | not found | EXIT_NOT_FOUND (mode.rs:36) |
| 5 | verification failed | EXIT_VERIFY (mode.rs:37) |
| 6 | conflict | EXIT_CONFLICT (mode.rs:38) |
| 7 | auth rejected | EXIT_AUTH (mode.rs:39) |
Codes are assigned by a heuristic over the error-chain text (classify) until
errors carry typed codes; the contract is the code, not the text.
:CAVEAT: classification is text-matching today (e.g. "connection refused" → 3,
"404"/"not found" → 4) — a misworded upstream error can misclassify.
:SRC: cli/src/mode.rs#classify (:43-63).
Environment variables
Every key resolves WBX_<KEY> first, then legacy WB_<KEY> (both work; docs
prefer WBX_*). :SRC: cli/src/util.rs#envvar (:84-88).
| var | effect | src |
WBX_AGENT=1 | force Agent mode | cli/src/mode.rs:26 |
WB_ENGINE_URL | remote engine base URL (overrides local discovery) | cli/src/io.rs:111-118 |
WB_ENGINE_TOKEN | bearer for the remote engine | cli/src/io.rs:115 |
WB_DESKTOP_DIR | discovery dir holding runtime.json (else app-data disco/) | cli/src/io.rs:60-64 |
WB_IMAGE | override the deploy runtime image (default below) | cli/src/deploy/mod.rs:127 |
WB_PROVIDERS_DIR | where wbx deploy resolves provider recipes | cli/src/deploy/mod.rs:280 |
WB_TOOLKIT_EXEC=1 | server-side gate required for wbx toolkit run | cli/src/main.rs:169 |
WB_PUBLIC_BEARER | (deploy-managed) control-plane token, generated once on cloud apply | cli/src/deploy/mod.rs:406 |
Engine discovery: with no WB_ENGINE_URL, the local engine is located via its
discovery file (WB_DESKTOP_DIR/runtime.json → else
~/Library/Application Support/sh.workbooks/disco/runtime.json on macOS,
~/.local/share/sh.workbooks/disco/runtime.json elsewhere).
:SRC: cli/src/io.rs#discoverypath (:60-65) · util.rs#appdir (:73-80).
Verbs
Columns: Run = LOCAL or ENGINE · args in fixed, optional in [brackets].
Defaults and flags are exactly as declared in clap.
:SRC: cli/src/main.rs#Cmd (:37-132).
Start here (local)
| verb | args / flags | does | Run | src (main.rs) |
wbx (bare) | — | where-am-I landing (doctor + start hints; agents get verb tree) | LOCAL | :283, :257 |
wbx init | name [=--template= minimal] | scaffold a new workbook source (workbook.org + data/) | LOCAL | :40, :289 |
wbx dev | [=src= .] [=--port=] | watch + rebuild + serve a live preview (interactive) | LOCAL | :42, :290 |
wbx doctor | — | env + engine health report (always exits 0; --json for agents) | LOCAL | :44, :291 |
wbx status | — | same landing as bare wbx | LOCAL | :46, :292 |
wbx open | file | open a workbook (or any file) in the default browser | LOCAL | :48, :293 |
wbx upgrade | — | replace this binary with the latest release (npm → use npm) | LOCAL | :50, :294 |
wbx completions | shell (bash| zsh| fish| elvish| powershell) | shell completions to stdout | LOCAL | :52, :295 |
Source inspection (local, kernel)
| verb | args | does | Run | src (main.rs) |
wbx query | file | org → headline / structure rows | LOCAL | :56, :302 |
wbx tangle | file | org → WIT-world-shaped build plan (literate) | LOCAL | :58, :303 |
wbx lint | file | diagnostics over a workbook source | LOCAL | :60, :304 |
tangle is the org-mode term of art and stays (not renamed to plan).
:SRC: cli/TAXONOMY.md:142 (decision LOCKED 2026-06-09).
Workbook lifecycle
| verb | args / flags | does | Run | src (main.rs) |
wbx build | [=src= .] | compile the source's code components → WASM | ENGINE | :63, :306 |
wbx bundle | [=src= .] [=-o/--out=] | assemble org (+ data) → one workbook .wbundle | LOCAL | :65, :307 |
wbx unbundle | file [=dest=] | workbook → source tree | LOCAL | :67, :308 |
wbx run | file [=input…= trailing] | execute a workbook's workflow DAG on the engine | ENGINE | :69, :309 |
wbx publish init | — | scaffold ./publish.org | LOCAL | :136, :311 |
wbx publish validate | — | coherence-check publish.org | LOCAL | :138, :312 |
wbx publish apply | [=workbook= workbook.html] | ship the assembled workbook to the configured surface | LOCAL¹ | :140, :313 |
¹ publish is local orchestration — it spawns wrangler=/=git to ship to a
surface (CF Pages / gh-pages / host); no runtime, but external tools.
:SRC: cli/TAXONOMY.md:136.
build/run delegation rationale: :SRC: cli/TAXONOMY.md:142 (decision 2).
Library (engine-backed)
| verb | args / flags | does | Run | src (main.rs) |
wbx library | — | list the tenant's workspaces + members | ENGINE | :75, :316 |
wbx checkout | member dir | borrow a library member into a working dir | ENGINE | :77, :317 |
wbx checkin | member dir | pack + sign a member back into the library | ENGINE | :79, :318 |
wbx store | [=slug=] [=--list=] [=--build=] | archive a workspace to durable storage (--build compiles first) | ENGINE | :81, :319 |
wbx fetch | key [=out= ./] | restore from durable storage | ENGINE | :88, :320 |
wbx search | query [=--semantic= | --literal | =--sql=] | cross-workbook search (default: hybrid) | ENGINE | :90, :321 |
search mode resolves to semantic / literal / sql if the flag is set,
else hybrid. :SRC: cli/src/main.rs:322.
Toolkit (agent extensibility; mixed)
| verb | args / flags | does | Run | src (main.rs) |
wbx toolkit list | — | list discoverable toolkits (id · status · tagline) | ENGINE | :146, :327 |
wbx toolkit show | id [=skill=] | a toolkit's manifest + skill index (or one skill's recipe) | ENGINE | :148, :328 |
wbx toolkit search | q… | search toolkits + skills | ENGINE | :150, :329 |
wbx toolkit verify | id | check a toolkit's invocation contract (bin/artifact present) | ENGINE | :152, :330 |
wbx toolkit sign | id | sign a toolkit manifest (did:key; required for third-party) | LOCAL | :154, :331 |
wbx toolkit build | id [=which=] | build a toolkit's declared artifact (in-sandbox compile + register) | ENGINE | :156, :332 |
wbx toolkit push | id dir | ship a toolkit directory onto the engine | ENGINE | :158, :333 |
wbx toolkit import | source [=--as=] [=--out=] | package an existing construct (skill / md / folder) as a toolkit | LOCAL | :160, :334 |
wbx toolkit run | id task [=args…=] | run a toolkit task recipe (gated on WB_TOOLKIT_EXEC=1) | ENGINE | :169, :336 |
wbx toolkit audit | [=dir= .] [=--fix=] | re-run the wasm-compat audit on an imported dir (--fix auto-converts) | LOCAL/ENGINE | :171, :335 |
--as override kinds (else detected by shape): claude-skill · markdown ·
folder. Detected source taxonomy (SKILL.md, single .md, dir, .mcp.json,
.cursorrules, AGENTS.md/CLAUDE.md, OpenAPI, package.json bin, pyproject scripts).
:SRC: cli/src/main.rs:165 · cli/SPEC.md:185-195.
import pipeline (parse+scaffold → dependency audit → fix-up plan as org TODOs):
:SRC: cli/SPEC.md:198-211. verify is the done-test.
Runtime ops (engine-backed)
| verb | args / flags | does | Run | src (main.rs) |
wbx workflow run | file [=input= ""] | execute the workflow DAG | ENGINE | :181, :340 |
wbx workflow plan | file | show the schedule/plan without executing | ENGINE | :183, :341 |
wbx agent run | task… [=--system= "…"] [=--model=] | start a long-horizon run (returns an id) | ENGINE | :189, :344 |
wbx agent status | id | poll a run's status + result | ENGINE | :196, :345 |
wbx workbook list | — | list deployed workbooks | ENGINE | :201, :348 |
wbx workbook show | id | show a deployed workbook's org source | ENGINE | :203, :349 |
wbx workbook deploy | id file | deploy an org source under an id | ENGINE | :205, :350 |
wbx telemetry | [=slug=] | run index, or one run's summary | ENGINE | :109, :352 |
wbx ledger | slug | verify a run's signed ledger | ENGINE | :111, :353 |
agent run default system prompt: "You are a careful, capable agent."
:SRC: cli/src/main.rs:192.
Provenance & federation
| verb | args / flags | does | Run | src (main.rs) |
wbx sign | file [=-o/--out=] | embed a did:key provenance manifest | LOCAL | :115, :355 |
wbx verify | file | check an artifact's signature + integrity | LOCAL | :117, :356 |
wbx mirror | target | mirror the tenant repo to a git host (url or forge) | LOCAL¹ | :119, :357 |
wbx federate | — | federate the tenant repo over Radicle (P2P) | ENGINE | :121, :358 |
¹ orchestration: spawns git. :SRC: cli/TAXONOMY.md:136.
Engine (the runtime itself)
| verb | args / flags | does | src (mod.rs) |
wbx deploy init | [=preset= local| cloud] | scaffold ./deployment.org (TTY picks if omitted) | :34, :84 |
wbx deploy validate | — | coherence check (incl. declared secrets present) | :36, :85 |
wbx deploy apply | — | converge to the declared state | :38, :97 |
wbx deploy status | — | inspect the live deployment | :40, :98 |
wbx deploy logs | — | tail the live deployment's logs | :42, :99 |
wbx deploy down | — | tear it down | :44, :100 |
wbx deploy local | — | shorthand: scaffold local config if absent, then apply | :46, :101 |
wbx deploy doctor | — | engines, recipes, and declared secrets — present/missing | :50, :107 |
wbx deploy secrets set | pairs… [=--from-env=] | stage KEY=VALUE secrets (0600 under app-dir) | :62, :225 |
wbx deploy secrets list | — | list secret NAMES (never values) | :66, :251 |
wbx deploy secrets unset | key | remove a secret by name | :68, :258 |
wbx deploy secrets push | — | push staged secrets to the provider without a deploy | :70, :266 |
Provider model: local uses a container-engine seam (docker → podman →
krunvm, first found wins); any other DEPLOY_TARGET is a recipe at
providers/<place>/bootstrap.sh (fly is the bundled one). Adding a provider =
dropping a bootstrap.sh, no recompile.
:SRC: cli/src/deploy/mod.rs#engine (:359-361) · resolverecipe (:300-303) · header comment :7-12.
Default image: ghcr.io/workbooks-sh/runtime:latest (WB_IMAGE overrides).
:SRC: cli/src/deploy/mod.rs:76, :127.
deployment.org keywords: #+DEPLOY_TARGET · #+DEPLOY_APP · #+DEPLOY_REGION
(default sjc) · #+DEPLOY_PORT (default 4000) · #+DEPLOY_IMAGE ·
#+DEPLOY_SECRETS (secret NAMES) · #+DEPLOY_TOOLKITS (id:dir …, pushed after apply).
:SRC: cli/src/deploy/mod.rs#Config (:116-145) · apply :384.
Cloud bearer: first cloud apply generates a 256-bit token once, persists it
as WB_PUBLIC_BEARER in secrets.env, and never rotates it (rotation would 401
live clients). Call your engine with export WB_ENGINE_TOKEN=<token>.
:SRC: cli/src/deploy/mod.rs#ensurecloud_bearer (:406-422).
wbx deployis the user's tool to run the runtime image for their own use. It is not how the platform publishes the compilers package or the runtime image — do not conflate the three release layers. :SRC: CLAUDE.md "Release / publishing — THREE separate layers" · cli/TAXONOMY.md:122.
Escape hatch & config (local)
| verb | args / flags | does | Run | src (main.rs) |
wbx rt | args… (status| get \pth| post \pth [body]) | raw RCP escape hatch | ENGINE | :127, :361 |
wbx var | args… (set| get| list| ref) | local variables / secrets (ref-only) | LOCAL | :131, :363 |
Not-yet-built: wbx docs *
Planned verbs (per the architecture plan, not present in the binary):
wbx docs new · build · drift (keystone CI gate) · lint · untangle ·
serve · publish, plus wbx schema --json. Verified absent: grep Docs
cli/src/main.rs matches nothing.
Legacy: the Elixir escript
See also
Capability surface a toolkit can request: Dock capabilities
Toolkit EXEC shapes: exec-shapes · manifest: manifest
Why build/run delegate to the engine: the Dock