ptywright
ptywright is a terminal/TUI automation driver. It launches CLI/TUI programs in a PTY, feeds ANSI/VT output into @xterm/headless, rebuilds the terminal screen, and exposes that state through MCP tools, script runners, replayable cassettes, and browser-terminal regression workflows.
The core idea is simple: prefer deterministic terminal snapshots over screenshots when testing terminal behavior.
What It Solves
- Drive a live terminal from an MCP client or agent.
- Test CLI/TUI flows with JSON/TypeScript scripts, goldens, and HTML reports.
- Record raw PTY byte streams once and replay them without rerunning the command.
- Test browser-hosted terminal renderers with terminal/DOM snapshots.
- Keep generated artifacts portable with manifests, hashes, and reusable argv
commands.
Non-goals remain intentional: ptywright does not try to reverse-engineer a full component tree from terminal cells, and pixel-level screenshot diff is not the main regression path.
Install
# One-off usage
bunx ptywright@latest --help
npx -y ptywright@latest --help
# Or install globally
bun add -g ptywright
npm install -g ptywright
Inside this repository, use the local CLI:
bun run src/cli.ts help
Pick A Workflow
| Need | Use | Start here | | --- | --- | --- | | Let an agent inspect and control a live CLI/TUI | MCP server | MCP tools | | Write deterministic CLI/TUI regression tests | Script runner | Script runner | | Capture terminal bytes once and replay them later | Raw PTY cassette | Raw PTY cassettes | | Test a browser page that renders a terminal | Browser agent regression | Browser agent regression | | Feed raw PTY replay into a downstream browser terminal renderer | Browser harness | Browser terminal harness | | Debug CI failures, moved artifacts, or snapshot drift | Artifact commands | Artifacts and CI |
Quick Start
MCP Server
ptywright mcp
ptywright mcp --caps core
ptywright mcp --caps core,script,recording
ptywright mcp-http --port 3000
MCP client config:
{
"mcpServers": {
"ptywright": {
"command": "bunx",
"args": ["ptywright@latest", "mcp", "--caps", "core,script,recording"]
}
}
}
Typical MCP flow: launch_session, wait_for_text, send_text or press_key, wait_for_stable_screen, snapshot_text or snapshot_view, then close_session.
Script Runner
Create a JSON script:
{
"$schema": "./schemas/ptywright-script.schema.json",
"name": "tui_smoke",
"launch": {
"command": "bun",
"args": ["run", "tests/fixtures/tui_demo.ts"],
"cols": 80,
"rows": 24
},
"steps": [
{ "type": "waitForText", "text": "PTYWRIGHT TUI DEMO" },
{ "type": "snapshot", "kind": "text", "saveAs": "ready" },
{ "type": "expect", "from": "ready", "contains": ["status: ok"] }
]
}
Run it:
ptywright run scripts/tui_smoke.json
ptywright run-all --dir scripts
ptywright script inspect .tmp/run-all
Run output is written under .tmp/runs/<name>/ for single scripts and .tmp/run-all/ for suites by default.
Raw PTY Cassette
ptywright pty record --out tests/cassettes/session.pty.json -- codex
ptywright pty replay tests/cassettes/session.pty.json --speed 0
ptywright pty validate tests/cassettes/session.pty.json
ptywright pty inspect tests/cassettes/session.pty.json
For projects that already own a node-pty or bun-pty style process, use the programmatic wrapper:
import { wrapPtyLike } from "ptywright/pty-cassette";
const recorded = wrapPtyLike(pty, {
path: "tests/cassettes/session.pty.json",
terminal: { cols: 120, rows: 40, term: "xterm-256color" },
command: { file: "codex", args: [] },
});
recorded.write("hello\r");
Browser Agent Regression
Use this when a browser page renders a terminal and exposes [data-terminal-root].
ptywright agent run examples/agent_deterministic.json --update-snapshots
ptywright agent run examples/agent_deterministic.json
ptywright agent replay .tmp/agent/agent_deterministic/agent_deterministic.cassette.json
ptywright agent check
The preferred integration is launch.mode="command": start a wrapper command, read the first printed URL, open it with Playwright, and snapshot terminal/DOM state across configured viewports.
Command Map
ptywright mcp # MCP over stdio
ptywright mcp-http --port 3000 # MCP over Streamable HTTP
ptywright run <file.json|file.ts> # Run one script
ptywright run-all --dir scripts # Run a script suite
ptywright script inspect <dir> # Inspect script artifacts
ptywright pty record --out <file> -- <command> [args...]
ptywright pty replay <file>
ptywright agent run <flow.json>
ptywright agent replay <run-or-cassette>
ptywright agent promote <run-or-cassette>
ptywright agent replay-all [dir]
ptywright agent check [dir]
ptywright agent inspect <artifact-or-dir>
ptywright agent exec <artifact-or-dir> --command rerun
Run ptywright help for the full CLI surface.
Documentation
- MCP tools
- Script runner
- Raw PTY cassettes
- Browser agent regression
- Browser terminal harness
- Artifacts and CI
- Documentation maintenance
- Roadmap
- Historical research notes
JSON schemas live in schemas/, and examples live in examples/ and scripts/.
Project Layout
src/cli/ CLI argument parsing and command dispatch
src/mcp/ MCP server and tool registrations
src/session/ TerminalSession lifecycle, waits, snapshots, frames
src/pty/ PTY adapter abstraction and Bun backends
src/terminal/ xterm/headless snapshot, ANSI, style, mouse helpers
src/script/ JSON/TS script runner, suites, reports, manifests
src/agent/ Browser terminal agent flows, replay, promote, check
src/pty-cassette/ Raw PTY record/replay and wrapper APIs
src/trace/ Cast and HTML report generation
schemas/ Published JSON schemas
tests/ Deterministic fixtures, goldens, cassettes, snapshots
Development
bun install
# Local CLI and MCP
bun run src/cli.ts help
bun run src/cli.ts mcp
# Main gates
bun run test
bun run agent:check
bun run check
# Formatting and linting
bun run format:check
bun run lint
# Useful focused runs
bun run src/cli.ts run examples/report_demo_pass.json
bun run src/cli.ts run-all --dir scripts
bun run src/cli.ts agent run examples/agent_deterministic.json --update-snapshots
CI installs Chromium, runs bun run check, and uploads .tmp/agent-check.
Environment
TUI_TEST_PTY_BACKEND=auto|bun-terminal|bun-pty- Default
auto: macOS/Linux preferbun-terminal; Windows usesbun-pty. PTYWRIGHT_CAPS=all|core|debug|script|recording- Equivalent to
ptywright mcp --caps ....
License
Apache-2.0






