record-tui

Use when recording terminal demos, creating GIFs of CLI apps, writing VHS tape files, or generating demo recordings for TUI applications. Use when asked to "record a demo", "create a GIF of my CLI", "write a VHS tape", "make a terminal recording", "generate a demo for my TUI", or "set up VHS for CI".

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "record-tui" with this command: npx skills add antjanus/skillbox/antjanus-skillbox-record-tui

Record TUI - Terminal Demo Recording with VHS

Overview

Record polished terminal demos using Charmbracelet VHS. VHS turns .tape scripts into GIFs, MP4s, and WebMs — reproducible, version-controlled, and CI-friendly.

Core principle: Write tape files as code, not as screen captures. Every demo should be reproducible from a single .tape file.

When to Use

Use this skill when:

  • Recording a demo GIF for a README or docs
  • Creating video walkthroughs of CLI/TUI applications
  • Setting up automated demo recording in CI/CD
  • Writing .tape files for VHS
  • Troubleshooting VHS output quality (choppy GIFs, wrong dimensions, timing issues)

Avoid when:

  • Recording non-terminal content (use screen capture tools instead)
  • One-off manual recordings where reproducibility doesn't matter (use asciinema)
  • The app has no terminal interface

Prerequisites

VHS requires two dependencies:

# macOS
brew install charmbracelet/tap/vhs ffmpeg ttyd

# Debian/Ubuntu
sudo apt install ffmpeg && sudo snap install ttyd --classic
go install github.com/charmbracelet/vhs@latest

Verify: vhs --version && ffmpeg -version && ttyd --version

Phase 1: Plan the Recording

Before writing a tape file, answer these questions:

  1. What are you recording? — The exact command to launch the app
  2. What interactions to show? — Key presses, navigation, typing sequences
  3. What's the target format? — GIF (README), MP4 (docs site), WebM (web)
  4. What dimensions? — Match your app's ideal viewport

Recommended dimensions by use case:

Use CaseWidthHeightFontSize
README GIF120060020
Docs/tutorial140080018
Social media120063022
Full TUI app160090016
Compact CLI demo80040020

Phase 2: Write the Tape File

Tape File Structure

Every tape file follows this order:

# 1. Output declaration
Output demo.gif

# 2. Requirements (optional)
Require my-app

# 3. Settings (MUST come before commands)
Set Shell "bash"
Set FontSize 20
Set Width 1200
Set Height 600
Set Theme "Catppuccin Frappe"
Set WindowBar Colorful
Set Padding 20
Set TypingSpeed 75ms

# 4. Hidden setup (optional)
Hide
Type "export TERM=xterm-256color"
Enter
Sleep 500ms
Ctrl+L
Show

# 5. Visible interactions
Type "my-app --demo"
Sleep 500ms
Enter
Sleep 2s

# 6. App interactions
Down Down Down
Enter
Sleep 1s
Type "hello world"
Enter
Sleep 3s

# 7. Hidden cleanup (optional)
Hide
Ctrl+c
Sleep 500ms

Essential Commands

CommandExamplePurpose
OutputOutput demo.gifSet output (gif/mp4/webm/ascii)
SetSet FontSize 20Configure settings
TypeType "hello"Emulate typing
Type@NmsType@100ms "slow"Type at specific speed
Enter/Tab/SpaceEnterKey presses
Up/Down/Left/RightDown 3Navigation (with repeat)
Ctrl+keyCtrl+cModifier combos
SleepSleep 2sPause (ms or s)
Wait+ScreenWait+Screen /ready/Wait for screen content
Hide/ShowHideControl recording visibility
ScreenshotScreenshot step1.pngCapture current frame
EnvEnv TERM "xterm-256color"Set env variable
SourceSource setup.tapeInclude another tape
RequireRequire nodeFail if not in PATH

For complete command details, settings, and timing guidelines, see Command Reference.

Phase 3: Smart Tape Generation

When asked to generate a tape file for a specific app, follow this process:

Step 1: Analyze the App

Read the app's code or help output to understand:

  • How it launches (command, flags, arguments)
  • Key interactions (what keys it responds to)
  • Visual states worth showing (menus, forms, results)

Step 2: Generate the Tape

Build the tape file showing the app's key features:

# Generate and preview
vhs validate demo.tape    # Check syntax
vhs demo.tape             # Record

Step 3: Iterate

Run the tape, review the output, adjust timing and interactions.

Useful iteration commands:

# Quick preview without saving
vhs demo.tape --output /dev/null

# Test specific section — use Source to split tapes
vhs section-test.tape

Available Templates

Use these as starting points — copy and customize:

  • Basic CLI Demo — Simple command + output recording
  • Interactive TUI Demo — Navigation, forms, keyboard interaction
  • Build-and-Run Demo — Hidden compilation, visible app usage
  • Multi-Panel TUI — Complex apps like lazygit, k9s
  • CI Golden File — ASCII output for regression testing
  • Composable Tapes — DRY settings with Source

For complete copy-paste templates, see Templates.

Phase 4: Optimize Output

GIF Optimization

GIFs can get large. Reduce size with:

Set Framerate 15          # Lower framerate (default 30)
Set PlaybackSpeed 1.5     # Speed up slow parts
Set Width 800             # Smaller dimensions

Post-processing with gifsicle (optional):

gifsicle -O3 --lossy=80 demo.gif -o demo-optimized.gif

Target sizes:

  • README GIF: < 5 MB (GitHub renders inline)
  • Docs GIF: < 10 MB
  • If over 10 MB, consider MP4 or WebM instead

Timing Tips

  • Sleep 500ms after typing a command — lets the viewer read it
  • Sleep 2-3s after Enter — lets the viewer see the output
  • Sleep 3-5s on the final frame — prevents abrupt loop restart
  • Set LoopOffset 0% smoother GIF looping
  • Use Type@100ms for important text the viewer should follow
  • Use Type@30ms for boilerplate the viewer doesn't need to read

Phase 5: CI/CD Integration

GitHub Actions

name: Record Demo
on:
  push:
    branches: [main]
    paths:
      - "demo.tape"
      - "src/**"

jobs:
  record:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Record demo
        uses: charmbracelet/vhs-action@v2
        with:
          path: "demo.tape"

      - name: Commit updated GIF
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "docs: update demo recording"
          file_pattern: "*.gif"

Golden File Testing

Use ASCII output to detect visual regressions:

Output demo.ascii
# ... your interactions ...
# In CI: compare against committed golden file
vhs demo.tape
diff demo.ascii demo.ascii.golden

Examples

Good: Well-Structured Tape File

<Good>
# Clear output declaration
Output demo.gif

# Explicit dependency
Require gum

# All settings grouped at top
Set Shell "bash"
Set FontSize 20
Set Width 1200
Set Height 600
Set Theme "Catppuccin Frappe"
Set WindowBar Colorful
Set TypingSpeed 75ms
Set Padding 20

# Hidden setup — always Ctrl+L before Show to clear the screen
Hide
Type "export GLAMOUR_STYLE=dark"
Enter
Sleep 500ms
Ctrl+L
Show

# Deliberate pacing — viewer can follow
Type "gum choose 'Option A' 'Option B' 'Option C'"
Sleep 500ms
Enter
Sleep 1s

# Navigate with visible pauses
Down
Sleep 300ms
Down
Sleep 300ms
Enter
Sleep 2s

# Generous final pause for loop
Sleep 3s
</Good>

Bad: Common Mistakes

<Bad>
# Missing Output declaration — VHS won't know where to save

# Settings scattered throughout (will error or be ignored)
Type "my-app"
Set FontSize 20
Enter
Set Theme "Dracula"

# No Sleep after Enter — output flashes by
Type "my-app run"
Enter
Type "my-app status"
Enter

# No final Sleep — GIF loops abruptly

# No Require — silently fails if app missing
</Bad>

Bad: TUI Recording Anti-Patterns

<Bad>
Output demo.gif
Set Width 600
Set Height 300
# Too small — TUI elements will be cramped and unreadable

Type "lazygit"
Enter
# No Sleep — app hasn't loaded yet, next keys arrive too early

Tab Tab Tab Tab Tab
# Rapid-fire navigation — viewer can't follow what's happening

Type "c"
Type "feat: add feature"
Enter
# No pauses between actions — looks like a blur
</Bad>

For a complete well-structured TUI example (lazygit, k9s), see Templates.

Troubleshooting

Problem: GIF is choppy or laggy

Cause: Framerate too high for GIF format, or file too large for viewer.

Solution:

Set Framerate 15            # Lower from default 30
Set PlaybackSpeed 1.0       # Don't speed up

If still choppy, reduce dimensions or switch to MP4.

Problem: TUI doesn't render correctly

Cause: Missing TERM variable, wrong shell, or app needs specific setup.

Solution:

Hide
Env TERM "xterm-256color"
Type "stty rows 50 cols 120"
Enter
Sleep 500ms
Ctrl+L
Show

Problem: Keys arrive before app is ready

Cause: No Sleep after launching the app — VHS sends keystrokes immediately.

Solution: Always add Sleep 1-3s after launching a TUI app:

Type "my-tui"
Enter
Sleep 2s          # Wait for app to initialize
Down              # Now safe to interact

For apps with variable startup time, use Wait:

Type "my-tui"
Enter
Wait+Screen /ready/    # Wait until "ready" appears on screen
Down

Problem: VHS command not found

Cause: Missing VHS, ffmpeg, or ttyd.

Solution:

# macOS
brew install charmbracelet/tap/vhs ffmpeg ttyd

# Verify all three
vhs --version && ffmpeg -version && ttyd --version

Problem: GIF too large for GitHub

Cause: High resolution, long recording, or high framerate.

Solution:

  1. Reduce dimensions: Set Width 800 / Set Height 400
  2. Lower framerate: Set Framerate 15
  3. Speed up slow sections: Set PlaybackSpeed 1.5
  4. Post-process: gifsicle -O3 --lossy=80 demo.gif -o demo-small.gif
  5. If still too large, use MP4 and embed with <video> tag

Integration

This skill pairs with:

  • build-tui — Record demos of TUIs you build
  • git-worktree — Test recordings across branches
  • track-session — Track recording iteration progress

Useful alongside:

Quick Reference

vhs validate demo.tape            # Check syntax
vhs demo.tape                     # Record
vhs demo.tape --output custom.gif # Custom output path
vhs themes                        # List available themes
vhs new demo.tape                 # Create tape from template

Key commands cheat sheet:

CommandPurpose
Output file.gifSet output file and format
Require appFail if dependency missing
Set Key ValueConfigure terminal settings
Type "text"Emulate typing
Type@100ms "text"Type at specific speed
Enter / Tab / SpaceKey presses
Up / Down / Left / RightNavigation
Ctrl+cModifier key combos
Sleep 2sPause execution
Wait+Screen /regex/Wait for screen content
Hide / ShowControl recording visibility
Screenshot file.pngCapture current frame
Env VAR "val"Set environment variable
Source other.tapeInclude another tape file

Deep Reference

For detailed guides, load these files when needed:

  • Command Reference — All VHS commands, settings, timing guidelines
  • Templates — Copy-paste tape file templates for common scenarios

Only load these when specifically needed to save context.

References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

generate-skill

No summary provided by upstream source.

Repository SourceNeeds Review
General

track-session

No summary provided by upstream source.

Repository SourceNeeds Review
General

ideal-react-component

No summary provided by upstream source.

Repository SourceNeeds Review
General

git-worktree

No summary provided by upstream source.

Repository SourceNeeds Review