Betamax is a Rust-first terminal capture tool in the spirit of
VHS. It reads tape files, runs commands in a PTY, feeds
terminal output through libghostty-vt, rasterizes frames in process with cosmic-text and
swash, and writes screenshots or animations.
The goal is VHS-style output without the browser/server/xterm.js stack. The current implementation
intentionally does not include serve, record, source, or publish.
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/betamaxIf Homebrew requires trusted taps, trust the formula first:
brew trust --formula joshka/tap/betamaxOr install from crates.io with cargo-binstall:
cargo binstall betamaxIf cargo-binstall is not installed, install it first:
cargo install cargo-binstallSource 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-localOther 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.
For local development or source checkouts, run from the workspace:
cargo run -- run examples/basic.tapeRender all local examples:
mise run render-examplesMP4 and WebM output require ffmpeg on PATH:
# macOS
brew install ffmpeg
# Debian/Ubuntu
sudo apt-get update
sudo apt-get install ffmpegThe script writes files under examples/output and copies them to target/betamax-examples for
local inspection. The GIF previews below are hosted as GitHub Release assets so they can render on
GitHub and crates.io without storing generated media in the source tree.
Output examples/output/basic.gif
Set Shell "bash"
Set Theme "Aardvark Blue"
Set FontSize 28
Set Width 900
Set Height 480
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"
Hide
Type "exit"
Enter
Hide and Show are useful for VHS-style tapes that hide setup or compile work and only reveal the
interesting terminal state. See the Tape Reference for the full command
and settings behavior.
The checked-in examples are small smoke-test tapes that demonstrate core behavior:
| Tape | Demonstrates | Main Output |
|---|---|---|
examples/quick-start.tape |
installing, help, new, and nested run |
quick-start.gif |
examples/basic.tape |
typing, wait, theme, window bar, border radius | basic.gif |
examples/hide-show.tape |
hidden setup and hidden trailing cleanup | hide-show.gif |
examples/waits.tape |
line, screen, regex, and default prompt waits | waits.gif |
examples/keys.tape |
key commands, repeats, editing, and interrupt | keys.gif |
examples/clipboard-env.tape |
Env, Copy, and Paste |
clipboard-env.gif |
examples/outputs.tape |
GIF, PNG, JSON, screenshot, state, frame dir | outputs.* |
examples/scrollback.tape |
scrollback-inclusive state JSON | scrollback.* |
examples/text-styles.tape |
ANSI styles, truecolor, and styled state spans | text-styles.* |
examples/layout.tape |
padding, margin, fill, window bar, radius | layout.gif |
examples/themes.tape |
copied Ghostty themes and palette mapping | themes.gif |
examples/screenshot.tape |
screenshots and terminal state JSON | screenshot.png |
examples/video.tape |
GIF, MP4, and WebM from one capture | video.* |
The video tape writes GIF, MP4, and WebM from the same captured frames. The GIF preview is shown here; the video files are generated next to it.
List available themes:
cargo run -- themes
cargo run -- themes --jsonTheme lookup searches user Ghostty theme directories first, then the copied themes in
crates/betamax-core/resources/ghostty/themes.
Betamax aims for the common VHS authoring flow, but the architecture is intentionally smaller and Ghostty-first. See Differences From VHS for the full comparison and remaining parity notes.
| 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 |
The main tradeoff today is video output: MP4 and WebM use ffmpeg as a focused encoder bridge.
Terminal execution and rasterization stay in process; video container encoding does not.
Betamax can also be used as a terminal testing harness. A tape can run an interactive terminal program, wait for text on the screen, capture PNG screenshots at checkpoints, write structured terminal state, and fail when expected terminal output does not appear before a timeout.
See Terminal Testing and State JSON for the test workflow and state snapshot format.
Questions, early ideas, and examples of Betamax in real projects belong in Discussions. If Betamax helped you make a demo, test a terminal UI, document a CLI, or replace part of an existing workflow, please share a screenshot, rendered tape, repo link, or short note in Show and tell.
- Documentation Site
- Tape Reference
- Terminal Testing
- State JSON
- Differences From VHS
- Contributing
- Development
- Security Policy
- Support
The Starlight docs site lives under site/ and can be run locally with:
pnpm install
mise run docs-site-dev