Claude Code Plugins

Community-maintained marketplace

Feedback

ghostty-terminal-automation

@hyperb1iss/ghostty-automator-python
0
0

Automate Ghostty terminal sessions via MCP. Use when you need to send commands to terminals, read terminal output, capture screenshots, resize windows, open new tabs/windows, or interact with TUI apps like Neovim, htop, or any CLI tool running in Ghostty.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name ghostty-terminal-automation
description Automate Ghostty terminal sessions via MCP. Use when you need to send commands to terminals, read terminal output, capture screenshots, resize windows, open new tabs/windows, or interact with TUI apps like Neovim, htop, or any CLI tool running in Ghostty.

Ghostty Terminal Automation

Control Ghostty terminals programmatically via the MCP server. Built on the ghostty-automator library with Playwright-style ergonomics.

Available MCP Tools

list_terminals

List all open terminal surfaces. Returns IDs, titles, dimensions, focus state, and working directory.

[
  {
    "id": "0x13604ba00",
    "title": "~/dev/project",
    "rows": 33,
    "cols": 135,
    "focused": true,
    "pwd": "/Users/bliss/dev/project"
  }
]

terminal

Interact with a specific terminal. Single supertool with 18 actions.

Required: terminal_id, action

Input Actions

Action Params Description
send text Send command + Enter
type text, delay_ms? Type text without Enter
key key, mods? Press key combination

Mouse Actions

Action Params Description
click x, y, button?, mods? Click at position
double_click x, y, button? Double-click
drag from_x, from_y, to_x, to_y, steps? Drag operation
scroll delta_y, delta_x?, mods? Scroll terminal

Screen Actions

Action Params Returns
read screen_type? {text, plain_text, cursor_x, cursor_y}
cells screen_type? {cells: [...], cursor_x, cursor_y, rows, cols}
screenshot output_path {path}

Waiting Actions (Critical for Automation!)

Action Params Description
wait_text pattern, regex?, timeout_ms? Wait for text/regex to appear
wait_prompt prompt_pattern?, timeout_ms? Wait for shell prompt
wait_idle stable_ms?, timeout_ms? Wait for screen to stabilize

Assertion Actions

Action Params Description
expect text, timeout_ms? Assert text is present
expect_not text, timeout_ms? Assert text is NOT present

Management Actions

Action Params Description
focus - Bring window to front
close - Close terminal
resize rows?, cols? Change dimensions

new_terminal

Create a new Ghostty window or tab.

Param Type Description
type "window" or "tab" Type of terminal to create
command list[str]? Optional command to run

Returns: {terminal_id, title, pwd}

Core Workflow

  1. Discover terminals with list_terminals
  2. Read current state with action="read" to see what's on screen
  3. Send commands with action="send"
  4. Wait for completion with action="wait_text" or action="wait_prompt"
  5. Verify results by reading again or taking a screenshot

Examples

Run a Command and Wait for Output

1. list_terminals                                    # Get terminal_id
2. terminal(id, action="send", text="npm test")      # Run command
3. terminal(id, action="wait_text", pattern="PASS")  # Wait for result
4. terminal(id, action="read")                       # Read output

Press Keys

# Press Enter
terminal(id, action="key", key="Enter")

# Ctrl+C to interrupt
terminal(id, action="key", key="KeyC", mods="ctrl")

# Arrow keys for navigation
terminal(id, action="key", key="ArrowUp")

# Tab completion
terminal(id, action="key", key="Tab")

# Escape (exit modes in vim, etc)
terminal(id, action="key", key="Escape")

Key names follow W3C standard: Enter, Tab, Escape, Backspace, Delete, Space, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Home, End, PageUp, PageDown, F1-F12, KeyA-KeyZ, Digit0-Digit9.

Type Without Executing

# Type partial input (no Enter)
terminal(id, action="type", text="git commit -m \"")

# Type slowly for effect
terminal(id, action="type", text="Hello", delay_ms=50)

Wait for Shell Prompt

# After running a long command
terminal(id, action="send", text="npm install")
terminal(id, action="wait_prompt")  # Waits for $ or similar
terminal(id, action="send", text="npm start")

Wait for Screen to Stabilize

# For streaming output or animations
terminal(id, action="send", text="curl https://example.com")
terminal(id, action="wait_idle", stable_ms=1000)  # Wait for 1s of no changes

Assertions

# Assert success message appears
terminal(id, action="expect", text="Build successful")

# Assert no errors
terminal(id, action="expect_not", text="ERROR")

Mouse Interactions

# Click at pixel position
terminal(id, action="click", x=100, y=200)

# Double-click to select word
terminal(id, action="double_click", x=100, y=200)

# Drag to select text
terminal(id, action="drag", from_x=50, from_y=100, to_x=200, to_y=100)

# Scroll down
terminal(id, action="scroll", delta_y=3)

Get Styled Cell Data (for TUI inspection)

# Get cell-level data with colors and formatting
terminal(id, action="cells")

# Returns cells with: char, x, y, fg, bg, bold, italic, underline, etc.

Screenshots

terminal(id, action="screenshot", output_path="/tmp/capture.png")
# Then use Read tool on /tmp/capture.png to view

Create New Terminal

# New window
new_terminal(type="window")

# New tab with command
new_terminal(type="tab", command=["python", "-i"])

Working with TUI Apps

Neovim

1. terminal(id, action="send", text="nvim file.py")
2. terminal(id, action="wait_text", pattern="file.py")
3. terminal(id, action="key", key="KeyI")           # Enter insert mode
4. terminal(id, action="type", text="print('hello')")
5. terminal(id, action="key", key="Escape")
6. terminal(id, action="type", text=":wq")
7. terminal(id, action="key", key="Enter")

htop / btop

1. terminal(id, action="send", text="htop")
2. terminal(id, action="wait_idle")                  # Wait for UI to render
3. terminal(id, action="screenshot", output_path="/tmp/htop.png")
4. terminal(id, action="key", key="KeyQ")           # Quit

Python Client

For scripting, use the ghostty-automator library directly:

from ghostty_automator import Ghostty

async with Ghostty.connect() as ghostty:
    # Get first terminal
    terminal = await ghostty.terminals.first()

    # Run command and wait for output
    await terminal.send("ls -la")
    await terminal.wait_for_text("package.json")

    # Assert text present
    await terminal.expect.to_contain("src/")

    # Take screenshot
    await terminal.screenshot("/tmp/result.png")

Sync API also available:

from ghostty_automator.sync_api import Ghostty

with Ghostty.connect() as ghostty:
    terminal = ghostty.terminals.first()
    terminal.send("echo hello")
    terminal.wait_for_prompt()

Tips

  • Always discover first: Call list_terminals before assuming terminal IDs
  • Use wait actions: Don't assume commands complete instantly
  • Read before sending: Check screen state to understand context
  • Use wait_prompt after commands: Ensures shell is ready for next command
  • Use cells for TUI inspection: Get color and style information
  • Screenshot for verification: Visual confirmation of complex operations