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
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:
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:
| code | meaning | what a script should do |
|---|---|---|
| 0 | ok | carry on |
| 2 | usage error | fix the invocation |
| 3 | engine unreachable | start one, then retry — it's retryable |
| 4 | not found | check the id/path with the matching list verb |
| 5 | verification failed | don't trust the artifact; re-sign or re-fetch |
| 6 | conflict | re-read state, retry |
| 7 | auth rejected | fix 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):
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:
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.