Skip to main content
ClaudeWave
Skill27.6k repo starsupdated 3d ago

terminal-capture

Automates terminal UI screenshot testing for CLI commands. Applies

Install in Claude Code
Copy
git clone --depth 1 https://github.com/QwenLM/qwen-code /tmp/terminal-capture && cp -r /tmp/terminal-capture/.qwen/skills/terminal-capture ~/.claude/skills/terminal-capture
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Terminal Capture — CLI Terminal Screenshot Automation

Drive terminal interactions and screenshots via TypeScript configuration, used
for visual verification during PR reviews.

## Prerequisites

Ensure the following dependencies are installed before running:

```bash
npm install       # Install project dependencies.
npx playwright install chromium   # Install Playwright browser (skip in CI: see note below)
```

> **CI / verify context:** when `QWEN_VERIFY_CHROMIUM=1` is set, the browser
> is already installed and `PLAYWRIGHT_BROWSERS_PATH` points at it. Do **not**
> run `playwright install` — it downloads ~170 MB and fails on system deps
> the agent user cannot install.

## Architecture

```
node-pty (pseudo-terminal)
  → ANSI byte stream
  → xterm.js (Playwright headless)
  → Screenshot
```

Core 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.

## Quick Start

### 1. Write Scenario Configuration

Create a `.ts` file under `integration-tests/terminal-capture/scenarios/`:

```typescript
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;
```

### 2. Run

```bash
# 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/
```

### 3. Output

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 |

## FlowStep API

Each flow step can contain the following fields:

### `type: string` — Input Text

Automatic behavior:
Input text → Screenshot (01) → Enter → stable output → Screenshot (02).

```typescript
{
  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 Press

Used 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`

```typescript
{
  key: 'ArrowDown';
} // Single key
{
  key: ['ArrowDown', 'ArrowDown', 'Enter'];
} // Multiple keys
```

Auto-screenshot is triggered after the key sequence ends (when the next step is
not a `key`).

### `streaming` — Capture During Execution

Capture multiple screenshots at intervals during long-running output (e.g.,
progress bars). Optionally generates an animated GIF.

```typescript
{
  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.
- Captures stop early if terminal output is unchanged for 3 consecutive
  intervals.
- Duplicate frames (no output change) are automatically skipped.

**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:

```bash
# Check
which ffmpeg

# Install (macOS)
brew install ffmpeg
```

If the user declines, the scenario still runs. GIF generation is skipped with a
warning.

### `capture` / `captureFull` — Explicit Screenshot

Use as a standalone step, or override automatic naming:

```typescript
{
  capture: 'initial.png';
} // Screenshot current viewport only
{
  captureFull: 'all-output.png';
} // Screenshot full scrollback buffer
```

## Scenario Examples

### Basic: Input + Command

```typescript
flow: [{ type: 'explain this project' }, { type: '/about' }];
```

### Secondary Menu Selection (/auth)

```typescript
flow: [
  { type: '/auth' },
  { key: 'ArrowDown' }, // Select API Key option
  { key: 'Enter' }, // Confirm
  { type: 'sk-xxx' }, // Input API key
];
```

### Tab Completion Selection (/export)

```typescript
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
];
```

### Array Batch (Multiple Scenarios in One File)

```typescript
export default [
  { name: '/about', spawn: [...], flow: [...] },
  { name: '/context', spawn: [...], flow: [...] },
] satisfies ScenarioConfig[];
```

## Integration with PR Review

This tool is commonly used for visual verification during PR reviews.

## Troubleshooting

- Playwright error `browser not found`
  Cause: browser not ins
agent-reproduce-alignSkill

Use after a Codex or Claude Code feature has been implemented in Qwen Code to run the selected reference agent and Qwen Code under the same scenario, capture HTTP and terminal traces, compare request bodies, tool/function schemas, outputs, and iterate until the reproduced behavior is close enough.

agent-reproduce-featureSkill

Use when reproducing an existing Codex or Claude Code feature in Qwen Code or another agent CLI by choosing a reference agent, capturing HTTP request bodies, prompts, tool/function schemas, terminal output, and then implementing the matching behavior in the target repo.

autofixSkill

Review and repair current local changes until they converge, or run Qwen Code Autofix issue and review workflows from GitHub Actions.

bugfixSkill

Fix a bug from a GitHub issue, following the reproduce-first

ci-flaky-patrolSkill

Classify a bounded batch of stale PR CI failures and choose the safest response.

codegraphSkill

Analyze indexed codebases via graph database (neug) and vector index (zvec). Covers call graphs, dependencies, dead code, hotspots, module coupling, architecture reports, semantic search, impact analysis, bug root cause from GitHub issues, class diagrams (UML), and PR review (risk scoring, conflict detection, auto-merge candidates, labeling). Also covers creating, inspecting, and repairing a CodeScope index. Use for: code structure, who calls what, why something changed, similar functions, module boundaries, bug tracing, class relationships, PR risk/conflicts, or any question benefiting from a code knowledge graph. Applies when a `.codegraph` index exists in the workspace, or when the user wants to create one.

create-issueSkill

Draft and submit a GitHub issue from a user idea or bug description, with bilingual body and correct labels.

deflakeSkill

Stabilize a flaky test with a minimal, assertion-preserving fix — never by weakening or deleting the check.