Terminals
The Terminals endpoints let you list, create, inspect, resize, write to, and read from terminal sessions over TermFlow's local REST API. This is the core surface an orchestrator or agent uses to drive a real shell.
All paths below are relative to the API base http://127.0.0.1:42031/api (the default production port). Every route in this group returns JSON.
In the default localhost-only mode, these endpoints are unauthenticated — that is safe precisely because the server is bound to 127.0.0.1 and never leaves your machine. Authentication (a bearer token) is enforced only when you turn on Expose on local network in Settings → Connections. See API overview & auth for the full model.
Endpoint summary
| Method | Path | Purpose |
|---|---|---|
GET | /api/terminals | List all active terminals |
POST | /api/terminals | Create a new terminal |
GET | /api/terminals/:id | Get one terminal's metadata |
DELETE | /api/terminals/:id | Kill and remove a terminal |
GET | /api/terminals/:id/size | Read the current cols/rows |
POST | /api/terminals/:id/size | Resize (cols/rows) |
POST | /api/terminals/:id/resize | Resize (cols/rows) — alias of POST …/size |
POST | /api/terminals/:id/input | Write raw bytes to the PTY |
GET | /api/terminals/:id/output | Read cleaned scrollback text |
GET | /api/terminals/:id/snapshot | Read a styled screen snapshot |
For back-compatibility, POST …/input, POST …/size, and POST …/resize return HTTP 200 with an {"error": …} body when the terminal id does not exist — they do not return 404. Always inspect the response body, not just the status code. (GET …/size and GET …/:id do return 404.)
The terminal object
GET /api/terminals, POST /api/terminals, and GET /api/terminals/:id all return the same shape:
{
"id": "term_a1b2c3",
"processId": "term_a1b2c3",
"name": "Terminal-powershell",
"profile": "powershell",
"status": "running",
"pid": 48213,
"createdAt": 1751600000000,
"mode": "ui",
"tabId": "tb-4f2a1c9d0"
}
| Field | Meaning |
|---|---|
id | The terminal's unique id — pass it wherever a :id is required. |
processId | Mirror of id (kept for client compatibility). |
name | Display name; defaults to Terminal-<profile> when not supplied. |
profile | The resolved shell profile id (see Profiles). |
status | Always "running" for a listed terminal. |
pid | OS process id of the spawned shell. |
createdAt | Creation timestamp. |
mode | Internal origin marker. |
tabId | The owning tab id (a tb-… value). |
List terminals
GET /api/terminals
Returns every active terminal.
Response
{
"terminals": [
{ "id": "term_a1b2c3", "processId": "term_a1b2c3", "name": "Terminal-powershell",
"profile": "powershell", "status": "running", "pid": 48213,
"createdAt": 1751600000000, "mode": "ui", "tabId": "tb-4f2a1c9d0" }
]
}
Example
curl http://127.0.0.1:42031/api/terminals
Create a terminal
POST /api/terminals
Spawns a shell and opens a corresponding tab/pane in the UI.
Body parameters (all optional)
| Field | Type | Default | Notes |
|---|---|---|---|
cols | integer | 80 | Initial column count. |
rows | integer | 24 | Initial row count. |
profileId | string | default profile | Shell profile id. profile is accepted as an alias. |
name | string | Terminal-<profile> | Display name for the tab. |
cwd | string | profile's cwd | Working directory to start in. |
tabId | string | auto-generated | Attach to an existing tab (tb-…) or let TermFlow mint one. |
paneId | string | — | Target pane when splitting. |
direction | string | — | horizontal (split right) or vertical (split bottom). |
Over REST, a new terminal defaults to 80 cols × 24 rows. The MCP create_terminal tool uses 120 × 40 instead. Pass cols/rows explicitly if you need a specific size.
An unknown or placeholder profileId (for example "default") falls back to the system default profile rather than erroring.
Response — the terminal object with status: "running" (HTTP 200). On spawn failure, HTTP 500 with {"error": …}.
Example
curl -X POST http://127.0.0.1:42031/api/terminals \
-H "Content-Type: application/json" \
-d '{ "name": "build", "cols": 120, "rows": 40 }'
Get a terminal
GET /api/terminals/:id
Returns one terminal's metadata, or HTTP 404 with {"error": "Terminal not found"}.
curl http://127.0.0.1:42031/api/terminals/term_a1b2c3
Delete a terminal
DELETE /api/terminals/:id
Kills the shell process tree and removes all associated state (matching the UI's close path).
Response
{ "status": "ok" }
If the id is unknown, the body is {"error": "Terminal not found"}.
curl -X DELETE http://127.0.0.1:42031/api/terminals/term_a1b2c3
Read the size
GET /api/terminals/:id/size
Returns the terminal's current dimensions.
Response
{ "cols": 120, "rows": 40 }
Returns HTTP 404 with {"error": "Terminal not found"} for an unknown id.
curl http://127.0.0.1:42031/api/terminals/term_a1b2c3/size
Resize a terminal
POST /api/terminals/:id/size · POST /api/terminals/:id/resize
Both paths call the same handler — use whichever you prefer.
Body parameters (both required)
| Field | Type | Notes |
|---|---|---|
cols | integer | New column count. |
rows | integer | New row count. |
Response
{ "status": "ok", "cols": 100, "rows": 30 }
For an unknown id the response is {"error": "Terminal not found"} at HTTP 200 (see the warning above).
Example
POST /api/terminals/term_a1b2c3/resize HTTP/1.1
Host: 127.0.0.1:42031
Content-Type: application/json
{ "cols": 100, "rows": 30 }
An honest note: if you need content to reflow on resize (rewrapping wrapped lines rather than just changing the viewport), that requires a tmux-backed terminal and the separate
POST /api/terminals/:id/resize-reflowpath. Plain resize adjusts the PTY dimensions only.
Send input
POST /api/terminals/:id/input
Writes raw bytes straight to the PTY, exactly as if typed. Include your own newline (\n or \r) to submit a command; nothing is added for you.
Body parameters
| Field | Type | Notes |
|---|---|---|
data | string | The raw text/bytes to write. |
Response
{ "status": "ok" }
An unknown id returns {"error": "Terminal not found"} at HTTP 200.
Example
curl -X POST http://127.0.0.1:42031/api/terminals/term_a1b2c3/input \
-H "Content-Type: application/json" \
-d '{ "data": "ls -la\n" }'
…/input is for raw keystrokes. To send a prompt to an interactive agent CLI (Claude, Gemini, Copilot, …) with the correct submission keystroke handled for you, use POST /api/terminals/:id/execute instead.
Read output
GET /api/terminals/:id/output
Returns the terminal's scrollback rendered to clean text (ANSI escape codes are always stripped).
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
lines | integer | 50 | Number of lines to return. last_lines is accepted as an alias. |
offset | integer | 0 | Pagination offset. 0 returns the last N lines (most recent); a non-zero offset paginates forward from that line. |
Response
| Field | Meaning |
|---|---|
totalLines | Total non-empty lines currently rendered. |
offset | The offset that was applied. |
raw | The selected page of lines, joined with \n. |
{
"totalLines": 128,
"offset": 0,
"raw": "$ ls -la\ntotal 24\ndrwxr-xr-x 5 user staff 160 ..."
}
An unknown or empty terminal returns {"totalLines": 0, "offset": 0, "raw": ""}.
Example
curl "http://127.0.0.1:42031/api/terminals/term_a1b2c3/output?lines=100"
Read a screen snapshot
GET /api/terminals/:id/snapshot
Returns a styled snapshot of the terminal's current visible screen — an escape-sequence string taken from TermFlow's authoritative screen parser. Written into a freshly reset terminal of the same size, it reproduces the screen exactly, including colors and cursor position. This is what a reconnecting client uses to hydrate in sync with a running TUI.
Response
| Field | Meaning |
|---|---|
snapshot | The styled escape-sequence screen content. |
rows | Row count the snapshot was captured at. |
cols | Column count the snapshot was captured at. |
{ "snapshot": "[2J[H...", "rows": 40, "cols": 120 }
An unknown id returns {"snapshot": "", "rows": 0, "cols": 0}.
The snapshot is captured at the parser's current size — align a client by calling resize first. Any cols/rows query params are accepted for forward-compatibility but intentionally ignored (no read-side resizing).
curl http://127.0.0.1:42031/api/terminals/term_a1b2c3/snapshot
…/output and …/snapshot are point-in-time reads. For a continuous live stream of terminal output, subscribe over the WebSocket API.
Next steps
- Execute & batch — send prompts to agent CLIs and fan a command out to many terminals at once.
- Terminals, panes & profiles — the mental model behind these ids.