SKILL.md

  1---
  2name: charm-vhs
  3description: "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."
  4---
  5
  6# charm-vhs
  7
  8VHS records terminal sessions from `.tape` scripts. Requires `ttyd` and `ffmpeg` on PATH.
  9
 10```sh
 11brew install vhs       # also installs deps on macOS
 12vhs demo.tape          # run a tape file
 13vhs new demo.tape      # scaffold a new tape
 14vhs record > out.tape  # record interactively, then exit
 15vhs publish demo.gif   # host on vhs.charm.sh
 16```
 17
 18## Tape File Structure
 19
 20Order matters: `Output` and `Set` must come before action commands. `Require` goes at the very top.
 21
 22```
 23Require <program>   # fail early if missing from PATH
 24Output <path>       # .gif / .mp4 / .webm / .ascii / frames/
 25Set <Setting> Value # terminal config (must precede actions)
 26<actions>           # Type, Enter, Sleep, etc.
 27```
 28
 29## Output Formats
 30
 31```elixir
 32Output demo.gif
 33Output demo.mp4
 34Output demo.webm
 35Output frames/        # PNG sequence
 36Output golden.ascii   # for CI golden file diffing
 37```
 38
 39Multiple `Output` lines are fine - all render in one run.
 40
 41## Settings Reference
 42
 43```elixir
 44Set Shell "zsh"
 45Set FontSize 14
 46Set FontFamily "JetBrains Mono"
 47Set Width 1200
 48Set Height 600
 49Set Padding 20
 50Set Margin 40
 51Set MarginFill "#6B50FF"
 52Set BorderRadius 10
 53Set WindowBar Colorful        # Colorful, ColorfulRight, Rings, RingsRight
 54Set Theme "Catppuccin Frappe" # run `vhs themes` for full list
 55Set TypingSpeed 0.05          # seconds per keypress
 56Set Framerate 60
 57Set PlaybackSpeed 1.0
 58Set LoopOffset 50%            # where GIF loop starts
 59Set CursorBlink false
 60```
 61
 62`TypingSpeed` is the only setting that can change mid-tape. All others are ignored after the first action command.
 63
 64## Action Commands
 65
 66### Typing + input
 67
 68```elixir
 69Type "git status"           # types the string
 70Type@500ms "slowly..."      # override typing speed for this line
 71Type `VAR="backtick escapes quotes"`
 72Enter
 73Enter 2                     # press N times
 74Tab
 75Tab@200ms 3
 76Backspace 5
 77Space 2
 78```
 79
 80### Navigation
 81
 82```elixir
 83Up / Down / Left / Right    # arrow keys
 84Up 3                        # repeat N times
 85PageUp / PageDown
 86ScrollUp 10
 87ScrollDown@100ms 5
 88Ctrl+C
 89Ctrl+Alt+Delete
 90```
 91
 92### Timing
 93
 94```elixir
 95Sleep 500ms
 96Sleep 2s
 97Sleep 0.5       # seconds (float ok)
 98Wait /regex/    # wait until last line matches (default timeout 15s)
 99Wait+Screen /regex/         # check whole screen
100Wait+Line@10ms /regex/      # poll every 10ms
101```
102
103`Wait` is better than `Sleep` for commands with unpredictable runtime (builds, network calls).
104
105### Hide / Show
106
107```elixir
108Hide
109Type "setup stuff not shown in recording"
110Enter
111Wait /\$/
112Show
113```
114
115Use `Hide`/`Show` to run setup or cleanup without polluting the demo.
116
117### Other
118
119```elixir
120Screenshot path/out.png     # capture current frame as PNG
121Copy "text"                 # put text on clipboard
122Paste                       # paste clipboard
123Env KEY "value"             # set env var
124Source config.tape          # include another tape
125```
126
127## Example Tapes
128
129### 1. Simple CLI demo
130
131```elixir
132Output demo.gif
133
134Set FontSize 14
135Set Width 900
136Set Height 400
137Set Theme "Catppuccin Frappe"
138Set WindowBar Colorful
139Set TypingSpeed 0.05
140
141Type "ls -la"
142Sleep 300ms
143Enter
144Sleep 2s
145```
146
147### 2. Build + run with hidden setup
148
149```elixir
150Output demo.gif
151
152Set FontSize 13
153Set Width 1200
154Set Height 600
155Set Theme "Dracula"
156
157Require go
158
159Hide
160Type "go build -o myapp . && clear"
161Enter
162Wait /\$/
163Show
164
165Type "./myapp --help"
166Sleep 200ms
167Enter
168Sleep 3s
169
170Hide
171Type "rm myapp"
172Enter
173```
174
175### 3. Interactive TUI demo with Wait
176
177```elixir
178Output tui-demo.gif
179Output tui-demo.mp4
180
181Set FontSize 14
182Set Width 1000
183Set Height 500
184Set WindowBar Rings
185Set Margin 30
186Set MarginFill "#1a1b26"
187Set BorderRadius 8
188Set TypingSpeed 0.07
189
190Require gum
191
192Type "gum choose 'Option A' 'Option B' 'Option C'"
193Enter
194Sleep 500ms
195Down
196Sleep 300ms
197Down
198Sleep 500ms
199Enter
200Sleep 2s
201```
202
203## CI Integration
204
205Use the [vhs-action](https://github.com/charmbracelet/vhs-action) GitHub Action to regenerate GIFs on push.
206
207For integration testing, output `.ascii` and commit as golden files - diff them in CI to catch terminal output regressions.
208
209```elixir
210Output golden.ascii
211```
212
213## Tips
214
215- `vhs record > cassette.tape` then edit the generated tape to add `Set` blocks and clean up timing
216- Use `Source` to share a `config.tape` with common `Set` defaults across multiple tapes
217- `Wait` beats `Sleep` for anything async - no need to guess how long a build takes
218- `LoopOffset` makes the GIF preview frame more interesting than frame 0
219- `vhs themes` lists all built-in theme names