terminal-use

v2026.09.24

Background knowledge for droid-control workflows -- not invoked directly. Terminal-use driver mechanics for terminal TUI automation: tuistory virtual PTY by default, true-input for real terminal proof.

GitHub
Install command
npx skhub add factory-ai/terminal-use
Markdown
SKILL.md

Terminal Use

The orchestrator routed you here for any terminal target. Select the backend, then execute your plan through tctl.

Select the backend

NeedBackendMechanics
Routine TUI automation, regression checks, deterministic wait / wait-idle, text snapshots of what the user would see, demo recordingstuistory (default)This file
Real terminal rendering, or proof of what Ghostty or Kitty actually emits for a keystroketrue-inputLoad true-input; it owns the compositor, VM, and platform mechanics

Use tuistory unless the claim is about the real terminal itself. The rest of this file is the tuistory backend: a target command in a virtual PTY with Playwright-style CLI for typing, pressing keys, waiting, snapshotting, and recording.

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
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

plugins/droid-control/skills/terminal-use

Default branch

master

Latest commit

d362dc1

Tree SHA

8ba2de2