Skip to content

📜 Clip format

A clip is described by a TOML file, usually kept in docs/clips/. Paths in it are relative to the file.

The smallest clip has a label and one run:

label = "Listing the files in a project"

[[run]]
cmd = "ls"
lines = ["README.md  src  tests"]

zoetty build turns clip.toml into clip.svg next to it.

Top-level keys

Key Default What it does
label required What the clip shows, in words. Used as the alt text and aria-label, so people who can't see the animation still get it.
title "" Shown in the window bar, like a terminal's title.
cols 80 Terminal width in columns. Recording uses it too, so output wraps where it would in a real terminal of that size.
rows every line Visible rows. Output scrolls once it passes this.
out ["<name>.svg"] Files zoetty build writes. .svg makes an SVG image, .html an HTML fragment.
prompt "[dim]$[/] " Shown before each command.
final_prompt prompt Left blinking at the end.
typing_speed 28 Characters per second commands are typed at. Typing always takes between 0.4 and 2.2 seconds.
line_gap 0.07 Seconds between output lines.
hold 4.0 Seconds the last frame is held before the clip loops.
duration worked out Total loop length in seconds, if you'd rather set it.
chrome true Draw the window bar with its dots and title.

[[run]]: commands

Each run is a command typed at the prompt, followed by its output. Runs are shown in order.

[[run]]
cmd = "clientele start-api -f schema.json -o my_client/"
output = "captures/start-api.ansi"
Key Default What it does
cmd required The command typed on screen.
output A file holding the command's captured output. zoetty record writes it.
lines Output written by hand, one markup string per line.
exec cmd What zoetty record actually runs, when it's different from what's shown (e.g. .venv/bin/tool instead of tool, or cd demo && tool).
input Text typed into the command while recording. Each line is typed once the command has been quiet for a moment, so it lands after the prompt that asked for it. Then Ctrl-D is sent, which ends a REPL.
record true Set to false to keep an output file but never re-record it.
prompt the clip's A different prompt for this command, e.g. ">>> " inside a REPL.
think 0.5 Seconds between finishing typing and the output appearing.
pause 0.9 Seconds after the output before the next command.
line_gap the clip's Seconds between this run's output lines.

A run has output or lines, not both. A run with neither shows no output.

Output lines wider than cols wrap onto the next row, as they would in a terminal.

[record]: how commands are recorded

[record]
cwd = "../.."                       # run from the repo root
setup = ["rm -rf my_client"]        # run first, output not shown
env = { NO_COLOR = "" }
timeout = 120
Key Default What it does
cwd the spec's folder Where commands run.
setup [] Shell commands run before the first recorded command, to start from a known state. Recording stops if one fails.
env {} Extra environment variables.
timeout 60 Seconds each command may take.

Commands also get TERM=xterm-256color, COLUMNS and LINES from the clip's size, FORCE_COLOR=1 and CLICOLOR_FORCE=1 so they keep their colours, and PAGER=cat and GIT_PAGER=cat so nothing waits on a pager. env can override any of them.

A command that exits non-zero is recorded like any other (failing commands make good demos too); zoetty record shows its exit code.

[theme]: colours

[theme]
bg = "#282c34"
bar = "#21252b"
fg = "#abb2bf"
green = "#98c379"

bg, fg (text), bar (window bar) and the six colours blue, green, yellow, red, cyan and magenta, as #rgb or #rrggbb. Anything you don't set keeps its default.

Markup

lines, prompt and final_prompt use a small markup, a lot like rich's:

Markup Shows
[bold]text[/] Styled text. Styles are bold, dim, italic, and the colours blue, green, yellow, red, cyan and magenta.
[bold green]text[/] Several styles at once.
\[ A literal [. In TOML strings write \\[, or use single-quoted strings: '\[y/N]'.
[type 1.2]text[/] Text typed out over 1.2 seconds. [type 1.2 0.5] waits 0.5 seconds first. Only needed in [[step]] clips: commands in runs are typed for you.

Captured output is converted to markup automatically: colours and bold, dim and italic are kept; cursor movement and other escape codes are dropped.

[[step]]: hand-timed clips

For clips that aren't a series of commands, give [[step]] entries instead of [[run]]s, saying exactly when lines appear. A clip has runs or steps, not both.

label = "A prompt being answered"
duration = 6

[[step]]
at = 0.5
lines = ['Start? \[y/N] [type 0.1 0.8]y[/]']
caret = true

[[step]]
at = 2
lines = ["[green]✓ started[/]"]
Key Default What it does
at required Seconds into the clip the lines appear.
lines required Markup lines.
caret false Show a blinking caret at the end of the last line, until the next step.

Limitations

  • zoetty reads output line by line rather than emulating a terminal. Colours are kept and a carriage return keeps what was last written on the line (so simple spinners end up showing their final state), but full-screen programs and progress bars that move the cursor won't look right.
  • Wide characters such as emoji take one column in zoetty's layout but two in most terminals, so text after them can sit slightly off.