TermPlot renders Plotly plots inside terminals. It runs a local daemon
(termplotd) with a browser-backed React Router app, screenshots the rendered
plot, and prints the image using terminal image protocols.
TermPlot v1 is macOS-focused. Ghostty uses Kitty graphics output, and iTerm2 uses iTerm2 OSC 1337 inline images.
Real terminal screenshot probes require macOS permissions for the app or shell that launches them. Grant Screen Recording permission before running the Ghostty or iTerm2 probe scripts. Permission prompts are setup failures for automation; the probes do not accept dialogs on your behalf.
Install dependencies and build:
pnpm install
pnpm run playwright:install
pnpm run buildVerify the Playwright Firefox renderer:
pnpm run playwright:verifyTermPlot uses Playwright Firefox for browser screenshots. Chromium was tested but rejected in this environment because headless Chromium hung while connecting to macOS SkyLight.
Render a Plotly config to a PNG file:
node build/bin/termplot.js render \
'{"data":[{"x":[1,2,3],"y":[2,5,3],"type":"scatter"}],"layout":{"width":640,"height":480},"config":{"staticPlot":true}}' \
--output /tmp/termplot.pngRender directly to the terminal:
node build/bin/termplot.js render \
'{"data":[{"x":[1,2,3],"y":[2,5,3],"type":"scatter"}],"layout":{"width":640,"height":480},"config":{"staticPlot":true}}' \
--protocol autoUse --protocol kitty for Ghostty and --protocol iterm2 for iTerm2 when
automatic detection is not enough.
Source the wrapper:
source termplot.nuWrite a PNG and receive structured metadata:
let plot = {
data: [{ x: [1, 2, 3], y: [2, 5, 3], type: "scatter" }]
layout: { width: 640, height: 480 }
config: { staticPlot: true }
}
$plot | termplot --output /tmp/termplot.pngReturn binary PNG data to the Nushell pipeline:
$plot | termplot | save --force /tmp/termplot.pngDisplay in the terminal from Nushell:
$plot | termplot --display --protocol autoMost render commands auto-start termplotd when needed and reuse it for later
plots. The default idle TTL is one hour. Private sockets are useful for tests:
node build/bin/termplot.js daemon status --socket /tmp/termplotd.sock
node build/bin/termplot.js daemon start --socket /tmp/termplotd.sock --ttl-ms 3600000
node build/bin/termplot.js daemon stop --socket /tmp/termplotd.sockDaemon options accepted by render commands include --socket, --ttl-ms,
--timeout-ms, and --log.
Run all automated checks:
pnpm test
pnpm run smoke
pnpm run pack:checkThe full-stack terminal probes live in scripts/probe-ghostty-termplot.sh and
scripts/probe-iterm2-termplot.sh. They open real terminal windows, render real
TermPlot output, screenshot it, assert pixels, and clean up only processes they
started.
- Run
pnpm run playwright:installif Firefox is missing. - Use
--log /tmp/termplotd.logto inspect daemon startup and render errors. - Use
--protocol kittyin Ghostty and--protocol iterm2in iTerm2 if--protocol autocannot identify the terminal. - Stop a private daemon with
node build/bin/termplot.js daemon stop --socket <path>.