learn / 07 — the command line

one command,EVERYverb

wbx is the ecosystem's command line — one compiled tool that authors, builds, signs, ships, and docks workbooks. The same binary runs on your laptop, in CI, and inside the engine, so you and your agents speak one language.

the command13 min read
A colossal chrome multitool with its instruments fanned open, a tiny figure using the smallest blade — 1970s sci-fi style

a bag of BINARIES

Every ecosystem eventually hands you a toolbelt: one binary to scaffold, another to build, a third to deploy, a wrapper to sign things, a daemon's client for the server bits — each with its own flags, its own config file, its own way of being slightly out of date. You don't learn the tools so much as negotiate with them.

An ecosystem whose whole bet is homogeneity can't ship that. If workbooks are one artifact and the grammar is one grammar, the tooling has to be one tool.

the DEFINITION

wbx /ˌdʌb·əl·juː·biː·ˈeks/ command

1. the Workbooks command line: one compiled tool that authors, builds, signs, ships, and docks workbooks — the same binary on your laptop, in CI, and inside the engine.

It's deliberately thin. wbx owns almost no logic of its own: it parses what you asked, handles local org operations with the same kernel the rest of the ecosystem uses, and drives the engine for everything heavy. The intelligence lives in the system; wbx is the handle.

install IT

Two honest paths today — the installer, or npm:

curl -fsSL https://workbooks.sh/cli.sh | sh    # detects your OS + arch
npm install -g @work.books/cli                 # same thing, npm-flavored
wbx --version                                  # → wbx 0.13.0

macOS (Apple Silicon + Intel), Linux (x64 + arm64), and Windows (x64) binaries ship from GitHub Releases — the npm package is a thin launcher that fetches the right one. (The bare npm name wbx belongs to someone else, so the package lives at @work.books/cli; the command is wbx either way.)

Then let the tool check itself:

wbx doctor      # env + engine health, what's wired and what isn't
wbx             # bare wbx = where am I — version, engine state, next moves

the verb FAMILIES

Thirty-odd verbs, but they group into five families — learn the families and the help text carries you the rest of the way:

wbx — one command, five families
authorinit · dev · query · tangle · lint — scaffold, live-preview, and shape org; the literate-programming surface
makebuild · bundle · unbundle · run — compile code to wasm, tangle everything into one artifact
trustsign · verify · ledger — did:key provenance that travels with the file
partstoolkit · workflow · agent — discover, build, push, import, and run the extensibility surface
enginedeploy · publish · workbook · rt · var — stand up a Nexus, ship to it, talk to it raw
everydaydoctor · status · open · upgrade · completions — the tool looks after itself and you
plus the library — store · fetch · search · checkout · checkin

Every family follows the same manners: scaffold with init, check with validate or lint, act with apply or build — declarative org files in, converged state out. If you've used one family you've basically used them all. And every success suggests the next verb, so the tool teaches its own grammar as you go.

two AUDIENCES, one binary

Here's the design decision that shapes everything else: wbx knows it has two kinds of users, and it changes its manners for each without changing what it does.

You, at a terminal. Human mode is deliberately dumb simple — the tool does the work. Missing argument with an obvious default? It picks the default and tells you. Genuinely your call? A tiny picker. Every success ends with the next verb you probably want. You should never need the manual for the happy path.

An agent, in a pipe. The moment stdout isn't a terminal, wbx switches: no prompts ever, no ANSI color, plain parseable output. Add --json and every outcome — success or failure — arrives as one envelope:

{ "ok": false, "verb": "toolkit push",
  "error": { "code": 3,
             "message": "engine unreachable at 127.0.0.1:4000",
             "hint": "start one with `wbx deploy local` or set WB_ENGINE_URL",
             "retryable": true } }

Failures carry a stable exit-code map, so a script can branch without parsing prose:

codemeaningwhat a script should do
0okcarry on
2usage errorfix the invocation
3engine unreachablestart one, then retry — it's retryable
4not foundcheck the id/path with the matching list verb
5verification faileddon't trust the artifact; re-sign or re-fetch
6conflictre-read state, retry
7auth rejectedfix credentials; don't retry blindly

Forcing a mode: --agent or WBX_AGENT=1 gets agent manners on a TTY; --json gets the envelope anywhere. Detection is just the default.

your first workbook, two MINUTES

Step by step, nothing assumed. You need wbx installed — that's it, no engine, no account.

1 — scaffold. One command, one folder:

wbx init field-notes
created field-notes/ — workbook.org + data/
next: wbx dev field-notes

2 — see it live. wbx dev watches the org file, re-renders on every save, and serves a preview that reloads itself:

wbx dev field-notes
wbx dev: http://127.0.0.1:4321 — watching field-notes/workbook.org

Open the URL, then open workbook.org in any editor. Change a heading, save, watch the browser follow. That loop — org file on the left, living page on the right — is the whole authoring experience.

3 — make it one file. When it's worth keeping, tangle everything into a single self-contained artifact and put your name on it:

wbx bundle field-notes      # packs workbook.html + source + data → field-notes.wbundle
wbx sign field-notes.html   # did:key provenance, embedded in the artifact

The carton ships anywhere; the workbook.html inside opens in any browser, mails like an attachment, and carries its own provenance (the bundles deep dive opens one up byte by byte). No server was involved at any point — the engine only enters the story when you want the workbook to keep living after you close the laptop, and that's wbx deploy local + wbx workbook deploy, shown in the session below.

import ANYTHING

You probably already have capability lying around — Claude skills, MCP servers, an OpenAPI spec, a little npm CLI. The intake ramp packages any of it as a toolkit:

wbx toolkit import ~/.claude/skills/my-skill
imported claude-skill → my-skill-toolkit/
  manifest.org      the toolkit surface
  skills/           3 skills
audited 2 scripts — 1 ready · 1 convertible · 0 blocked

Nine source kinds detect by shape — point it at the thing and it figures out what the thing is (--as overrides):

wbx toolkit import — what it eats
claude-skillSKILL.md + references + scripts → manifest + skill tree, docs translated to org
mcp-server.mcp.json → a skill per server; the launch command becomes the audited bin. Env vars carry over by name only — secret values never enter the artifact
openapia JSON spec → a skill per operation, HTTP routed through the engine
npm-cli / pip-clipackage.json bin / pyproject scripts → README becomes the manual, entry points get audited honestly
guidanceAGENTS.md · CLAUDE.md · .cursorrules · plain markdown · a folder of docs → guidance-only toolkits, a valid landing

Import is three honest stages, and the second two run automatically:

Stage 1 — parse + scaffold. Detect the kind, translate the docs to org, write a real manifest.org that wbx toolkit push will accept.

Stage 2 — the wasm audit. Every carried script gets classified against the sandbox lanes: ready (shell and JS run today), convertible (a known recipe — npm deps bundle at build time, raw curl becomes engine-brokered HTTP), or blocked (python has no lane yet; sudo means nothing in a sandbox). The findings are written into the manifest, so the artifact carries its own audit.

Stage 3 — the fix-up plan. Everything not ready becomes an org TODO with concrete steps — which lane, which recipe, what to rewrite — and the done-test spelled out. It reads like a manual because it is one: hand the folder to an agent and the work is already itemized.

** TODO fix-up plan [0/1]
*** TODO scrape.py (blocked — python3)
    - [ ] rewrite in JS for the quickjs lane — keep the CLI contract
    - [ ] re-run =wbx toolkit audit= — scrape.py must classify ready

And when an engine is reachable, wbx toolkit audit --fix runs the convert for you: push → build → verify, one shot.

wire in an AGENT

If you're pointing a coding agent at wbx, three things make it fluent immediately:

1 — let it discover the surface. The whole verb tree is machine-readable, so an agent never guesses at flags:

wbx help --json     # every verb, sub-verb, arg, and flag as one JSON tree

2 — give it the envelope. Tell the agent to call everything with --json and branch on error.code + error.retryable instead of scraping stderr. The hint field is written for the agent to act on — code 3's hint literally names the command that fixes it.

3 — pipe freely. Author verbs accept - for stdin, so generated org never needs a temp file:

cat generated.org | wbx lint -
echo "* hello" | wbx query -

That's the whole integration. No SDK, no API keys for the local surface — the same binary you use, spoken plainly. This is the contract the runtime's own agents use; nothing about it is special-cased for them.

same binary EVERYWHERE

The part that makes wbx more than a convenience: it's one Rust crate with two build targets. The native binary is what you install; the same source also compiles to WebAssembly, so it runs inside the engine's sandbox — which means the agents working in a runtime container reach for the exact same tool you do, with the same help text and the same manners.

That's not an implementation detail; it's the trust model. When an agent's session log says wbx toolkit build, you can run the identical command and see the identical thing. No translation layer between what your agents do and what you'd do — which is what "people and AI build together" has to mean at the tooling level.

a real SESSION

Start to finish — author, check, make, trust, dock:

>_one tool, the whole journey

questions people actually ASK

Do I need the engine installed to use it?

Not for the local families — author, make, and trust verbs work on plain files. The engine families (deploy, rt, workbook) need a Nexus to talk to, and wbx deploy local is how you get one.

Windows?

Yes, as of 0.13.0 — wbx-windows-x64.exe ships in every release and the npm launcher picks it up. WSL still works if that's home for you.

Is this the same CLI my agents use?

Identical — that's the point. The runtime image carries the same binary at /usr/local/bin/wbx, and the wasm build runs it in-sandbox. One tool, every hand that holds it.

What's the difference between agent mode and --json?

Agent mode is manners — no prompts, no color, plain output, kicks in automatically when stdout is piped. --json is a format — the one-envelope-per-outcome contract with stable error codes. Most agent integrations want both; piping gets you the first for free.

Can it really convert my Claude skill into a toolkit?

It packages anything parseable immediately — docs become org, the manifest is real, push accepts it. Scripts are the honest part: shell and JS usually classify ready, python is blocked until there's a lane, and everything in between gets a written fix-up plan rather than a shrug. Guidance-only is a perfectly good landing; plenty of skills are knowledge, not code.

the deep DIVES

Go deeper into this area — the technical docs underneath it.

keep GOING

The command is how you drive the rest — pick a destination.