mcpField
T
tuistory

tuistory

github.com/factory-aiTesting & quality11782 installsUpdated 4d ago
Repository

About tuistory

tuistory is a driver skill for automating terminal UI sessions through a virtual PTY. It supports scripted input, deterministic waits, text snapshots, and recordings for routine TUI automation and regression checks.

Key features

  1. 01Launch sessions through tctl
  2. 02Send text and key combinations
  3. 03Wait for text or stable output
  4. 04Capture terminal text snapshots
  5. 05Record sessions as .cast files

Use cases

  1. 01Automate routine TUI interactions
  2. 02Run terminal UI regression checks
  3. 03Verify output after scripted input
  4. 04Record terminal sessions for playback

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/factory-ai/factory-plugins --skill tuistory

After installing, type/tuistoryin Claude Code to confirm it loaded.

Details

From the project README

Tuistory Driver

The orchestrator routed you here. Use these mechanics to execute your plan.

Launch a target command in a virtual PTY with Playwright-style CLI for typing, pressing keys, waiting, snapshotting, and recording.

When to use

  • Routine TUI automation and regression checks
  • Deterministic wait / wait-idle against the virtual screen buffer
  • Text snapshots of exactly what the user would see
  • Any scenario where you do not need to prove real terminal keyboard encoding

If you need to prove what Ghostty or Kitty actually emits for a given keystroke, use true-input instead.

Prerequisites

npm install -g tuistory    # or: bun add -g tuistory

Optional: tmux (scrollback flows), asciinema (recordings), agg (.cast to .gif).

Core pattern

TCTL=${DROID_PLUGIN_ROOT}/bin/tctl

$TCTL launch "droid-dev" -s demo --backend tuistory \
  --repo-root /path/to/worktree \
  --cols 120 --rows 36 \
  --env FORCE_COLOR=3 --env COLORTERM=truecolor
$TCTL -s demo wait ">" --timeout 15000
$TCTL -s demo type "hello"
$TCTL -s demo press enter
$TCTL -s demo snapshot --trim
$TCTL -s demo close

Note: --repo-root is mandatory for droid-dev launches — tctl enforces it.

Always pass --env FORCE_COLOR=3 --env COLORTERM=truecolor when launching. The virtual PTY doesn't advertise color support, so Node.js apps (Ink/chalk) suppress all color escape codes without these.

Command reference (via tctl)

CommandPurpose
launch <cmd> -s <name> --backend tuistoryStart a tuistory session
type <text>Send literal text
press <key> [keys...]Send key chord (e.g., press shift enter)
wait <pattern>Block until text or /regex/ appears
wait-idleBlock until output stabilizes
snapshot [--trim]Print cleaned text (--trim strips trailing blanks)
closeTear down session

Launch options: --cols <n>, --rows <n>, --cwd <path> (child working directory; defaults to --repo-root when set), --env KEY=VALUE, --record <path>.

Recording

Pass --record at launch. tctl wraps asciinema rec around the PTY, so recording must be set at launch time (raw tuistory cannot record):

$TCTL launch "droid-dev" -s demo --backend tuistory \
  --repo-root /path/to/worktree \
  --cols 120 --rows 36 --record /tmp/demo.cast \
  --env FORCE_COLOR=3 --env COLORTERM=truecolor
# ... interact ...
$TCTL -s demo close    # finalizes the .cast

Before/after comparison -- launch two sessions against different worktrees:

$TCTL launch "droid-dev" -s before --backend tuistory \
  --repo-root /path/to/baseline-worktree \
  --cols 120 --rows 36 --record /tmp/before.cast \
  --env FORCE_COLOR=3 --env COLORTERM=truecolor

$TCTL launch "droid-dev" -s after --backend tuistory \
  --repo-root /path/to/candidate-worktree \
  --cols 120 --rows 36 --record /tmp/after.cast \
  --env FORCE_COLOR=3 --env COLORTERM=truecolor

Playback: asciinema play /tmp/demo.cast

tmux (scrollback flows only)

Only needed when the demo requires terminal-emulator scrollback and the app uses the standard buffer (not alternate screen). True-input sessions rarely need tmux because the real terminal owns native scrollback.

Use --tmux at launch. tctl wraps the command in tmux, starts tmux with TERM=xterm-256color, and preconfigures default-terminal=tmux-256color, terminal-features=...,xterm-256color:RGB, terminal-overrides=...,xterm-256color:Tc (fallback for tmux < 3.2), COLORTERM=truecolor (via set-environment), escape-time=50, and mode-keys=vi.

Copy-mode: ctrl-b [ to enter, g g top, shift-g bottom, ctrl-u/ctrl-d half-page, / search, q to exit (not esc).

Launch with tmux:

$TCTL launch "droid-dev" -s demo --backend tuistory --tmux \
  --repo-root /path/to/worktree \
  --cols 120 --rows 36 --record /tmp/demo.cast \
  --env FORCE_COLOR=3 --env COLORTERM=truecolor

When recording includes tmux redraws, asciinema must wrap tmux, not the reverse.

Known dead ends

  • Raw asciinema rec: Do not call asciinema rec directly. tctl --record wraps asciinema rec around the PTY so that tuistory-relay still owns the session and interactive TUIs (Ink/React) receive stdin correctly. Calling asciinema rec manually bypasses this wiring — stdin forwarding breaks, typed keys echo on the outer PTY instead of reaching the child, and tuistory commands (wait, snapshot, close) cannot find the session.
  • Raw tuistory launch with tctl flags: tuistory has no --record, --backend, --repo-root, or --env flags. Passing them crashes tuistory-relay. Use tctl for all launches.

Recovery

$TCTL -s demo press esc         # bail out of a stuck dialog
$TCTL -s demo snapshot --trim   # check visible state
$TCTL -s demo close             # hard reset

Escape hatch: raw tuistory (last resort)

If tctl itself is broken or unavailable, you can fall back to raw tuistory for non-recording sessions only. Raw tuistory accepts only --cols, --rows, and -s — no other flags. Do not pass --record, --backend, --repo-root, --env, or --tmux.

tuistory launch "my-tui-app" -s demo --cols 120 --rows 36
tuistory -s demo wait ">" --timeout 15000
tuistory -s demo snapshot --trim
tuistory -s demo close

Comments

Markdown supported