betamax 0.1.15

Rust-first VHS-style terminal capture CLI
betamax-0.1.15 is not a library.
Visit the last successful build: betamax-0.1.0

Betamax

Betamax is a Rust-first terminal capture CLI in the spirit of VHS. It runs tape files in a real PTY, feeds terminal output through libghostty-vt, rasterizes frames in process with cosmic-text and swash, and writes GIFs, screenshots, videos, or structured terminal state.

The goal is VHS-style authoring without a browser, server, xterm.js, or shelling out to a terminal web stack. Betamax is useful for project demos, CLI documentation, release notes, and snapshot-style tests for terminal applications.

Install

Betamax currently supports macOS and Linux. Windows is not supported because the upstream libghostty-vt-sys native build does not support Windows.

Install the CLI with Homebrew from joshka/homebrew-tap:

brew install joshka/tap/betamax

If Homebrew requires trusted taps, trust the formula first:

brew trust --formula joshka/tap/betamax

Or install from crates.io with cargo-binstall:

cargo binstall betamax

If cargo-binstall is not installed, install it first:

cargo install cargo-binstall

Source installs are mainly for maintainers. Betamax uses the safe libghostty-vt Rust wrapper; its libghostty-vt-sys dependency fetches a pinned Ghostty source commit and runs Zig 0.15.2 to build the native VT library. In a checkout, use mise to get the pinned toolchain:

mise install
mise run install-local

Other toolchain managers can work too, including Nix or a manually installed Zig 0.15.2 on PATH. mise is the documented path because it works for this repository today. The specific Zig version is an upstream Ghostty build requirement until Ghostty supports newer Zig releases such as 0.16.

MP4 and WebM output require ffmpeg on PATH; GIF, PNG, screenshots, and state JSON are written in process.

# macOS
brew install ffmpeg

# Debian/Ubuntu
sudo apt-get update
sudo apt-get install ffmpeg

A Tape

Tape files describe the terminal session to run and the artifacts to write:

Output examples/output/basic.gif
Output examples/output/basic.png
Output examples/output/basic.state.json

Set Shell "bash"
Set Theme "Aardvark Blue"
Set FontSize 28
Set Width 924
Set Height 534
Set Margin 12
Set WindowBar Colorful
Set BorderRadius 8

Hide
Type "cargo build --quiet"
Enter
Wait
Show

Type "printf 'hello from betamax\n'"
Enter
Wait+Screen "hello from betamax"
Screenshot examples/output/basic-checkpoint.png
Hide
Type "exit"
Enter

Run it with:

betamax run demo.tape

Hide and Show let setup and teardown happen without appearing in the final animation. Wait commands can block on time, a line, the whole screen, or a regular expression, so tapes can be stable even when terminal programs do real work.

What It Can Write

Output Use case
GIF README demos, release notes, docs pages
PNG Final-frame screenshots
Screenshot command Checkpoint screenshots from the middle of a run
MP4 and WebM Video assets encoded through ffmpeg
Frame directory Individual rendered frames for debugging or custom tooling
State JSON Viewport, scrollback, text, and style spans for tests

Examples

The repository includes tapes that exercise the core behavior:

Tape Demonstrates
examples/quick-start.tape installing, help, new, and nested run
examples/basic.tape typing, wait, theme, window bar, border radius
examples/hide-show.tape hidden setup and hidden trailing cleanup
examples/waits.tape line, screen, regex, and default prompt waits
examples/keys.tape key commands, repeats, editing, and interrupt
examples/clipboard-env.tape Env, Copy, and Paste
examples/outputs.tape GIF, PNG, JSON, screenshot, state, frame dir
examples/scrollback.tape scrollback-inclusive state JSON
examples/text-styles.tape ANSI styles, truecolor, and styled state spans
examples/layout.tape padding, margin, fill, window bar, radius
examples/presentation-overlays.tape captions plus keyboard overlay layout
examples/themes.tape copied Ghostty themes and palette mapping
examples/video.tape GIF, MP4, and WebM from one capture

Quick Start

Quick Start Betamax GIF

Basic

Basic Betamax GIF

Hide And Show

Hide and Show Betamax GIF

Themes

Ghostty theme Betamax GIF

Themes And Styling

Betamax ships copied Ghostty themes and can also read user Ghostty theme directories. List theme names with:

betamax themes
betamax themes --json

Tapes can control width, height, font size, padding, margin, border radius, window bar style, fill color, typing speed, playback speed, and prompt text. The defaults are chosen to feel close to VHS: a readable terminal size, a visible frame, and a simple > prompt unless a tape asks for a real shell prompt.

Captions and keyboard overlay chips are presentation-only annotations for visual outputs. When a tape uses them, Betamax reserves a bottom presentation row before deriving the terminal grid so labels do not cover terminal content. Captions align left, keyboard chips align right, and long captions truncate with ... instead of wrapping into the chips. Caption glyphs are clipped to their reserved width as a final guard for font fallback and unusually wide characters.

Terminal Testing

Betamax can be used as a terminal test harness, not only as a GIF generator. A tape can run an interactive program, wait until expected text appears, capture screenshots at important states, and write structured state JSON that snapshot tests can compare with tools such as insta.

State JSON includes:

  • viewport text
  • scrollback text
  • a compact style table
  • styled text spans that avoid cell-by-cell verbosity

That makes it possible to test terminal UI behavior as text and style data, while still keeping PNG or GIF output available for visual review.

Differences From VHS

Betamax intentionally keeps a smaller architecture than VHS:

Area Betamax status
Architecture PTY plus libghostty-vt, no browser/server/xterm.js
GIF/PNG/state In process
MP4/WebM Supported through ffmpeg
Themes Copied Ghostty themes plus inline JSON themes
Window styling Rust composition
Testing snapshots JSON state with viewport, scrollback, and styles
Source Parsed but intentionally not executed
record/serve Intentionally not implemented
publish Intentionally not implemented

See Differences From VHS for the full comparison.

Documentation