Visual Plan

CLI reference

vplan is the CLI that renders a plan .mdx file to a self-contained HTML page. Install it with npm i -g vplan (see Installation).

render

vplan <file.mdx>

Opens the plan in an interactive review session by default (see Review mode). Pass --static to instead compile a single self-contained <file>.plan.html next to the source and open it. render is the default command, so vplan plan.mdx and vplan render plan.mdx are the same. The file argument may be - (or omitted) to read the plan from stdin.

FlagEffect
--staticRender a static HTML page and open it instead of the review session (the pre-review default).
--watchStart a hot-reloading dev server instead of writing a file. Long-running; stops on Ctrl+C.
--port <number>Port for the --watch dev server (default 9140, auto-incrementing if taken).
--out <path>Write the HTML to <path> instead of <file>.plan.html (implies --static).
--stdoutWrite the rendered HTML to stdout instead of a file (implies --static; composes in a pipeline; never auto-diffs).
--reviewOpen the interactive review session (now the default; kept for compatibility).
--no-daemonReview without the shared queue daemon, using a one-shot in-process server.
-i, --iteration <n>Plan revision number shown in the review bar; increment it each re-review.
--timeout <duration>Max wait for review feedback, e.g. 15m, 30s, 1h (default 15m).
--diff <path>Diff this render against an explicit baseline plan, overriding the snapshot cache.
--no-diffSkip iteration diffing (do not read or write the snapshot cache).
--no-openDo not open the result in the browser.

For a one-shot HTML file use --static (or --stdout for a pipeline), not --watch (which serves a local URL and writes no file).

Review mode

vplan <file.mdx> opens the plan as an interactive review session: the reviewer comments on sections or selected text, answers any <Questions> inline, then clicks Approve, Deny, or Iterate. The command blocks until they submit, prints the decision, comments, and answers to stdout, then exits with a decision-specific code (see Exit codes). It is a long-running foreground server; a closed tab counts as Deny, and --timeout bounds the wait.

Reviews join a shared queue so several plans share one tab: vplan review <files...> enqueues several at once, and vplan open opens (or pre-warms) the queue tab on its own. See Review mode for the demo, the queue, and the full session walkthrough.

Iteration diffing

A render of a plan file snapshots its source (under ~/.vplan/snapshots, keyed by absolute path), and the next render of that path diffs the new source against the snapshot, marking added and edited sections git-gutter style with an “N changed” summary so the reviewer re-reviews only the delta. Diffing applies to render, --watch, and --review; a --stdout render never auto-diffs (it stays deterministic for pipelines). Use --diff <path> to force an explicit baseline without touching the cache, or --no-diff to opt out (for example a clean first look).

check

vplan check <file.mdx>

Validates a plan without rendering it, the self-correction loop. It reports MDX compile errors plus static component checks as file:line:col, naming the valid values for bad enums and flagging unknown components. It also validates each mermaid diagram and math block, and rejects markdown images (which would break the self-contained output).

Once a plan parses cleanly, check also runs an author-time quality lint that flags weak renders before a human sees them: a plan that is all prose with no structure, a Phase that is a wall of prose with no visual, a wide left-to-right mermaid diagram that will shrink to illegibility, an over-long Matrix cell, a -- comment on a FileTree move row, or a Chart whose series differ wildly in scale. These surface as warnings, and a warning fails the check (non-zero exit) just like an error, so the lint is not advisory. The quality lint runs only on the check command; the programmatic checkPlan runs the static checks alone.

Run check before showing a plan to a user, so they never see a broken render.

export

vplan export <pdf|jpg> <file.mdx>

Builds the same self-contained page, then renders it to a static file with a headless Chromium: pdf prints a paginated A4 document, jpg a full-page hi-dpi screenshot. The output goes to <file>.pdf / <file>.jpg next to the source and opens. See Exporting for when to reach for it over the HTML page.

FlagEffect
--out <path>Write to <path> instead of <file>.<pdf|jpg>. Required when reading from stdin.
--theme <theme>Override the baked color scheme: light, dark, or system.
--browser <path>Render with a specific Chromium binary instead of auto-discovering one.
--no-openDo not open the exported file.

Export needs a Chromium. It uses a system Chrome or Edge if present, then a playwright-installed Chromium; if none is found it tells you to run npx playwright install chromium.

share

vplan share <file.mdx>

Prints a stateless visualplan.dev/view?data=... link that encodes the entire plan (its MDX source, deflate plus base64url) in the URL, so anyone can open the rendered plan with no files, server, or account. It validates the plan first, so a broken plan is never shared, and reads a file or stdin (-). This is the CLI equivalent of the share button on a rendered page.

components

vplan components

Prints the component vocabulary cheat-sheet with the exact prop signatures. See Authoring plans for the full guide.

config

vplan config            # show the current settings
vplan config get <key>  # print one setting
vplan config set <key> <value>
vplan config path       # print the config file path

Views and edits persistent settings stored in ~/.vplan/config.json:

  • theme (light, dark, or system): the default color scheme baked into every rendered plan. The in-page settings cog overrides this per view in the browser (via localStorage) and never writes the file, so the on-disk default and the in-page override are separate layers.
  • daemonTimeout (a duration like 15m, default 15m): how long the review queue daemon lingers after its queue empties before exiting, so a quick re-plan reuses the warm tab.

Exit codes

  • 0, success (rendered, or check found no issues).
  • Non-zero, a compile error or a check failure (errors or quality-lint warnings). The reported file:line:col issues are printed to stderr.
  • A --review session exits by the reviewer’s decision: 0 Approve, 1 Deny, 2 Iterate, 3 timeout. A closed tab counts as Deny.