Via a fun blogpost from Leigh Dodds — Recreating sci-fi terminals using VHS — and the fascinating repo behind it, I come across charmbracelet/vhs
, a nifty package for creating animated gif based screencasts / movies of terminal based interactions.
Ar first, I thought this was just about creating fake replays from a canned script, which obviously has issues if you are looking to create a reproducible and true video of an actual terminal interaction…
But then, looking at Leigh’s repo, it suddenly became clear to me that this was just a hack based on using a real terminal, and that the script can be used to script, and record, actual terminal interactios. Doh!
So for example, Leigh’s .tape
script to create the above video looks like this:
Output gifs/jurassic-park-nedry.gif
Output gifs/jurassic-park-nedry.mp4
Set FontSize 14
Set Width 800
Set Height 600
Set Theme { "name": "Neo", "black": "#0D0208", "red": "#ef6487", "green": "#5eca89", "yellow": "#fdd877", "blue": "#65aef7", "magenta": "#aa7ff0", "cyan": "#43c1be", "white": "#ffffff", "brightBlack": "#0D0208", "brightRed": "#ef6487", "brightGreen": "#5eca89", "brightYellow": "#fdd877", "brightBlue": "#65aef7", "brightMagenta": "#aa7ff0", "brightCyan": "#43c1be", "brightWhite": "#ffffff", "background": "#203085", "foreground": "#ffffff", "selection": "#000000", "cursor": "#5eca89" }
# Change the default prompt before we start the script
Hide
Type "source jurassic-park-nedry.sh" Enter
Type "export PS1=''" Enter
Ctrl+L
Type "Jurassic Park, System Security Interface" Enter
Show
Type@100ms "access security"
Sleep 1s
Enter
Sleep 1s
Type@100ms "access security grid"
Enter
Sleep 1s
Type@100ms "access main security grid"
Enter
Sleep 5s
Ctrl+U
Those are actual commands, as you can see from the source jurassic-park-nedry.sh
typed command. What that does is load in a script that creates definitions for “commands” that appear later in the tape
script (i.e. commands that might not be recognised by the terminal, or that we might want to override:
Jurassic() {
export PS1='> '
echo "Version 4.0.5, Alpha E";
echo "Ready...";
}
access() {
sleep 0.5;
case $1 in
security)
echo "access: PERMISSION DENIED.";
;;
main)
echo "access: PERMISSION DENIED....and....";
for i in {1..100}
do
echo "YOU DIDN'T SAY THE MAGIC WORD!";
sleep 0.1;
done
;;
esac
}
So for example, when the command Jurassic
is entered into the real terminal, we want a particular echoed response. Similarly when the access
commands are Type
d.
If you have Docker installed, the simplest way to run vhs
is probably via a container. For example, hacking the following simple .tape
script together:
Output demo.gif
# Set up a 1200x600 terminal with 46px font.
Set FontSize 46
Set Width 1200
Set Height 600
Set TypingSpeed 100ms
# Type a command in the terminal.
Type "echo 'A simple VHS demo...'"
# Pause for dramatic effect...
Sleep 2s
# Run the command by pressing enter.
Enter
Type "mkdir -p demo"
Sleep 500ms
Enter
Sleep 1s
Type@100ms "ls demo"
Sleep 500ms
Enter
Sleep 1s
Type "echo 'Hello world' > demo/test.txt"
Enter
Sleep 500ms
Type@1s "ls demo"
Enter
Sleep 2s
Type "cat demo/test.txt"
Enter
Sleep 500ms
Type "echo '....and that is the end of the demo...'"
Sleep 1s
Enter
Sleep 3s
I can generate an animated gif as easily as typing docker run --rm -v $PWD:/vhs ghcr.io/charmbracelet/vhs MYTAPE.tape
I’ve also started wondering about using a Jupyter notebook to draft the interaction, then some sort of simple script to convert the notebook code cells to .tape
instrcutions, perhaps with suitable delays…
It might also be possible to spoof the notebook interaction, by echoing the commands in the code cell as if they wer real commands and then echoing the code cell output? Then you could use a pre-run notebook as the basis for a tape that replayed the “mocked” taped console commands from the notebook and the actual outputs from the notebook code cells?