Skip to main content

Keys File Format

Keys files are declarative scripts that define terminal interactions for Betamax. Each file is self-describing and contains all the information needed to reproduce a terminal session.

Betamax keys file workflow

Overview​

A keys file consists of:

  • Comments - Lines starting with #
  • Settings directives - Configure terminal dimensions, delays, and dependencies
  • Actions - Control timing, waiting, capturing, and recording
  • Keys - Individual keystrokes to send to the terminal

Each line contains exactly one directive, action, or key. Blank lines are ignored.

Comments and Blank Lines​

Comments start with # and continue to the end of the line. Use them to document your keys files:

# This is a comment explaining the next action
@sleep:500

# Navigate through the menu
j
j
Enter

Blank lines are ignored and can be used to organize your file into logical sections.

Settings Directives​

Settings at the top of a keys file make it self-describing and reproducible. CLI flags override these values when specified.

DirectiveDescriptionCLI Override
@set:cols:NTerminal width in columns--cols
@set:rows:NTerminal height in rows--rows
@set:delay:MSDefault delay between keys in milliseconds-d, --delay
@set:output:DIROutput directory for captures-o, --output-dir
@set:timeout:SECTimeout for wait operations in seconds-t, --timeout
@set:shell:PATHShell to use for consistent environment--shell
@set:gif_delay:MSFrame duration in GIF playback (default: 200ms)-
@set:speed:NGIF playback speed multiplier, 0.25-4.0 (default: 1.0)-
@set:loop_offset:MSDuplicate first MS of frames at end for seamless looping-
@set:theme:NAMEApply a color theme for decorations (see Theme System)-
@set:window_bar:STYLEAdd macOS-style window bar: colorful, colorful_right, rings, none-
@set:bar_color:RRGGBBWindow bar background color (6 hex digits, no # prefix)-
@set:bar_height:NWindow bar height in pixels (default: 30)-
@set:border_radius:NRounded corner radius in pixels-
@set:margin:NOuter margin in pixels-
@set:margin_color:RRGGBBMargin background color (6 hex digits, no # prefix)-
@set:padding:NInner padding in pixels-
@set:padding_color:RRGGBBPadding background color (6 hex digits, no # prefix)-
@set:shadow:BOOLEnable drop shadow (true or false)-
@set:shadow_blur:NShadow blur radius in pixels (0-100, default: 15)-
@set:shadow_offset_x:NHorizontal shadow offset (-200 to 200, default: 0)-
@set:shadow_offset_y:NVertical shadow offset (-200 to 200, default: 8)-
@set:shadow_opacity:NShadow opacity 0.0-1.0 (default: 0.4)-
@set:shadow_color:RRGGBBShadow color (6 hex digits, default: 000000)-

Note: Color values use 6 hex digits without the # prefix because # starts comments in keys files.

Example Settings Block​

@set:cols:120
@set:rows:40
@set:delay:100
@set:output:./screenshots
@set:shell:/bin/bash
@set:gif_delay:150
@set:speed:1.5

# Decoration settings for polished GIFs
@set:window_bar:colorful
@set:bar_color:282a36
@set:border_radius:8
@set:margin:20
@set:margin_color:1a1a2e

# Drop shadow for floating window effect
@set:shadow:true
@set:shadow_blur:20
@set:shadow_offset_y:10
@set:shadow_opacity:0.5

Theme System​

Betamax includes 30+ built-in themes for styling GIF decorations. Themes set colors for the window bar, padding, and margin to match popular terminal color schemes.

Using Themes​

Apply a theme with @set:theme:NAME:

@set:theme:dracula
@set:window_bar:colorful
@set:padding:10
@set:margin:20
@record:start
# ... recording ...
@record:stop:demo.gif

Available Themes​

Dark themes:

  • dracula - Dracula color scheme
  • catppuccin-mocha, catppuccin-macchiato, catppuccin-frappe - Catppuccin variants
  • gruvbox-dark - Gruvbox dark
  • nord - Nord theme
  • tokyo-night, tokyo-night-storm - Tokyo Night variants
  • one-dark - Atom One Dark
  • monokai - Monokai
  • solarized-dark - Solarized Dark
  • github-dark, github-dark-dimmed - GitHub Dark variants
  • ayu-dark, ayu-mirage - Ayu variants
  • rose-pine, rose-pine-moon - Rose Pine variants
  • everforest-dark - Everforest Dark
  • kanagawa - Kanagawa
  • material, material-darker - Material variants
  • night-owl - Night Owl
  • palenight - Material Palenight
  • synthwave-84 - Synthwave '84
  • cyberpunk - Cyberpunk theme

Light themes:

  • catppuccin-latte - Catppuccin Latte
  • gruvbox-light - Gruvbox Light
  • solarized-light - Solarized Light
  • github-light - GitHub Light
  • rose-pine-dawn - Rose Pine Dawn
  • everforest-light - Everforest Light

Theme Precedence​

Themes provide default colors that can be overridden:

@set:theme:dracula        # Base colors from Dracula
@set:bar_color:ff0000 # Override just the bar color

Explicit color settings take precedence over theme values.

Note on Terminal Colors​

Themes style the decorations (window bar, padding, margin) around your terminal content. The terminal content itself uses colors from termshot's built-in ANSI palette. For the most visually consistent results, use a terminal theme that complements your decoration theme.

Dependency Checking with @require​

The @require:CMD directive checks that a command exists in PATH before running the keys file. This allows fast failure with clear error messages.

@require:termshot    # Required for PNG output
@require:aha # Required for HTML output
@require:ffmpeg # Required for GIF recording

If the required command is not found, Betamax exits immediately with an error.

Modular Keys Files with @source​

The @source:PATH directive imports keys from another file, enabling reusable setup sequences and modular organization.

# main.keys
@source:common/setup.keys # Import shared setup
@source:themes/dracula.keys # Import decoration settings

@record:start
# ... your recording ...
@record:stop:demo.gif

Path Resolution​

Paths are resolved relative to the current file's directory:

project/
├── demos/
│ └── main.keys # @source:../common/setup.keys
├── common/
│ └── setup.keys # Resolves correctly

Features​

  • Relative paths: Resolve from the sourcing file's directory
  • Nested imports: Sourced files can themselves use @source
  • Circular detection: Betamax detects and reports circular imports with the full import chain
  • Depth limit: Maximum 10 levels of nesting to prevent runaway imports
  • Settings preservation: @set directives from sourced files are applied

Example: Shared Setup​

# common/terminal-setup.keys
@set:cols:80
@set:rows:24
@set:delay:80
@require:termshot
@require:ffmpeg
# demos/vim-demo.keys
@source:../common/terminal-setup.keys
@set:gif_delay:150

@sleep:400
@record:start
i
@frame
# ... rest of recording

Error Handling​

Betamax provides clear error messages for common issues:

  • File not found: Shows the full path that couldn't be found
  • Circular import: Shows the complete import chain (A → B → C → A)
  • Typo detection: Suggests @source if you use @import, @include, etc.

Actions​

Actions control the flow of execution, timing, and output capture.

ActionDescription
@sleep:MSWait MS milliseconds before continuing
@sleep:MS:captureWait MS milliseconds, capture frames before and after (opt-in for GIF recording)
@wait:PATTERNWait for text pattern to appear in terminal
@wait:/REGEX/Wait for regex pattern to match in terminal
@captureCapture terminal state to stdout
@capture:NAME.pngSave screenshot as PNG (requires termshot)
@capture:NAME.htmlSave as HTML with colors (requires aha)
@capture:NAME.txtSave as plain text with ANSI codes
@capture:NAMESave in all available formats
@record:startStart GIF recording session
@record:pausePause frame capture (session continues), auto-captures on resume
@record:resumeResume frame capture, capturing current state
@hideHide recording - keys execute but frames not captured
@showShow recording - resume capturing frames (no auto-capture)
@frameCapture current state as a GIF frame (during recording)
@record:stop:NAME.gifStop recording and save animated GIF
@repeat:NBegin a loop that repeats N times
@endEnd the current @repeat loop
@pauseWait for Enter key (interactive debugging)

Wait Patterns​

Wait for specific text or patterns before continuing:

@wait:Ready           # Wait for literal text "Ready"
@wait:/Loading\.+/ # Wait for regex pattern

Capture Examples​

@capture:screenshot.png    # Save PNG only
@capture:output.html # Save HTML only
@capture:terminal.txt # Save text with ANSI codes
@capture:demo # Save demo.png, demo.html, and demo.txt

Loop with @repeat​

Use @repeat:N and @end to repeat a sequence of keys and actions:

@repeat:5
j
@frame
@end

This sends j five times, capturing a frame after each press.

Key Syntax​

Keys use tmux send-keys format. Most printable characters are sent literally.

Literal Keys​

Single characters are sent directly:

a
b
1
2

Special Keys​

KeySyntax
EnterEnter
EscapeEscape
TabTab
Shift+TabBTab
SpaceSpace
BackspaceBSpace
DeleteDC
Arrow keysUp, Down, Left, Right
Home / EndHome, End
Page Up / DownPPage, NPage
Function keysF1, F2, ... F12
Ctrl+keyC-c, C-v, C-x
Alt+keyM-x, M-a

Examples​

Escape          # Press Escape
C-c # Ctrl+C
M-x # Alt+X
F1 # Function key F1

Per-Key Timing​

Override the default delay for individual keys using the @MS suffix:

key@MS

The number after @ specifies milliseconds to wait after sending that key.

Examples​

j@50           # Press j, wait 50ms (fast navigation)
j@50
j@50
Enter@1000 # Press Enter, wait 1 second

This is useful for:

  • Rapid navigation - Use short delays like @50 for repeated keys
  • Waiting for responses - Use longer delays like @1000 after actions that take time

Complete Example​

Here is a complete keys file demonstrating all features:

# demo-capture.keys
# Captures a screenshot of a TUI application

# Settings - make this file self-describing
@set:cols:120
@set:rows:40
@set:delay:100
@set:output:./screenshots
@set:shell:/bin/bash

# Dependencies - fail fast if missing
@require:termshot

# Wait for application to start
@sleep:500

# Wait for ready indicator
@wait:Ready

# Navigate the menu quickly
j@50
j@50
j@50

# Select item and wait for it to load
Enter@500

# Capture the screenshot
@capture:demo.png

# Exit the application
q
y

GIF Recording Example​

# record-typing.keys
# Records an animated GIF of typing in vim

@set:cols:80
@set:rows:24
@set:delay:80
@set:gif_delay:150

@require:termshot
@require:ffmpeg

# Wait for vim to load
@sleep:400

# Start recording
@record:start

# Type "Hello" with frame after each character
i
@frame
H
@frame
e
@frame
l
@frame
l
@frame
o
@frame

# Exit insert mode
Escape
@sleep:300
@frame

# Quit vim
:q!
Enter

# Save the recording
@record:stop:typing-demo.gif

Loop Example​

# scroll-demo.keys
# Demonstrates scrolling with @repeat

@set:cols:80
@set:rows:24
@set:delay:100

@sleep:500
@record:start

# Scroll down 10 times
@repeat:10
j
@frame
@end

# Scroll back up 10 times
@repeat:10
k
@frame
@end

@record:stop:scroll-demo.gif

Shadow Example​

# shadow-demo.keys
# Creates a polished screenshot with drop shadow

@set:cols:80
@set:rows:20
@set:theme:dracula
@set:window_bar:colorful
@set:border_radius:10
@set:padding:8

# Enable drop shadow
@set:shadow:true
@set:shadow_blur:20
@set:shadow_offset_y:10
@set:shadow_opacity:0.5

@require:termshot

@sleep:300
echo "Hello from betamax!"
@sleep:200
@capture:shadow-demo.png

Shadow works with both PNG screenshots (@capture:NAME.png) and animated GIFs (@record:stop:NAME.gif). The shadow is rendered with full RGBA transparency.