Tapes and shots in your repo

Write the keystrokes once, keep them beside the code, and record any shot by name.

What it does

prec runs inside your app's git repository and reads render/terminal.toml at its top. Each shot names its tape, what to launch and how the clip closes. prec builds the app (a cached build per commit), runs its fixture setup and teardown in a clean environment, and renders the working tree or any tag or commit.

A tape holds only steps: text to type and keys to press, each with an optional speed and repeat count. The settings live in terminal.toml, so one tape renders at any size, rate or theme.

  • Wait for the screen, not the clock

    Wait /regex/ returns as soon as the screen matches, instead of guessing a sleep; Idle 3s waits until the screen, colours and cursor included, has not changed for 3 seconds, as when an agent session finishes.

  • Squeeze the spinners

    Squeeze 400ms cuts every later stretch where no letter on the screen changes, a spinner or a counter, to 400 ms, keeping typed and printed text and Sleep at real speed.

  • Your data stays out

    The pty starts from a clean environment with a scratch HOME. pass_env hands named variables to the app, and the cast lists the names, never the values. Before a replay, prec refuses a picture showing your home path, hostname, user name, an email or a passed value.

  • Masks in every frame

    mask fills each regex match on the screen, wherever and whenever it shows, and each block of cells with the theme's background in every frame, written into the cast so every replay covers it.

Measured

colour schemes built in, VHS v0.11.0's set, plus your installed Omarchy themes
348
README, themes

How to use it

  1. Describe the app and its shots in render/terminal.toml.

    app = "myapp"
    bin = "myapp"
    grid = [120, 34]
    frame = "bare"
    setup = "{bin}/myapp-fixture >/dev/null"
    teardown = "myapp server --stop || true"
    
    [build]
    command = "cargo build --release --locked --bin myapp --bin myapp-fixture"
    bin_dir = "{target}/release"
    
    [env]
    MYAPP_DATA = "{scratch}/data"
    MYAPP_NOW = "2026-09-29T10:00:00Z"
    
    [theme]
    background = "#eff1f5"
    foreground = "#4c4f69"
    
    [shots.tour]
    kind = "clip"
    line = "The terminal workspace stepping through its views"
    tape = "render/terminal/tour.tape"
    launch = "myapp tui"
    settle = "3s"
    closure = "palindrome"
  2. Write the tape. This is the sample app's typing.tape.

    Sleep 300ms
    Type "demo tick"
    Enter
    Sleep 1.6s
    Type "demo show"
    Enter
    Sleep 1.2s
  3. List the shots, then record one.

    prec shots myapp
    prec clip myapp tour --size 1080p --fps 60
  4. Try it in a checkout of prec, on its sample app, once prec doctor finds Chromium and the fonts.

    prec clip demo typing --app-dir examples/demo --size 720p --fps 30

Read it. Run it. It's MIT.

The code is MIT licensed, © Catalin Ilinca: read it, fork it, ship it in your own work. Its name and logos, and PITO MD's, are © Catalin Ilinca, all rights reserved, and are not covered by the MIT licence.

Credits

prec vendors xterm.js 5.5.0 and VHS v0.11.0's 348 colour schemes, both under the MIT licence; their notices are in its NOTICE.

Set in Archivo by Omnibus-Type and Atkinson Hyperlegible Mono by the Braille Institute, both under the SIL Open Font License.