TTY testing — spawn terminal sessions, send keystrokes, capture screenshots and text. Use when user says /tty.
From ttynpx claudepluginhub beorn/bearly --plugin ttyThis skill is limited to using the following tools:
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Interactive terminal app testing - MCP server with Termless (PTY + xterm.js).
Prefer headless tests (testEnv()/board.press()) over TTY for testing logic. TTY is only for visual verification.
MCP Server -> Termless (PTY + xterm.js backend) -> target process
-> Playwright (lazy, screenshots only)
screenshot (renders SVG to PNG)| Tool | Description |
|---|---|
mcp__tty__start | Start PTY session with xterm.js terminal emulator |
mcp__tty__stop | Close PTY session and kill process |
mcp__tty__press | Press keyboard key(s) |
mcp__tty__type | Type text into terminal |
mcp__tty__screenshot | Capture screenshot (launches browser for rendering) |
mcp__tty__text | Get terminal text content |
mcp__tty__wait | Wait for text to appear or terminal stability |
mcp__tty__list | List active sessions |
1. mcp__tty__start({ command: ["bun", "km", "view", "/path"] })
-> { sessionId: "abc123" }
2. mcp__tty__wait({ sessionId: "abc123", for: "BOARD VIEW" })
-> { success: true }
3. mcp__tty__press({ sessionId: "abc123", key: "j" })
-> { success: true }
4. mcp__tty__screenshot({ sessionId: "abc123" })
-> Returns PNG image
5. mcp__tty__stop({ sessionId: "abc123" })
-> { success: true }
Use Playwright key formats for mcp__tty__press:
| Key | Format |
|---|---|
| Enter | Enter |
| Escape | Escape |
| Arrow keys | ArrowUp, ArrowDown, ArrowLeft, ArrowRight |
| Tab | Tab |
| Backspace | Backspace |
| Single char | j, k, q, etc. |
| With modifier | Control+c, Control+d, Shift+Tab, Alt+Enter |
{
command: string[] // Required: ["bun", "km", "view", "/path"]
env?: Record<string, string> // Optional: { DEBUG: "silvery:*" }
cols?: number // Terminal columns (default: 120)
rows?: number // Terminal rows (default: 40)
cwd?: string // Working directory
waitFor?: "content" | "stable" | string // Wait condition
timeout?: number // Wait timeout in ms (default: 5000)
}
{
sessionId: string // Required
outputPath?: string // Optional: save to file instead of base64
}
{
sessionId: string // Required
for?: string // Wait for specific text
stable?: number // Wait for terminal stability (ms)
timeout?: number // Default: 30000ms
}
mcp__tty__start({ command: ["bun", "km", "view", "/tmp/test"] })
mcp__tty__wait({ sessionId, for: "Ready" })
mcp__tty__screenshot({ sessionId })
mcp__tty__stop({ sessionId })
mcp__tty__start({ command: ["bun", "km", "view", "/path"] })
mcp__tty__wait({ sessionId, for: "BOARD VIEW" })
# Navigate down
mcp__tty__press({ sessionId, key: "j" })
mcp__tty__press({ sessionId, key: "j" })
# Check result
mcp__tty__text({ sessionId })
# -> { content: "... Item 3 selected ..." }
mcp__tty__stop({ sessionId })
# Start two sessions in parallel
mcp__tty__start({ command: ["app1"] }) -> session1
mcp__tty__start({ command: ["app2"] }) -> session2
# Interact with each
mcp__tty__press({ sessionId: session1, key: "q" })
mcp__tty__press({ sessionId: session2, key: "Enter" })
# Clean up
mcp__tty__stop({ sessionId: session1 })
mcp__tty__stop({ sessionId: session2 })
On first mcp__tty__screenshot, Chromium is automatically installed to a local cache: