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.
Scanned 2/12/2026
Install via CLI
openskills install majiayu000/claude-skill-registry---
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.
```json
[
{
"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:
```python
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:
```python
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
No comments yet. Be the first to comment!