promptbook

CLI

promptbook ls, resolve, view, lint, eval, bundle, watch, annotations.

The CLI ships with the @markbrutx/promptbook-cli package. Install it globally or run via npx:

npm i -g @markbrutx/promptbook-cli
# or
npx @markbrutx/promptbook-cli <command>

Run from any folder that contains promptbook.json, or pass --dir <path> explicitly.

Streams

  • stdout = the payload (resolved prompt text, JSON when --json).
  • stderr = explanations (the --explain trace), warnings, errors.

This lets you pipe promptbook resolve … | curl … to a model API while still seeing the trace on your terminal. NO_COLOR is honored.

--help

The list below is captured from the built CLI itself, so it cannot drift from what ships.

promptbook · compose prompts from reusable fragments

Usage:
  promptbook <command> [options]

Commands:
  resolve [<book>/]<prompt>  Assemble a prompt and print it to stdout (--all: every book)
  lint [<prompt>]         Run static checks; with no prompt, book rules only
  eval [<name|glob>]      Run fixtures through a model adapter, report pass-rate
  bundle [<dir>]          Compile a prompts folder into an importable book module (--all/--check)
  watch [<dir>]           Rebuild book.generated.ts as fragments/rules/compositions change
  view                    Start the local web viewer over the workspace (book switcher)
  annotations <action>    Drain the viewer's feedback queue: list | resolve <id> | clear
  ls                      List compositions and fragments (--all: cross-book inventory)

A <book>/<comp> operand addresses one book in a multi-book workspace; a bare
name resolves by uniqueness. With a single-book --dir, names work unqualified.

Options:
  --dir <path>            Prompts folder (default: promptbook.json promptsDir, else ./prompts)
  --ctx key=value         Context value, repeatable (coerced to boolean/number/string)
  --context-file <json>   Merge context from a JSON file (--ctx overrides it)
  --explain               resolve: print the resolution trace to stderr
  --json                  Emit machine-readable JSON on stdout
  --max-tokens N          lint: token-budget ceiling (overrides promptbook.json)
  --strict                lint: exit non-zero on warnings too
  --model <id>            eval: model id for the adapter (overrides promptbook.json)
  --samples N             eval: default samples per fixture (default 1; a fixture's own samples wins)
  --threshold R           eval: a fixture passes when passRate >= R (default 1)
  --lint                  eval: run a static lint gate over every variant first
  -o, --out <file>        bundle/watch: write to a file (default: stdout for bundle, <bookDir>/book.generated.ts for watch/--all)
  --plain                 bundle/watch: emit a plain module (no type-only import; e.g. for Deno)
  --check                 bundle: compare with the existing output; exit 1 on drift or missing artifact
  --exclude-code-prompts  bundle/watch: serialize code-prompts as an empty map (runtime-lean bundle)
  --port N                view: port for the viewer server (default: a free port)
  --no-open               view: do not open the browser after starting
  --fragments             ls: list fragments only
  --compositions          ls: list compositions only
  --all                   ls/resolve/bundle: span every book in the workspace
  -h, --help              Show this help
  -v, --version           Show the version

Streams: stdout = payload (prompt text or JSON); stderr = explanations and errors.

The headline commands

resolve · assemble one prompt

promptbook resolve reply --ctx model=gpt --ctx locale=English
promptbook resolve reply --ctx model=claude --explain

--explain prints the rule trace to stderr.

view · open the local viewer

promptbook view --dir examples/sports-broadcast

A web app at http://localhost:<random-port> listing every composition, fragment, and code-prompt; pick a context combination to re-assemble live and diff two variants. The bundled live demo is the same viewer running entirely in the browser.

lint · static checks, no model

promptbook lint
promptbook lint reply

Without an argument, only book-level rules run (dead rule, unused fragment, dangling reference). With a composition name, resolved-scope rules also run (token budget, banned tokens, language-directive position).

eval · run fixtures through a model adapter

promptbook eval gpt-json --model openai/gpt-4o-mini --threshold 1

Requires an adapter package (e.g. @markbrutx/promptbook-openrouter). The core itself never makes a model call.

bundle · compile a book to an importable module

promptbook bundle examples/sports-broadcast -o book.generated.ts
promptbook bundle --check    # exit 1 on drift in CI
promptbook bundle --all      # every book in a multi-book workspace

The runtime then imports book and calls resolveBook(book, prompt, context), so no filesystem touches at request time. This is the path the demo site takes, with JSON output instead of TS.