Skip to content

Latest commit

 

History

History
267 lines (212 loc) · 10.6 KB

File metadata and controls

267 lines (212 loc) · 10.6 KB

Automation API

TermDeck exposes a local HTTP API for agents and scripts. The default server is http://127.0.0.1:8530. Authentication is disabled by default; configure TERMDECK_ACCESS_TOKEN before direct network exposure. When enabled, add Authorization: Bearer <token> to every request. TERMDECK_READ_ONLY=1 rejects all mutating API calls even after authentication.

These endpoints start real persistent TermDeck terminals. A successful prompt response means the prompt was written to the terminal and submitted; it does not mean the agent has finished processing it. Use GET /api/sessions/{session_id}/last_turn for the minimal status/result poll.

Projects and worktrees

The project header can switch between the repository root and every Git worktree discovered for that repository. Sessions, closed sessions, terminal layout, files, search, and Git views are scoped to the selected worktree. The root worktree always has the stable ID root; child IDs are stable across server restarts.

List the worktrees for a registered project:

curl -sS 'http://127.0.0.1:8530/api/worktrees?project=stock'

Create a worktree from the current branch, or provide base_ref and an explicit branch:

curl -sS -X POST http://127.0.0.1:8530/api/worktrees \
  -H 'Content-Type: application/json' \
  -d '{"project":"stock","name":"review","base_ref":"main"}'

TermDeck creates the branch and a free folder below <repository>-worktrees/, beside the repository itself. Pass location to put it somewhere else — it must be an absolute path outside the repository. Select the returned id when creating a terminal:

{"project":"stock","worktree_id":"wt-abc123","model":"codex","title":"reviewer"}

Delete a worktree only after its terminals are closed and purged. Set move_to_trash to move its folder to the configured trash directory; false leaves the files in place and detaches the Git worktree:

curl -sS -X DELETE http://127.0.0.1:8530/api/worktrees/wt-abc123 \
  -H 'Content-Type: application/json' \
  -d '{"project":"stock","move_to_trash":true}'

Start one terminal task (create + run in one call)

POST /api/terminals/task creates one terminal, starts it immediately, submits a single prompt, and returns the created session summary. Set origin_session to have the completed child result sent back to that session.

task_json=$(curl -sS -X POST http://127.0.0.1:8530/api/terminals/task \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "reviewer",
    "cwd": "/Users/dan/workspace/stock",
    "project": "stock",
    "model": "codex",
    "model_name": "gpt-5.6-luna xhigh",
    "permission": "workspace-write",
    "prompt": "Please review this terminal state and summarize the top 3 risks.",
    "output_path": "/tmp/termdeck/reviewer.out",
    "after": "termde",
    "origin_session": "termde",
    "bracketed": true,
    "queue": false
  }')

If project is omitted and after is the unique session/group name in a single project, TermDeck infers that project from the anchor before creating the new terminal.

For a minimal result poll, use GET /api/sessions/{session_id}/last_turn:

session_id=$(python3 -c 'import json,sys; print(json.load(sys.stdin)["session_id"])' <<< "$task_json")
curl -sS "http://127.0.0.1:8530/api/sessions/$session_id/last_turn"

Relative output_path values are resolved under cwd before writing.

Response:

{
  "session_id": "abc123...",
  "status": "completed",
  "last_turn": {"role": "assistant", "text": "..."}
}

output_path is where raw terminal bytes are appended. Set a per-project path and include that file in any monitor process that needs deterministic logs. model_name is passed as an explicit --model argument to Codex, Claude, or AGY. The request is not blocking; it returns after prompt submission. Poll last_turn for status and the latest turn.

Session IDs are globally unique, so agent callers address a terminal only by /api/sessions/{session_id}. A worktree_id is session metadata supplied in the create/task request or used as a list/layout filter; it is not part of the agent session URL.

Set worktree_id to run the child in an existing project worktree. The older worktree: true option remains available for automation callers that want TermDeck to create a worktree for that individual terminal. The optional worktree_branch and worktree_base fields select the branch name and base ref; otherwise TermDeck generates a branch under termdeck/ from the terminal title. The response includes worktree_path, worktree_branch, and the base commit. This does not make the request blocking and it does not commit changes for the agent.

Launch several named terminals

POST /api/terminals/batch creates up to 32 terminals and submits their prompts. The top-level prompt, cwd, project, model, permission, bracketed, queue, after, and worktree values are defaults for every item. An item can override any of them. after accepts an existing session name or group name (case-insensitive), or the stable session:<id> / group:<id> layout token. It inserts each new terminal immediately after that anchor. If the anchor is a member of a group, the new terminal inherits that group and is inserted immediately after that member; when several items share the same after, their request order is preserved. Every request creates new terminals; it is not idempotent.

For a new Codex terminal, name is also submitted as Codex's thread name after the new session is detected. The initial prompt is sent only after that rename and the Codex composer are ready, so it is not lost during startup. Resuming an existing Codex session does not rename the resumed thread.

curl -sS -X POST http://127.0.0.1:8530/api/terminals/batch \
  -H 'Content-Type: application/json' \
  -d '{
    "cwd": "/Users/dan/workspace/stock",
    "project": "stock",
    "model": "codex",
    "model_name": "gpt-5.6-luna xhigh",
    "permission": "workspace-write",
    "after": "existing session or group name",
    "prompt": "Inspect the current task, make the requested change, and report the result.",
    "terminals": [
      {"name": "x"},
      {"name": "y"},
      {"name": "z"}
    ]
  }'

The response contains one result per requested terminal. A terminal that was created successfully remains available even if its prompt submission fails, so a partial failure does not silently kill work already started.

{
  "requested": 3,
  "created": 3,
  "prompt_submitted": 3,
  "failed": 0,
  "items": [
    {
      "name": "x",
      "session": {
        "session_id": "abc123...",
        "title": "x",
        "project": "stock",
        "agent_kind": "codex",
        "agent_session_id": null,
        "running": true
      },
      "prompt_submitted": true,
      "queued": false
    }
  ]
}

The agent session ID may initially be null; TermDeck discovers the Codex or Claude session asynchronously after the CLI creates its session file.

Create one terminal, then submit a prompt

For callers that want individual control, use the existing session-create endpoint followed by the prompt endpoint. It also accepts the optional after field, using the same session/group name or stable layout token rules as the batch endpoint.

session_json=$(curl -sS -X POST http://127.0.0.1:8530/api/sessions \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "x",
    "cwd": "/Users/dan/workspace/stock",
    "project": "stock",
    "model": "codex",
    "model_name": "gpt-5.6-luna xhigh",
    "permission": "workspace-write",
    "after": "termde"
  }')

session_id=$(python3 -c 'import json,sys; print(json.load(sys.stdin)["session_id"])' <<< "$session_json")

curl -sS -X POST "http://127.0.0.1:8530/api/sessions/$session_id/prompt" \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Inspect the current task, make the requested change, and report the result.",
    "bracketed": true,
    "queue": false
  }'

bracketed defaults to true and sends the prompt as one paste operation before pressing Enter. Set queue: true for Codex to place the prompt in its queue with Tab instead of submitting it for immediate processing. If a requested placement target is missing or ambiguous, that terminal is still created and its prompt is still submitted; the item reports placement_error and the response increments placement_failed.

Review an isolated worktree

Every session created with worktree: true exposes its branch and worktree folder in the terminal list. Review the parent-relative commits, changed files, and diff with:

curl -sS "http://127.0.0.1:8530/api/sessions/$session_id/worktree/review"

Finish it with one of these actions:

curl -sS -X POST "http://127.0.0.1:8530/api/sessions/$session_id/worktree/finish" \
  -H 'Content-Type: application/json' \
  -d '{"action":"keep"}'

keep leaves the folder and branch in place and detaches them from TermDeck cleanup. merge requires the worktree to be clean and merges its branch into the recorded base branch, then removes the worktree and session. discard force-removes the worktree and branch and removes the session. The finish calls are separate from prompt execution; an agent must commit its changes before merge can proceed.

Other useful calls

List active terminals:

curl -sS 'http://127.0.0.1:8530/api/sessions?project=stock'

Delete a terminal and stop its running process:

curl -sS -X DELETE "http://127.0.0.1:8530/api/sessions/$session_id"

The delete succeeds only after TermDeck has terminated that session's dtach process tree and verified that its socket was removed. A failed cleanup returns HTTP 409 and leaves the terminal session visible for inspection.

Terminal process health and orphan cleanup

GET /api/terminals/processes is a local, read-only inventory of processes reachable from TermDeck's own dtach sockets. It reports each socket's session/title, whether it is attached or detached, descendant PIDs, RSS, CPU, process state, node_repl count, zombie count, and any socket with no persisted session record.

curl -sS http://127.0.0.1:8530/api/terminals/processes

POST /api/terminals/reclaim-orphans is deliberately explicit: it terminates only process trees reachable from dtach sockets that are not present in the TermDeck session store, then verifies their socket removal. It does not affect named/current sessions.

curl -sS -X POST http://127.0.0.1:8530/api/terminals/reclaim-orphans

The normal terminal WebSocket remains available at /ws/<session_id> for interactive input, resize events, scrollback, and live output. The HTTP prompt endpoint is intended for automation that does not need to attach a terminal renderer.