Playwright for Terminals
Features • Requirements • Installation • Usage • API Reference
⚠️ Important: This library requires ghostty-automator, a fork of Ghostty with IPC automation support. Stock Ghostty does not include the automation protocol. Install from the hyperb1iss/homebrew-tap for easy setup.
- Playwright-style API — Familiar, ergonomic interface for terminal automation
- Async-first — Built on anyio for high performance with sync wrapper available
- Strong typing — Full type hints with strict pyright compliance
- Auto-waiting — Built-in wait helpers with configurable timeouts
- Assertions — Playwright-style
expectassertions for testing - Screenshots — Capture terminal state as PNG images
- Python 3.11+
- ghostty-automator (the Ghostty fork with IPC support)
# Install the Ghostty fork via Homebrew
brew tap hyperb1iss/bliss
brew install ghostty-automatorpip install ghostty-automatorOr with uv:
uv add ghostty-automatorfrom ghostty_automator import Ghostty
async with Ghostty.connect() as ghostty:
# Get the first terminal
terminal = await ghostty.terminals.first()
# Send commands
await terminal.send("ls -la")
# Wait for output
await terminal.wait_for_text("package.json")
# Assertions
await terminal.expect.to_contain("src/")
# Screenshots
await terminal.screenshot("debug.png")If you get a connection error about “insecure permissions”, either fix the socket permissions or connect with:
async with Ghostty.connect(validate_socket=False) as ghostty:
...from ghostty_automator.sync_api import Ghostty
with Ghostty.connect() as ghostty:
terminal = ghostty.terminals.first()
terminal.send("echo hello")
terminal.wait_for_text("hello")await terminal.send("npm test")
await terminal.wait_for_text("PASS", timeout=30_000)
await terminal.screenshot("tests-passed.png")| Method | Description |
|---|---|
Ghostty.connect() |
Create a connected client |
ghostty.terminals.all() |
Get all terminals |
ghostty.terminals.first() |
Get the first terminal |
ghostty.terminals.focused() |
Get the focused terminal |
ghostty.terminals.by_title(title) |
Find by title (partial match) |
ghostty.terminals.by_pwd(path) |
Find by working directory |
ghostty.new_window(command?) |
Open a new window |
ghostty.new_tab(command?) |
Open a new tab |
| Method | Description |
|---|---|
terminal.send(text) |
Send text + Enter |
terminal.type(text, delay_ms?) |
Type character by character |
terminal.press(key) |
Press a key (Enter, Tab, Ctrl+C, etc.) |
terminal.screen() |
Get current screen content |
terminal.wait_for_text(pattern) |
Wait for text to appear |
terminal.wait_for_prompt() |
Wait for shell prompt |
terminal.wait_for_idle(stable_ms?) |
Wait for screen to stabilize |
terminal.screenshot(path) |
Capture as PNG |
terminal.focus() |
Bring window to front |
terminal.close() |
Close the terminal |
terminal.resize(rows?, cols?) |
Resize the terminal |
| Method | Description |
|---|---|
terminal.expect.to_contain(text) |
Assert text is present |
terminal.expect.not_to_contain(text) |
Assert text is absent |
terminal.expect.to_match(pattern) |
Assert regex matches |
terminal.expect.to_have_title(title) |
Assert window title |
terminal.expect.to_have_pwd(path) |
Assert working directory |
terminal.expect.prompt() |
Assert prompt is visible |
# Clone and install
git clone https://github.com/hyperb1iss/ghostty-automator-python
cd ghostty-automator-python
uv sync
# Run checks
uv run pytest
uv run pyright src/
uv run ruff check src/MIT License — see LICENSE for details.
Created by Stefanie Jane