charm-vhs

Record terminal sessions as GIF/MP4/WebM from declarative .tape scripts with VHS. Use when creating terminal demos, recording CLI sessions, VHS tape files, or generating terminal GIFs.

6 stars

Best use case

charm-vhs is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Record terminal sessions as GIF/MP4/WebM from declarative .tape scripts with VHS. Use when creating terminal demos, recording CLI sessions, VHS tape files, or generating terminal GIFs.

Teams using charm-vhs should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/charm-vhs/SKILL.md --create-dirs "https://raw.githubusercontent.com/alxxpersonal/forge/main/skills/charm-vhs/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/charm-vhs/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How charm-vhs Compares

Feature / Agentcharm-vhsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Record terminal sessions as GIF/MP4/WebM from declarative .tape scripts with VHS. Use when creating terminal demos, recording CLI sessions, VHS tape files, or generating terminal GIFs.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# charm-vhs

VHS records terminal sessions from `.tape` scripts. Requires `ttyd` and `ffmpeg` on PATH.

```sh
brew install vhs       # also installs deps on macOS
vhs demo.tape          # run a tape file
vhs new demo.tape      # scaffold a new tape
vhs record > out.tape  # record interactively, then exit
vhs publish demo.gif   # host on vhs.charm.sh
```

## Tape File Structure

Order matters: `Output` and `Set` must come before action commands. `Require` goes at the very top.

```
Require <program>   # fail early if missing from PATH
Output <path>       # .gif / .mp4 / .webm / .ascii / frames/
Set <Setting> Value # terminal config (must precede actions)
<actions>           # Type, Enter, Sleep, etc.
```

## Output Formats

```elixir
Output demo.gif
Output demo.mp4
Output demo.webm
Output frames/        # PNG sequence
Output golden.ascii   # for CI golden file diffing
```

Multiple `Output` lines are fine - all render in one run.

## Settings Reference

```elixir
Set Shell "zsh"
Set FontSize 14
Set FontFamily "JetBrains Mono"
Set Width 1200
Set Height 600
Set Padding 20
Set Margin 40
Set MarginFill "#6B50FF"
Set BorderRadius 10
Set WindowBar Colorful        # Colorful, ColorfulRight, Rings, RingsRight
Set Theme "Catppuccin Frappe" # run `vhs themes` for full list
Set TypingSpeed 0.05          # seconds per keypress
Set Framerate 60
Set PlaybackSpeed 1.0
Set LoopOffset 50%            # where GIF loop starts
Set CursorBlink false
```

`TypingSpeed` is the only setting that can change mid-tape. All others are ignored after the first action command.

## Action Commands

### Typing + input

```elixir
Type "git status"           # types the string
Type@500ms "slowly..."      # override typing speed for this line
Type `VAR="backtick escapes quotes"`
Enter
Enter 2                     # press N times
Tab
Tab@200ms 3
Backspace 5
Space 2
```

### Navigation

```elixir
Up / Down / Left / Right    # arrow keys
Up 3                        # repeat N times
PageUp / PageDown
ScrollUp 10
ScrollDown@100ms 5
Ctrl+C
Ctrl+Alt+Delete
```

### Timing

```elixir
Sleep 500ms
Sleep 2s
Sleep 0.5       # seconds (float ok)
Wait /regex/    # wait until last line matches (default timeout 15s)
Wait+Screen /regex/         # check whole screen
Wait+Line@10ms /regex/      # poll every 10ms
```

`Wait` is better than `Sleep` for commands with unpredictable runtime (builds, network calls).

### Hide / Show

```elixir
Hide
Type "setup stuff not shown in recording"
Enter
Wait /\$/
Show
```

Use `Hide`/`Show` to run setup or cleanup without polluting the demo.

### Other

```elixir
Screenshot path/out.png     # capture current frame as PNG
Copy "text"                 # put text on clipboard
Paste                       # paste clipboard
Env KEY "value"             # set env var
Source config.tape          # include another tape
```

## Example Tapes

### 1. Simple CLI demo

```elixir
Output demo.gif

Set FontSize 14
Set Width 900
Set Height 400
Set Theme "Catppuccin Frappe"
Set WindowBar Colorful
Set TypingSpeed 0.05

Type "ls -la"
Sleep 300ms
Enter
Sleep 2s
```

### 2. Build + run with hidden setup

```elixir
Output demo.gif

Set FontSize 13
Set Width 1200
Set Height 600
Set Theme "Dracula"

Require go

Hide
Type "go build -o myapp . && clear"
Enter
Wait /\$/
Show

Type "./myapp --help"
Sleep 200ms
Enter
Sleep 3s

Hide
Type "rm myapp"
Enter
```

### 3. Interactive TUI demo with Wait

```elixir
Output tui-demo.gif
Output tui-demo.mp4

Set FontSize 14
Set Width 1000
Set Height 500
Set WindowBar Rings
Set Margin 30
Set MarginFill "#1a1b26"
Set BorderRadius 8
Set TypingSpeed 0.07

Require gum

Type "gum choose 'Option A' 'Option B' 'Option C'"
Enter
Sleep 500ms
Down
Sleep 300ms
Down
Sleep 500ms
Enter
Sleep 2s
```

## CI Integration

Use the [vhs-action](https://github.com/charmbracelet/vhs-action) GitHub Action to regenerate GIFs on push.

For integration testing, output `.ascii` and commit as golden files - diff them in CI to catch terminal output regressions.

```elixir
Output golden.ascii
```

## Tips

- `vhs record > cassette.tape` then edit the generated tape to add `Set` blocks and clean up timing
- Use `Source` to share a `config.tape` with common `Set` defaults across multiple tapes
- `Wait` beats `Sleep` for anything async - no need to guess how long a build takes
- `LoopOffset` makes the GIF preview frame more interesting than frame 0
- `vhs themes` lists all built-in theme names

Related Skills

charm-ultraviolet

6
from alxxpersonal/forge

Low-level Go terminal primitives - cell-based rendering, input handling, screen management. Use when building custom Go terminal renderers, ultraviolet, cell buffers, or performance-critical TUI work below Bubble Tea's abstraction level.

charm-pop

6
from alxxpersonal/forge

Send emails from the terminal with pop - TUI and CLI modes, SMTP and Resend support, attachments. Use when sending email from terminal, pop, CLI email, or piping email content from shell scripts.

charm-lipgloss

6
from alxxpersonal/forge

CSS-like terminal styling for Go with lipgloss v2 - styles, colors, borders, layout, tables, lists, and trees. Use when styling Go terminal output, lipgloss, terminal layout composition, or building styled tables/lists/trees in Go.

charm-huh

6
from alxxpersonal/forge

Build interactive terminal forms and prompts in Go with huh - input, select, confirm, multiselect, validation, theming. Use when building Go terminal forms, huh, interactive Go prompts, or form fields with validation. NOT for shell script prompts (use gum).

charm-harmonica

6
from alxxpersonal/forge

Physics-based animation for Go TUIs - damped spring oscillator and projectile motion. Use when adding spring animations, physics-based motion, or smooth transitions to Go terminal apps. No Ease function exists in this library.

charm-gum

6
from alxxpersonal/forge

Interactive shell script prompts, fuzzy filters, spinners, and styled output with gum. Use when building bash/shell script UIs, gum commands, interactive shell prompts, or CLI script workflows. NOT for Go terminal forms (use huh).

charm-freeze

6
from alxxpersonal/forge

Generate PNG, SVG, or WebP screenshots of code and terminal output with freeze. Use when screenshotting code, freeze, terminal-to-image, or capturing styled code snippets as images.

charm-fang

6
from alxxpersonal/forge

Wrap Cobra with styled help, error output, auto versioning, and manpage generation via fang. Use when building Go CLIs with fang, styled Cobra help, or adding lipgloss-rendered help pages to a Go CLI.

charm-ecosystem

6
from alxxpersonal/forge

Architect's guide to the charmbracelet Go TUI ecosystem - which libraries to combine, dependency hierarchy, integration patterns. Use when choosing charm libraries, planning TUI architecture, combining bubbletea/lipgloss/bubbles/huh, or asking 'which charm library for X'. NOT for specific library API details (use individual charm-* skills).

charm-crush

6
from alxxpersonal/forge

Architecture patterns from Crush, charmbracelet's production agentic coding CLI built on bubbletea v2, lipgloss v2, bubbles v2, glamour v2, and ultraviolet. Use when building production bubbletea apps, composing charm TUI components at scale, designing agentic CLI tools, implementing streaming LLM UIs, or asking about crush internals. NOT for individual charm library basics.

charm-bubbletea

6
from alxxpersonal/forge

Build terminal UIs in Go with Bubble Tea v2's Elm Architecture (Model/Update/View). Use when building Go TUI apps, tea.Model, tea.Cmd, Elm architecture, or terminal applications. NOT for pre-built TUI components (use bubbles).

charm-bubbles

6
from alxxpersonal/forge

Pre-built TUI components for Bubble Tea apps - spinner, text input, textarea, list, table, viewport, paginator, progress bar. Use when adding Go TUI components, bubbles, or terminal widgets to a Bubble Tea app. NOT for the core TUI framework (use bubbletea).