svg-term-recorder: The tiny recorder that makes terminal demos feel rehearsed

A Bun-powered TypeScript script, a virtual clock, and SVG output turn messy shell sessions into lightweight documentation assets.

6 min read • View on GitHub • More from dbuezas

A terminal window staged like a small theater performance. A conductor sits at a desk while a shell prompt is cued like an instrument, and a clock mechanism turns behind the scenes. The scene explains that this tool is really about pacing a demo, not just capturing one.
The project treats terminal recording as direction, not just capture.
Key Takeaways

The demo is the product

Terminal demos are easy to underestimate. They look like a formatting problem, but they are really a timing problem: too fast and nobody can follow, too slow and the demo feels padded, too heavy and it stops being a documentation asset. svg-term-recorder takes that problem seriously and solves it with a simple trick, it decouples execution speed from presentation speed.

The surprise is the pacing layer. Real commands run, the recorder watches for the prompt, and virtual time makes the result feel human.

That is the core idea. The script runs the shell for real, watches the output buffer, waits until the prompt comes back, and only then advances to the next step. The output is not synthetic terminal text. The timing is synthetic, which is exactly why the finished animation feels polished instead of jittery.

let virtualTime = 0;

function castWrite(data: string) {
  const realTime = performance.now() - start;
  const t = (virtualTime + realTime) / 1000;
  entries.push(JSON.stringify([+t.toFixed(6), 'o', data]));
}

That small pattern does a lot of work. When the recorder is in fast mode, the virtual clock can advance without waiting for the wall clock. The shell still executes, the prompt still matters, and the exported cast still has believable pauses. The script is also built around prompt detection, so the next command does not begin until the shell has actually settled.

Why Bun is the enabler

The repo stays tiny because it leans on Bun where a heavier stack would usually show up. TypeScript runs directly, process spawning stays close to the metal, and there is no separate build pipeline to babysit. That matters because the tool is not trying to be a platform. It is trying to be a sharp little utility that starts fast, records one session, and gets out of the way.

const proc = Bun.spawn(['zsh'], {
  terminal: {
    cols: 120,
    rows: 30,
    data(_terminal, data) {
      // record terminal output here
    }
  }
});

This is where the project feels opinionated in a good way. Bun is not just a trendy runtime here. It is the reason a terminal recorder can stay almost comically small while still doing the messy work of launching a shell, capturing bytes, and writing them into a format another renderer can understand.

Why SVG wins here

A split illustration contrasts a bulky screen recording workflow with a compact SVG document. One side has a long film reel, stacked media files, and visual weight. The other side shows a crisp terminal frame held like a document page, which explains why the output is better suited to READMEs and docs.
The output choice is the point. SVG turns a demo into an embeddable artifact.
ToolInput modelRuntimeOutputStrengthTradeoff
svg-term-recorderLive shell session with prompt-aware pacingBun / TypeScriptAnimated SVGTiny single-file workflow with virtual timeNiche ecosystem
termtosvgRecorded terminal sessionPythonAnimated SVG or frame setMature and flexibleHeavier runtime
term-to-svgscript command recordingsPHPAnimated SVGLightweight and dependency-freeDifferent capture model
GIF or screen recordingLive screen captureMedia toolsGIF or videoFamiliar and easy to shareLarge files and less doc-native

The comparison is less about feature count and more about workflow philosophy. GIFs and screen recordings are familiar, but they are bulky and awkward in docs. The SVG tools are closer to the shape of the problem, and svg-term-recorder narrows the niche further by making the pacing itself part of the design.

A utility extracted from real work

WSJ-style hedcut portrait of dbuezas based on a verified GitHub avatar. The portrait gives a face to the project's maintainer and reinforces that this is a real utility built by one person, not a broad platform team.

There is no big public origin story to lean on here, and that is part of the appeal. The repository reads like a tool extracted from real documentation work, built by dbuezas to solve a recurring annoyance with enough precision to be reusable. It has the feel of something made because the maintainer needed a better way to ship a demo, then decided to keep it around for everyone else.