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
- In Termdock: Settings > Remote Control > Terminal API > enable the API server.
- Click Generate Token to create an API token.
- The server runs on:
Dev: localhost:3036Prod: localhost:3037
Authentication
All requests require a Bearer token in the Authorization header:
Authorization: Bearer $TERMINAL_API_TOKENRate Limiting
120 requests per 60 seconds per IP/method/path combination. Exceeding the limit returns 429 Too Many Requests.
Endpoints
/api/terminal/workspacesList all available workspaces.
Response:
{ "workspaces": [
{ "id": "ws_123", "name": "my-project", "rootPath": "/home/user/my-project" }
]
}/api/terminal/sessionsCreate 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
} }
}/api/terminal/sessionsList all active terminal sessions.
/api/terminal/sessions/:id/statusGet session status including running state and metadata.
/api/terminal/sessions/:id/logRetrieve session log. Only available when logPolicy="persist".
/api/terminal/sessions/:id/inputSend 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 }/api/terminal/sessions/:id/outputRead 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)
/api/terminal/sessions/:id/keysSend special keys to a session: enter, up, down, left, right, tab, esc, ctrl+c, ctrl+d.
/api/terminal/sessions/:id/submitSubmit 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.
/api/terminal/sessions/:id/eventsServer-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.
/api/terminal/sessions/:id/interruptSend Ctrl+C to the foreground process without destroying the session (v1.9+).
/api/terminal/sessions/:id/portsList ports the session's processes are listening on (v1.15+). The same data powers the port chips on terminal tabs.
/api/terminal/sessions/:idDestroy 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 releaseCreate 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"