Automates terminal UI screenshot testing for CLI commands. Applies when reviewing PRs that affect CLI output, testing slash commands (/about, /context, /auth, /export), generating visual documentation, or when 'terminal screenshot', 'CLI test', 'visual test', or 'terminal-capture' is mentioned.
74
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
High
Do not use without reviewing
Drive terminal interactions and screenshots via TypeScript configuration, used for visual verification during PR reviews.
Ensure the following dependencies are installed before running:
npm install # Install project dependencies.
npx playwright install chromium # Install Playwright browsernode-pty (pseudo-terminal)
→ ANSI byte stream
→ xterm.js (Playwright headless)
→ ScreenshotCore files:
integration-tests/terminal-capture/terminal-capture.ts
Low-level PTY, xterm.js, and Playwright engine.integration-tests/terminal-capture/scenario-runner.ts
Scenario executor for config, interactions, and screenshots.integration-tests/terminal-capture/run.ts
CLI entry point for batch scenario runs.integration-tests/terminal-capture/scenarios/*.ts
Scenario configuration files.Create a .ts file under integration-tests/terminal-capture/scenarios/:
import type { ScenarioConfig } from '../scenario-runner.js';
export default {
name: '/about',
spawn: ['node', 'dist/cli.js', '--yolo'],
// cwd is relative to this config file's location.
terminal: { title: 'qwen-code', cwd: '../../..' },
flow: [
{ type: 'Hi, can you help me understand this codebase?' },
{ type: '/about' },
],
} satisfies ScenarioConfig;# Single scenario
npx tsx integration-tests/terminal-capture/run.ts \
integration-tests/terminal-capture/scenarios/about.ts
# Batch (entire directory)
npx tsx integration-tests/terminal-capture/run.ts \
integration-tests/terminal-capture/scenarios/Screenshots are saved to
integration-tests/terminal-capture/scenarios/screenshots/{name}/:
| File | Description |
|---|---|
01-01.png | Step 1 input state |
01-02.png | Step 1 execution result |
02-01.png | Step 2 input state |
02-02.png | Step 2 execution result |
full-flow.png | Final state full-length screenshot |
Each flow step can contain the following fields:
type: string — Input TextAutomatic behavior: Input text → Screenshot (01) → Enter → stable output → Screenshot (02).
{
type: 'Hello';
} // Plain text
{
type: '/about';
} // Slash command (auto-completion handled automatically)Special rule: If the next step is key, do not auto-press Enter (hand over
control to the key sequence).
key: string | string[] — Send Key PressUsed for menu selection, Tab completion, and other interactions. Does not auto-press Enter or auto-screenshot.
Supported key names: ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Enter,
Tab, Escape, Backspace, Space, Home, End, PageUp, PageDown,
Delete
{
key: 'ArrowDown';
} // Single key
{
key: ['ArrowDown', 'ArrowDown', 'Enter'];
} // Multiple keysAuto-screenshot is triggered after the key sequence ends (when the next step is
not a key).
streaming — Capture During ExecutionCapture multiple screenshots at intervals during long-running output (e.g., progress bars). Optionally generates an animated GIF.
{
type: 'Run this command: bash progress.sh',
streaming: {
delayMs: 7000, // Wait before first capture (skip initial waiting phase)
intervalMs: 500, // Interval between captures
count: 20, // Maximum number of captures
gif: true, // Generate animated GIF (default: true, requires ffmpeg)
},
}delayMs (optional): Milliseconds to wait after pressing Enter before
starting captures. Useful for skipping model thinking/approval time.GIF prerequisite: If the scenario uses streaming with GIF enabled
(default), check if ffmpeg is installed before running. If not, ask the user
whether they'd like to install it:
# Check
which ffmpeg
# Install (macOS)
brew install ffmpegIf the user declines, the scenario still runs. GIF generation is skipped with a warning.
capture / captureFull — Explicit ScreenshotUse as a standalone step, or override automatic naming:
{
capture: 'initial.png';
} // Screenshot current viewport only
{
captureFull: 'all-output.png';
} // Screenshot full scrollback bufferflow: [{ type: 'explain this project' }, { type: '/about' }];flow: [
{ type: '/auth' },
{ key: 'ArrowDown' }, // Select API Key option
{ key: 'Enter' }, // Confirm
{ type: 'sk-xxx' }, // Input API key
];flow: [
{ type: 'Tell me about yourself' },
{ type: '/export' }, // No auto-Enter (next step is key)
{ key: 'Tab' }, // Pop format selection
{ key: 'ArrowDown' }, // Select format
{ key: 'Enter' }, // Confirm → auto-screenshot
];export default [
{ name: '/about', spawn: [...], flow: [...] },
{ name: '/context', spawn: [...], flow: [...] },
] satisfies ScenarioConfig[];This tool is commonly used for visual verification during PR reviews.
browser not found
Cause: browser not installed.
Solution: npx playwright install chromium.npm rebuild node-pty.interface FlowStep {
type?: string; // Input text
key?: string | string[]; // Key press(es)
capture?: string; // Viewport screenshot filename
captureFull?: string; // Full scrollback screenshot filename
streaming?: {
delayMs?: number; // Delay before first capture (default: 0)
intervalMs: number; // Interval between captures in ms
count: number; // Maximum number of captures
gif?: boolean; // Generate animated GIF (default: true)
};
}
interface ScenarioConfig {
name: string; // Scenario name (also used as screenshot subdirectory name)
spawn: string[]; // Launch command ["node", "dist/cli.js", "--yolo"]
flow: FlowStep[]; // Interaction steps
terminal?: {
cols?: number; // Number of columns, default 100
rows?: number; // Number of rows, default 28
theme?: string; // Theme: dracula|one-dark|github-dark|monokai|night-owl
chrome?: boolean; // macOS window decorations, default true
title?: string; // Window title, default "Terminal"
fontSize?: number; // Font size
cwd?: string; // Working directory (relative to config file)
};
outputDir?: string; // Screenshot output directory (relative to config file)
}8878264
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.