Terminal API

Local HTTP API for AI agents to create and control terminal sessions programmatically. Designed for agentic workflows with Claude Code, Cursor, and other AI tools.

Overview

The Terminal API exposes a local HTTP server that AI agents can use to create terminal sessions, send commands, read output, and manage session lifecycles. It runs on localhost only and requires token-based authentication.

Setup

  1. In Termdock: Settings > Remote Control > Terminal API > enable the API server.
  2. Click Generate Token to create an API token.
  3. The server runs on:
    Dev: localhost:3036Prod: localhost:3037

Authentication

All requests require a Bearer token in the Authorization header:

Authorization: Bearer $TERMINAL_API_TOKEN

Rate Limiting

120 requests per 60 seconds per IP/method/path combination. Exceeding the limit returns 429 Too Many Requests.

Endpoints

GET/api/terminal/workspaces

List all available workspaces.

Response:

{ "workspaces": [
    { "id": "ws_123", "name": "my-project", "rootPath": "/home/user/my-project" }
  ]
}
POST/api/terminal/sessions

Create a new terminal session. workspaceId is required; optional: cols (80-500), rows (24-100), name, logPolicy, background. Use wider cols (e.g. 300) when an agent reads long command echoes.

Request body:

{ "workspaceId": "ws_123", "cols": 300, "logPolicy": "persist" }

Response:

{ "success": true,
  "data": { "session": {
    "id": "terminal-pty-123", "name": "my-session",
    "status": "running", "isActive": true, "background": false
  } }
}
GET/api/terminal/sessions

List all active terminal sessions.

GET/api/terminal/sessions/:id/status

Get session status including running state and metadata.

GET/api/terminal/sessions/:id/log

Retrieve session log. Only available when logPolicy="persist".

POST/api/terminal/sessions/:id/input

Send input to a terminal session. Use appendEnter: true for normal command submission. With queueUntilReady: true the write is held until the terminal is idle, or fails with TERMINAL_NOT_READY after readyTimeoutMs.

Request body:

{ "data": "npm test", "appendEnter": true, "queueUntilReady": true, "readyTimeoutMs": 30000 }
GET/api/terminal/sessions/:id/output

Read terminal output.

Query parameters:

mode       = text | raw | content | screen
lines      = 50           (number of lines)
since      = <cursor>     (output cursor; use nextCursor from a previous read)
waitForChange = true      (long-poll until new output)
timeoutMs  = 10000        (long-poll timeout)
POST/api/terminal/sessions/:id/keys

Send special keys to a session: enter, up, down, left, right, tab, esc, ctrl+c, ctrl+d.

POST/api/terminal/sessions/:id/submit

Submit input when the session is already in an interactive prompt state (TUI composer, y/n confirmation) — applies the same settle path Termdock uses for interactive input. Supports settleMs and queueUntilReady. Not a default follow-up after every normal command.

GET/api/terminal/sessions/:id/events

Server-Sent Events stream of session output events (output.new). Accepts mode=raw|text|content (screen is rejected — its cursors are screen-relative). Powers termdock session output --follow.

POST/api/terminal/sessions/:id/interrupt

Send Ctrl+C to the foreground process without destroying the session (v1.9+).

GET/api/terminal/sessions/:id/ports

List ports the session's processes are listening on (v1.15+). The same data powers the port chips on terminal tabs.

DELETE/api/terminal/sessions/:id

Destroy a terminal session and release resources.

Layout Endpoints

Control the pane layout programmatically (v1.6.2+). The same surface backs termdock layout.

GET  /api/terminal/layout                          # current layout + pane assignments
POST /api/terminal/layout                          # set layout type / session mapping
POST /api/terminal/layout/panes/:paneId/assign     # assign a session to a pane
POST /api/terminal/layout/panes/:paneId/activate   # focus a pane

Agent Sessions

Managed AI agent sessions (v1.9+) for claude, codex, and gemini. Termdock launches the agent CLI in a terminal, tracks its lifecycle (dispatch state, lifetime metadata), and exposes structured reads instead of raw scraping.

POST   /api/agent-sessions                    # create: { provider, cwd, prompt }
POST   /api/agent-sessions/attach             # attach: { provider, sessionId, cwd }
POST   /api/agent-sessions/resolve            # resolve a session target
GET    /api/agent-sessions                    # list
GET    /api/agent-sessions/:id                # status + lifecycle metadata
POST   /api/agent-sessions/:id/input          # send a follow-up prompt
POST   /api/agent-sessions/:id/interrupt      # soft-interrupt the running turn
POST   /api/agent-sessions/:id/restart        # restart the agent process
GET    /api/agent-sessions/:id/events         # SSE lifecycle events
GET    /api/agent-sessions/:id/rendered       # rendered screen snapshot
GET    /api/agent-sessions/:id/rendered/stream # SSE rendered screen stream
POST   /api/agent-sessions/hooks              # ingest provider hook events (v1.13+)
DELETE /api/agent-sessions/:id                # terminate and release

Create request body:

{ "provider": "claude", "cwd": "/home/user/my-project", "prompt": "Fix the failing tests" }

Service Tokens

Long-lived tokens for daemon consumers (v1.9+), separate from the UI-generated token. Scoped to terminal and/or agent-session (omit scopes for both). Mint with the local bootstrap secret from ~/.termdock/config/terminal-api-bootstrap.json via the X-Termdock-Bootstrap-Token header, or with the UI token. Rotation supports a graceSeconds window; a service token can rotate or revoke only itself.

POST   /api/auth/service-tokens              # create a service token
POST   /api/auth/service-tokens/:id/rotate   # rotate a token
DELETE /api/auth/service-tokens/:id          # revoke a token

Output Modes

text

Strips ANSI escape codes. Clean plain text suitable for LLM consumption.

raw

Preserves all ANSI sequences. Use when you need color or formatting data.

content

Filters out TUI chrome (progress bars, spinners). Best for extracting meaningful output.

screen

Current visible screen state, read headless-first with DOM fallback (v1.15+). Best for TUI supervision. Responses include outputHash; send ifHash to get unchanged: true cheaply.

Example: Agent Workflow

A typical AI agent workflow using curl:

# 1. Get a workspace id
WS=$(curl -s http://localhost:3037/api/terminal/workspaces \
  -H "Authorization: Bearer $TOKEN" | jq -r '.data.workspaces[0].id')

# 2. Create a session (id is at .data.session.id)
SID=$(curl -s -X POST http://localhost:3037/api/terminal/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"workspaceId\": \"$WS\"}" | jq -r '.data.session.id')

# 3. Send a command (held until the shell is idle)
curl -s -X POST http://localhost:3037/api/terminal/sessions/$SID/input \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data": "npm test", "appendEnter": true, "queueUntilReady": true}'

# 4. Poll for output (save .data.nextCursor for the next poll)
curl -s "http://localhost:3037/api/terminal/sessions/$SID/output?mode=text&lines=100" \
  -H "Authorization: Bearer $TOKEN"

# 5. Clean up
curl -s -X DELETE http://localhost:3037/api/terminal/sessions/$SID \
  -H "Authorization: Bearer $TOKEN"