CLI
The same rendering pipeline as the extension and the MCP server, as shell commands. Render a figure source to SVG or PNG, validate sources in CI, list formats, or host the MCP server — with output byte-for-byte identical to what quarto render produces.
Install
Nothing to install with npx:
npx livefigures --helpOr use the copy that ships inside the extension — every project that ran quarto add already has it:
node _extensions/seandavi/livefigures/cli.mjs --helpNode ≥ 18 is the only requirement, same as the extension.
Commands
# render a source file (format inferred from the extension)
livefigures render figures/arch.excalidraw -o arch.png
livefigures render figures/deps.dot -o deps.svg
# render from stdin
echo 'digraph { a -> b }' | livefigures render - --format graphviz > g.svg
# check sources without producing output — exit 1 + the exact
# quarto render error on a bad source
livefigures validate figures/*.dot figures/*.vl.json
# what can I write?
livefigures formats
livefigures formats --json
# host the MCP server (stdio)
livefigures mcpRender options mirror the extension: --theme light|dark, --background transparent|scene (Excalidraw, Vega-Lite and Vega only), --scale <n> for PNG.
Look at the figure, not just the exit code
validate catches broken sources. It cannot catch the more common problem: a figure that renders perfectly and is still wrong. Those never raise an error, so the only thing that catches them is rendering the figure and looking at it — which is what render -o is for.
What to look for, and the usual repair:
| What you see | Fix |
|---|---|
| Text too small on a slide — the figure is tall and height-bound | Check the output aspect ratio against the target medium; restructure the figure |
| A row laid out as a diagonal staircase (Graphviz) | {rank=same; a; b; c; } |
| Two opposing edges overlapping, labels colliding | One dir=both edge with a single label |
| An edge label sitting on the arrow | Shorten it, or lengthen the edge (nodesep / ranksep) |
Clusters reordered after a rankdir change (Graphviz) |
Disconnected-cluster order is not rankdir-stable — re-check visually after any such edit |
A literal {...} appearing as text (nomnoml) |
Inline directives don’t work everywhere; define #.name: fill=… and use [ Label] |
| Legend or axis labels truncated (Vega-Lite) | Raise labelLimit, e.g. legend: {labelLimit: 300} |
| A cluster label clipped at the figure edge (Graphviz) | Reduce the figure width in the document, or add graph margin |
Agents get the same checklist from the skill, and the MCP server returns the rendered image in-context so an agent can do this pass itself.
Validate figures in CI
validate exits non-zero on the first bad source, so a one-line CI step keeps broken figures out of main:
- name: Validate figure sources
run: npx -y livefigures validate figures/*See also
- MCP server — the same tools, callable by your agent, with images the agent can see.
- Agent skill — teach an agent when and how to use all of this.