Skip to content

Tape Reference

This is the canonical reference for Betamax tape files. Use it with Tape Files, Outputs, and Examples when authoring tapes.

Betamax parses a tape before it starts a shell. Syntax errors, unknown commands, invalid regexes, unknown settings, type mismatches, unsupported output extensions, and startup-command ordering errors fail before the PTY is spawned.

  • A tape is line oriented.
  • Blank lines are ignored.
  • Lines whose trimmed form starts with # are comments.
  • Tokens are parsed with shell-like quoting and escaping through shell_words.
  • One physical line may contain more than one command, such as Type "echo hi" Enter.
  • Startup commands must appear before runtime commands.

Startup commands are Output, Require, Set, and Env. Runtime commands include typing, keys, waits, sleeps, screenshots, state checkpoints, Hide, Show, Copy, and Paste.

CommandBehaviorNotes
Output <path>.gifWrite an animated GIFEncoded in process
Output <path>.pngWrite a final-frame PNGEncoded in process
Output <path>.jsonWrite final terminal stateSee State JSON
Output <path>.mp4Write MP4 videoRequires ffmpeg on PATH
Output <path>.webmWrite WebM videoRequires ffmpeg on PATH
Output <dir>Write numbered PNG frames into a directoryExtensionless path only
Screenshot <path>.pngWrite a checkpoint screenshot at this commandOnly .png is supported
State <path>.jsonWrite checkpoint terminal stateOnly .json is supported

Primary Output paths are grouped by output kind when written, not returned in source order. Checkpoint Screenshot and State commands are side effects at their position in the tape.

Settings use Set <name> <value>. Values are parsed before the setting name is interpreted: percentages become numbers in 0.0..=1.0, then numbers, booleans, durations, and finally strings are attempted in that order. Known settings reject the wrong value kind, so Set Width "wide" is an error rather than a quiet fallback.

SettingValue kindDefaultBehavior
Shellstring$SHELL or shShell command and optional arguments; split with shell-like rules
ThemestringAardvark BlueTheme name loaded from user Ghostty themes or bundled themes
FontFamilystringJetBrains MonoPreferred font family passed to the renderer
FontSizenumber22Font size in pixels
LetterSpacingnumber1Extra pixels between terminal cells
LineHeightnumber1Multiplier applied to the font size
Widthnumber1200Raw terminal canvas width before margin/window decoration
Heightnumber600Raw terminal canvas height before margin/window decoration
Paddingnumber60Inner padding between the terminal cells and raw canvas edge
Frameratenumber50Capture cadence in frames per second
TypingSpeedduration50msDelay between characters typed by Type
PlaybackSpeednumber1.0Output playback multiplier; does not speed up command execution
LoopOffsetnumber or percentage0.0Rotates animated output frames to move the loop boundary
CursorBlinkbooltrueSimulates cursor blink in captured frames
WaitTimeoutduration or number15sDefault timeout for wait commands; bare numbers are seconds
WaitPatternregex string>$Regex used by bare Wait
Marginnumber0Outer decoration margin in pixels
MarginFill#rrggbb stringtheme backgroundFill color for the outer margin; invalid colors fall back to theme bg
WindowBarstringempty / disabledNon-empty values draw a synthetic window bar
WindowBarSizenumber30Window bar height in pixels
BorderRadiusnumber0Rounded-corner mask radius in pixels

The terminal grid is derived after all settings are applied. Width, height, padding, font size, letter spacing, and line height determine the PTY columns and rows. Extremely small dimensions are clamped to at least one row and one column.

Adds a primary output. Supported extensions are .gif, .png, .json, .mp4, and .webm. An extensionless output path is treated as a directory for numbered PNG frames. Unsupported extensions fail before shell startup.

Fails early if a program is not present on PATH. This is useful for tapes that call optional tools such as git, rg, cargo, or ffmpeg. The check runs before output files are written.

Applies one setting from the table above. Set commands must appear before runtime commands because they affect shell startup, PTY size, capture timing, rendering, or output decoration.

Adds or overrides an environment variable for the spawned shell. Betamax applies its terminal defaults first, then tape Env values, so a tape can intentionally override variables such as TERM, COLORTERM, NO_COLOR, or application-specific flags.

Types text into the PTY one Unicode scalar at a time. Type@25ms "hello" overrides the default typing speed for that command. Use Type for printable text and key commands for terminal control keys such as arrows, tab, delete, and interrupt.

Key commands send terminal key sequences to the PTY. They accept an optional @duration suffix and an optional repeat count:

Enter
Enter@250ms
Down 3
Shift+Tab
Ctrl+C
Alt+F
Ctrl+Alt+Shift+X
F5

Supported named keys are Escape, Backspace, Delete, Insert, Down, Enter, Space, Tab, Left, Right, Up, PageUp, PageDown, Home, End, and F1 through F25. Single-character key tokens are accepted for modified combinations such as Ctrl+C.

Pauses tape execution while continuing to drain PTY output and capture frames. Durations accept compact forms such as 500ms, 1s, and 2m, split forms such as 500 ms, and bare numbers as seconds.

Waits for terminal text while continuing to drain output and capture frames. A bare Wait checks the current cursor line with WaitPattern, which defaults to the VHS-style prompt regex >$. Wait@5s overrides the timeout for that command.

Use /.../ for regex patterns and plain text for substring patterns.

Waits against the current cursor line. This is equivalent to bare Wait with an explicit target, and it is useful when the tape should make the target obvious.

Waits against all visible viewport text. Use this for command output, full-screen TUIs, status lines, or any situation where cursor position should not matter.

Stops appending frames to animated outputs. The PTY still runs, terminal state still updates, waits still work, and checkpoint outputs still see the current terminal. Use this for compilation, setup, or teardown that should not appear in the final GIF/video.

Resumes frame capture and immediately captures the current terminal. This reveals the prepared state without showing the hidden commands that produced it.

Writes an immediate PNG screenshot using the same theme and frame decoration as primary outputs. Only .png checkpoint screenshots are supported.

Writes an immediate terminal-state snapshot. The state includes viewport text, scrollback text, cursor metadata, a default style, compact style deltas, and styled text spans. See State JSON for the schema and snapshot-testing tradeoffs.

Copy stores text in Betamax’s tape-local clipboard. Paste writes that clipboard into the PTY. This does not touch the host operating system clipboard, which keeps tapes deterministic and safe for CI.

Source is parsed for VHS-language compatibility, but execution is intentionally not implemented. A tape containing Source returns a targeted error instead of silently skipping the include.

Betamax currently exposes these CLI commands:

CommandBehavior
betamax new <path>Write a starter tape with an inline command summary
betamax run <path>Parse, execute, render, and write requested outputs
betamax run -Read a tape from standard input
betamax run -o out.gif demo.tapeAppend one CLI-provided output to the tape
betamax validate <path-or-glob>Parse tapes without starting shells or writing outputs
betamax themesList theme names available to Set Theme
betamax themes --jsonPrint theme names as JSON
betamax themes --markdownPrint theme names as Markdown bullets

publish, record, and serve remain explicit not-implemented commands so users migrating from VHS get a clear error message.