Skip to content
Hoody.com

Drive TUI applications programmatically: snapshot the rendered screen, search with regex, send named key presses, paste bracketed text, inject cell-based mouse events, and block until a screen condition is met. All endpoints read from and write to a server-side libvterm parser that mirrors the browser’s xterm.js state, so what automation sees matches what a connected user sees. Use these endpoints to script CLI tools, drive installers headlessly, or build agent-style workflows that observe and react to terminal output.

Returns a rendered snapshot of the terminal screen as seen by a user. The response includes the visible text grid (lines array), cursor position, window title, fullscreen (alt-screen) state, reverse-video highlight spans, and a monotonic sequence counter. Optionally includes ANSI SGR colored lines. On the 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 window
curl -G \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/snapshot \
-H "Authorization: Bearer <token>" \
--data-urlencode "terminal_id=1" \
--data-urlencode "include_colors=true"

Search the rendered terminal screen (or scrollback) for a PCRE2 regular expression. Returns cell-coordinate hits with matched text. Supports case-insensitive matching, result limits, and scope selection. Pattern length is capped at 1024 bytes; the scan honors a 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 window
curl -G \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/find \
-H "Authorization: Bearer <token>" \
--data-urlencode "terminal_id=1" \
--data-urlencode "pattern=error|warning" \
--data-urlencode "scope=all" \
--data-urlencode "case_insensitive=true"

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 the last screen change, alt-screen flag, title, scrollback length, and active waiter count. Useful for debugging automation workflows — for example, answering “why did my wait timeout? did the screen actually change?”.

NameInTypeRequiredDescription
terminal_idpathstringYesTerminal session ID
Terminal window
curl -X GET \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/1/automation \
-H "Authorization: Bearer <token>"

Returns global metrics for the server-side VT parser: active vterm session count, memory used and cap in MB, total active 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.

Terminal window
curl -X GET \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/automation/metrics \
-H "Authorization: Bearer <token>"

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.

Terminal window
curl -X GET \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/keys \
-H "Authorization: Bearer <token>"

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), producing correct byte sequences for programs like vim, htop, and tmux. Supports letters, ctrl+letter, arrow keys, function keys, enter, tab, escape, backspace, and more. All keys are validated before any are sent — a single unknown key rejects the entire request with no partial writes.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID

Provide exactly one of keys (array) or key (single string). The fields are mutually exclusive.

FieldTypeRequiredDescription
keysarray of stringsNoArray of key names to press in sequence (for example ["ctrl+c", "arrow_up", "enter"]). Mutually exclusive with key. Maximum 256 entries per request.
keystringNoSingle key name for one-shot press (for example "enter"). Mutually exclusive with keys.
Terminal window
curl -X POST \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/press?terminal_id=1 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"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 (for example vim, zsh). This prevents auto-indent mangling and other paste artifacts. When bracketed=false, the text is sent as raw keystrokes. UTF-8 text including emoji and CJK is fully supported.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID
FieldTypeRequiredDescription
textstringYesText to paste (UTF-8)
bracketedbooleanNoUse bracketed paste mode if the program supports it. Default: true
Terminal window
curl -X POST \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/paste?terminal_id=1 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"text": "git commit -m \"fix: handle empty input edge case\"\n",
"bracketed": true
}'

Send deterministic mouse events to a terminal session using libvterm’s mouse API. Mouse protocol output is emitted only when the target program has enabled terminal mouse reporting. Events are validated before any are sent — matching the all-or-nothing contract of /press.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID

Provide exactly one of event (single object) or events (array of 1 to 256 objects). The fields are mutually exclusive.

FieldTypeRequiredDescription
eventTerminalMouseEventNoA single mouse event to send. Mutually exclusive with events.
eventsarray of TerminalMouseEventNoA batch of mouse events (1 to 256 items). Mutually exclusive with event.
FieldTypeRequiredDescription
typestringYesMouse event kind: move, down, up, click, or scroll. click expands to a down/up pair; scroll uses wheel buttons.
rowinteger >= 0YesZero-based terminal row cell.
colinteger >= 0YesZero-based terminal column cell.
buttoninteger 1-5NoMouse button. Non-scroll events accept 1-3; scroll accepts 4-5.
amountinteger 1-20NoScroll repeat count for scroll events.
directionstringNoOptional scroll direction (up or down); overrides the scroll button. Scroll only.
modifiersarray of stringsNoKeyboard modifiers applied to the mouse event. Each entry is one of shift, alt, meta, ctrl, or control. Maximum 8 entries.
Terminal window
curl -X POST \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/mouse?terminal_id=1 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "type": "move", "row": 10, "col": 5 },
{ "type": "down", "row": 10, "col": 5, "button": 1 },
{ "type": "up", "row": 10, "col": 5, "button": 1 }
]
}'

Block until a terminal condition is met, then return an atomic snapshot of the screen at the moment of resolution. Supports three modes:

  • stable — no screen updates for debounce_ms (default)
  • regex — a PCRE2 pattern matches on the screen
  • either — first condition wins

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 due to a memory-cap resize and no coherent snapshot can be captured (clients should retry). Maximum 16 concurrent waiters per session.

NameInTypeRequiredDescription
terminal_idquerystringYesTerminal session ID
FieldTypeRequiredDescription
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 the response snapshot. Default: false
include_highlightsbooleanNoInclude highlights in the response snapshot. Default: true
Terminal window
curl -X POST \
https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/wait?terminal_id=1 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"mode": "regex",
"pattern": "\\$ ",
"timeout_ms": 5000,
"search_scope": "screen"
}'