CLI reference
Get the direct screenbook command with one global install:
npm install -g @screenbook/engine
Alternatives that need no install: npx -y @screenbook/engine <command>, or from a
checkout npm run build once, then node dist/cli/screenbook.js <command>. Every command
takes an optional project directory (default: the current one; running from inside
.screenbook/ resolves to its parent project automatically).
init [dir] [--name X] [--force] [--app <src>] [--cooperative]
Create .screenbook/ in the target project — brief.md (your requirements), app.config.json, starter theme, a welcome feature, review/, the agent authoring contract, plus the packaged skill at .claude/skills/screenbook/. The folder is the prototype's source of truth; commit or gitignore it. Refuses to overwrite an existing .screenbook/ without --force.
--app path/to/index.html additionally registers an existing SPA in that folder as an
embedded app (driver scaffolded unless --cooperative).
serve [dir] [--port 4600] [--background]
The dev server. Static hosting with:
- the studio runtime mounted at
/screenbook/*straight from the installed package (/engine/*kept as a compatibility alias) — your project never carries runtime code - live reload over SSE — saving any project file refreshes the studio; screen edits reload
the current frame (agent writes to
review/comments.jsonrefresh the review panel and count badges live) - automatic
manifest.jsonregeneration when screens change review/comments.jsondisk sync and 🎨 Theme-Lab Save (POST /__sb/theme/<id>)Cache-Control: no-storeon everything — stale-cache rituals don't exist here/redirects to the studio
A taken port automatically moves to the next free one (--port makes it strict instead).
Serve as many projects as you like — the first serve starts a tiny port-80 gate, and each
studio also gets a pretty, portless URL like http://qahwa.localhost/screenbook/.
--background detaches the server and returns your terminal (logs land under
~/.screenbook/).
The standard base URL — screenbook.localhost
With the gate up, one address works from anywhere, no matter which project or folder you're in:
| URL | What happens |
|---|---|
http://screenbook.localhost/ | Dashboard of every running project — display name, host, port, uptime; click to open. http://localhost/ shows the same page. |
http://screenbook.localhost/<slug> | 302-redirects to that project's studio (http://<slug>.localhost/screenbook/). Deeper paths and ?query are preserved, and the browser carries #hash deep links across the redirect — so screenbook.localhost/qahwa#order lands exactly where you meant. |
| unknown slug | A 404 page that still lists everything running. |
The <slug> is the project folder name (lowercased, non-alphanumerics dashed).
Inside the studio the topbar's project name doubles as a project switcher: click it
for the list of running projects (current one check-marked) and hop between them.
Small print: screenbook and gate are reserved — a project folder literally named
screenbook serves as screenbook-app.localhost so the front door can never be
shadowed. Serving the same project twice keeps both instances, but the slug routes to
the lowest port everywhere (gate, dashboard, switcher — listed once with an instance
count). If port 80 is busy, the gate stays off: studios keep their 127.0.0.1:<port>
URLs, the switcher keeps working through them, and screenbook.localhost is simply
unavailable.
servers [--json]
Every running ScreenBook server on this machine — name, URL, port, pid, mode.
stop [dir | --port N | --all]
Stop a server (with no arguments: the current project's). Stopping the last studio takes the port-80 gate down with it.
manifest [dir]
Rescan features/*/screens/*.html → regenerate each feature's derived manifest.json
(writes only on change; reports per-feature counts and any broken meta blocks).
validate [dir] [--static] [--json]
The done gate, two halves:
- Static — config/feature wiring, screen contract lint (meta block, bridge include,
ids), dangling
data-gotargets, manifest freshness, scenario/flow references, theme shape, i18n gaps (warnings), app-featuresrc/driver existence. - Browser (skipped with
--static) — headless Chrome renders every screen × theme × light/dark × LTR/RTL, assertingEngine.ready, meta present, zero console errors; embedded apps must register and survive a visit to every screen they report.
Exit code 0 = green. --json prints the full machine-readable report.
screenshot [dir] --screen <feature>/<screen> [options]
Device-framed PNGs via headless Chrome. Options: --mode light,dark · --dir ltr,rtl ·
--scenario id · --theme id · --lang xx · --out dir (default
review/screenshots/). Comma lists produce a matrix.
app add <src> [dir] [--id --title --icon --device --chrome self|engine --cooperative]
Embed an existing single-page app as an app-type feature. Scaffolds an injectable
driver.js template (fill in screens() / go() / set()) unless --cooperative, in
which case the app is expected to include the packaged app-bridge.js itself. See
App mode.
mcp [--root dir]
Start the stdio MCP server (23 authoring tools for AI agents). This is what makes the npx registration line work:
claude mcp add screenbook -- npx -y @screenbook/engine mcp --root .
Nothing but JSON-RPC goes to stdout; server logs go to stderr. See AI agents & MCP.
tool [name] [dir] [--param value…]
Every one of those 23 MCP operations, runnable directly from the terminal — the same registry, the same handlers, one implementation ("one core, two faces"):
screenbook tool # the catalog: every operation + summary
screenbook tool add_screen --help # parameter help, straight from the schema
screenbook tool list_screens --feature order # JSON out — identical to the MCP reply
screenbook tool add_screen --feature order --screen 045-tip --html @tip.html
cat seed.json | screenbook tool set_data --feature order --seed -
Parameter values are literals, @path/to/file (reads the file — handy for screen HTML),
or - (reads stdin, one parameter per call). Object-typed parameters parse as JSON after
file/stdin resolution. Kebab-case flags alias the snake_case parameters (--input-image
= --input_image). Results print as pretty JSON; a result carrying ok: false
(e.g. tool validate) exits 1, so it scripts cleanly.
The registry includes the Image Generator: generate_image (providers nano-banana /
chatgpt / grok, resolution 512–4K, aspect ratios, edit via --input-image, per-image
cost estimates in the studio), list_images, and remove_image — see the
skills/screenbook-images skill for the full workflow. Inside a project, images land in
the images/ library with a manifest; standalone they save to the current directory.
config [list | get <key> | set <key> <value> | unset <key>]
Machine-wide preferences in ~/.screenbook/config.json — today: image.provider
(nano-banana | chatgpt | grok) and image.model (pin any model id — a Nano Banana 3,
say). Precedence when consumed: per-call flag → env (SCREENBOOK_IMAGE_PROVIDER /
SCREENBOOK_IMAGE_MODEL) → this file → defaults. API keys are refused here by
design — they live only in env variables (GEMINI_API_KEY, OPENAI_API_KEY,
XAI_API_KEY).
help · version
What you'd expect.
Exit codes
0 success/green · 1 operation failed (validate red, bad input to an operation) ·
2 usage errors (no project found, missing arguments, refused overwrite).