Skip to content

The Terminal Automation API provides programmatic control over TUI (text-based UI) applications running in managed terminal sessions. Use these endpoints to snapshot the screen, search rendered output with regex, inject key presses and pasted text, and block until a target condition is met — without driving a real keyboard. Endpoints are backed by a server-side libvterm parser that mirrors the browser’s xterm.js state, so snapshots reflect exactly what a user would see.

Returns a rendered snapshot of the terminal screen as seen by a user. The snapshot includes the visible text grid (lines), cursor position, window title, fullscreen (alt-screen) state, reverse-video highlight spans, and a monotonic sequence counter. On first call for a session the parser is lazily initialized by replaying the session’s output buffer.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID (numeric 1-65535)
include_colorsquerybooleanNoInclude ANSI SGR colored_lines array alongside plain text lines. Default: false
include_highlightsquerybooleanNoInclude reverse-video highlight spans. Default: true
scroll_offsetqueryintegerNoLines into scrollback (0 = live viewport). Default: 0
{
"terminal_id": 1042,
"sequence": 4271,
"title": "vim /etc/hosts",
"alt_screen": false,
"dimensions": { "rows": 24, "cols": 80 },
"cursor": { "row": 7, "col": 12, "visible": true },
"lines": [
" GNU nano 5.4 /etc/hosts ",
"127.0.0.1 localhost",
"::1 localhost",
""
],
"highlights": [
{ "row": 1, "col_start": 0, "col_end": 12, "reverse": true }
],
"colored_lines": null
}
const snapshot = await client.terminal.terminalAutomation.getTerminalSnapshot({
terminal_id: "1042",
include_colors: true,
include_highlights: true,
scroll_offset: 0
});

Search the rendered terminal screen (or scrollback) for a PCRE2 regular expression pattern. Returns cell-coordinate hits with matched text. The scan enforces an internal 500 ms wall-clock bound to prevent ReDoS.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID
patternquerystringYesPCRE2 regex pattern to search for (max 1024 bytes)
scopequerystringNoSearch scope: screen (default), scrollback, or all
limitqueryintegerNoMaximum number of hits to return (default 100, max 1000)
case_insensitivequerybooleanNoCase-insensitive matching. Default: false
scroll_offsetqueryintegerNoScrollback offset for screen scope (0 = live viewport). Default: 0
{
"terminal_id": 1042,
"pattern": "Error.*",
"scope": "screen",
"total": 2,
"truncated": false,
"deadline_exceeded": false,
"hits": [
{ "row": 12, "col": 4, "text": "Error: file not found" },
{ "row": 18, "col": 0, "text": "Error: permission denied" }
]
}
const results = await client.terminal.terminalAutomation.findInTerminal({
terminal_id: "1042",
pattern: "Error.*",
scope: "screen",
limit: 100,
case_insensitive: false,
scroll_offset: 0
});

Returns the full list of key names accepted by /api/v1/terminal/press, including aliases and canonical forms. Useful for client-side validation and discoverability. Single printable characters (a-z, 0-9, punctuation) are also accepted but not listed individually.

This endpoint takes no parameters.

{
"keys": [
"enter", "tab", "escape", "backspace", "space",
"up", "down", "left", "right",
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
"ctrl+a", "ctrl+b", "ctrl+c", "ctrl+d", "ctrl+e", "ctrl+f",
"ctrl+g", "ctrl+h", "ctrl+i", "ctrl+j", "ctrl+k", "ctrl+l",
"ctrl+m", "ctrl+n", "ctrl+o", "ctrl+p", "ctrl+q", "ctrl+r",
"ctrl+s", "ctrl+t", "ctrl+u", "ctrl+v", "ctrl+w", "ctrl+x",
"ctrl+y", "ctrl+z",
"esc", "bs", "del", "home", "end", "page_up", "page_down",
"insert", "kp_enter", "kp_plus", "kp_minus"
]
}
const { keys } = await client.terminal.terminalAutomation.listSupportedKeys();

GET /api/v1/terminal/{terminal_id}/automation

Section titled “GET /api/v1/terminal/{terminal_id}/automation”

Returns the VT parser state for a specific session: whether vterm is active, dimensions, update sequence counter, time since last screen change, alt-screen flag, title, scrollback length, and active waiter count. Useful for debugging automation workflows (“why did my wait timeout? did the screen actually change?”).

NameInTypeRequiredDescription
terminal_idpathstringYesTerminal session ID
{
"terminal_id": 1042,
"vterm_active": true,
"dimensions": { "rows": 24, "cols": 80 },
"update_seq": 4271,
"ms_since_change": 142,
"alt_screen": false,
"title": "vim /etc/hosts",
"scrollback_len": 1240,
"active_waiters": 1
}
const state = await client.terminal.terminalAutomation.getSessionAutomationState({
terminal_id: "1042"
});

Returns global metrics for the server-side VT parser: active vterm session count, memory used/cap in MB, total active wait-waiters across all sessions, and configured limits. Use to monitor resource usage, tune --vterm-memory-cap-mb, and detect leaks.

This endpoint takes no parameters.

{
"active_sessions": 14,
"memory_used_mb": 87.4,
"memory_cap_mb": 512,
"active_waiters": 3,
"limits": {
"max_waiters_per_session": 16,
"max_body_size_mb": 8
}
}
const metrics = await client.terminal.terminalAutomation.getAutomationMetrics();

Send one or more named key presses to a terminal session. Keys are encoded through libvterm’s keyboard API which respects the terminal’s current application-cursor mode (DECCKM) and keypad mode (DECKPAM), ensuring correct byte sequences for programs like vim, htop, and tmux.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID

Exactly one of keys or key is required.

NameTypeRequiredDescription
keysarrayNoArray of key names to press in sequence (e.g. ["ctrl+c", "arrow_up", "enter"]). Mutually exclusive with key. Maximum 256 entries per request.
keystringNoSingle key name for one-shot press (e.g. "enter"). Mutually exclusive with keys.
{
"keys": ["ctrl+c", "arrow_up", "enter"]
}
{
"terminal_id": 1042,
"keys_pressed": 2,
"bytes_written": 6
}
await client.terminal.terminalAutomation.pressTerminalKeys({
terminal_id: "1042",
data: {
keys: ["ctrl+c", "arrow_up", "enter"]
}
});

Paste text into a terminal session with optional bracketed paste mode. When bracketed=true (default), the text is wrapped in bracketed paste escape sequences if the running program has enabled DECSET 2004 (e.g., vim, zsh), preventing auto-indent mangling and other paste artifacts. UTF-8 text including emoji and CJK is fully supported.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID
NameTypeRequiredDescription
textstringYesText to paste (UTF-8)
bracketedbooleanNoUse bracketed paste mode if the program supports it. Default: true
{
"text": "git pull origin main\n",
"bracketed": true
}
{
"terminal_id": 1042,
"bytes_written": 1284,
"bracketed_active": true,
"esc_neutralized": 0
}
await client.terminal.terminalAutomation.pasteTerminalText({
terminal_id: "1042",
data: {
text: "git pull origin main\n",
bracketed: true
}
});

Block until a terminal condition is met, then return an atomic snapshot of the screen at the moment of resolution. The response includes a full snapshot for the matched, stable, timeout, and exited statuses so clients avoid a TOCTOU race between wait and a follow-up /snapshot call. The vterm_reinit status is the lone exception — it fires when the VT parser was torn down mid-wait (typically due to a memory-cap resize) and no coherent snapshot can be captured; the client should retry.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID

pattern is required when mode is regex or either.

NameTypeRequiredDescription
modestringNoWait mode: stable, regex, or either. Default: stable
debounce_msintegerNoStable mode debounce in milliseconds (10-60000). Default: 100
patternstringNoPCRE2 regex pattern (required for regex/either modes, max 1024 bytes)
timeout_msintegerNoHard deadline in milliseconds (10-300000). Default: 5000
search_scopestringNoWhere to search: screen, scrollback, or all. Default: screen
include_colorsbooleanNoInclude colored_lines in response snapshot. Default: false
include_highlightsbooleanNoInclude highlights in response snapshot. Default: true
{
"mode": "stable",
"debounce_ms": 150,
"timeout_ms": 5000
}
{
"status": "matched",
"match": {
"row": 3,
"col": 0,
"text": "build successful"
},
"snapshot": {
"terminal_id": 1042,
"sequence": 4312,
"title": "make",
"alt_screen": false,
"lines": [
"$ make build",
"Compiling project v1.2.3...",
"build successful"
]
}
}
const result = await client.terminal.terminalAutomation.waitForTerminal({
terminal_id: "1042",
data: {
mode: "stable",
debounce_ms: 150,
timeout_ms: 5000
}
});