Skip to main content
  1. Posts/

Capturing Commands as GIFs with VHS

··310 words·2 mins·

This document summarises how I use Charm’s vhs to capture and document command-line interactions.

General Configuration #

I tend to like capturing my preferred shell, prompt and font, all of which can be configured in the header of a .tape file.

Output command.gif

Set FontSize 18
Set Shell zsh
# or "FiraCode Nerd Font"
Set FontFamily "Fira Code"
# Set Margin 1

# time for the shell to load
Hide
Type eval "$(starship init zsh)"
Enter
Sleep 1s
Type clear
Enter
Show
# or any other command
Type neofetch
Sleep 500ms
Enter
# more time might be required for more time-consuming processes
Sleep 500ms

Before generating the GIF, you need to have FFmpeg and ttyd installed.

vhs < cassette.tape

Examples #

Tab Completion #

Since vhs requires the pauses between operation to be precise, this assumption also applies in waiting for tab completions to appear on the screen. It is important to ensure that each operation is clearly captured, by having an appropriate amount of time where vhs waits for the shell to respond to the key presses.

Output starship.gif

Set FontSize 18
Set Shell zsh
Set FontFamily "Fira Code"

Hide
Type eval "$(starship init zsh)"
Enter
Sleep 1s
Type clear
Enter
Show
Type ls
Enter
Sleep 500ms
Type hu
Tab
Sleep 1000ms
Tab
Sleep 500ms
Enter
Sleep 500ms
Tab
Sleep 500ms
Tab
Sleep 500ms
Up
Sleep 500ms
Enter
Sleep 500ms
Enter
Sleep 1000ms
Type cat starship.tape
Enter
Sleep 1000ms

My command-line prompt with tab completion
My command-line prompt with tab completion

Character Escaping #

Commands with more arguments and special character should be surrounded by quotes to ensure correct parsing and execution by vhs.

Output starship.gif

Set FontSize 18
Set Shell zsh
Set FontFamily "Fira Code"

Hide
Type eval "$(starship init zsh)"
Enter
Sleep 1s
Type clear
Enter
Show
Type "goreleaser release --clean --snapshot --skip-publish"
Enter
Sleep 5s
Type tree dist
Enter
Sleep 500ms

GoReleaser running a non-production build
GoReleaser running a non-production build