Skip to content

Support agent-created terminals in the controller terminal surface #266

Description

@germanescobar

Summary

Extend the controller terminal surface from #261 with a create action so an agent can spawn a new persistent terminal in its own worktree, instead of only being able to drive terminals the user has already opened in the Terminals tab.

Today the surface exposes list, run, snapshot, and tail, but no way to create a new terminal — that was an explicit non-goal in #261 ("Creating a terminal remains a UI action"). In practice this is the most common workflow we'd want agents to do without round-tripping through the user:

  • "start the dev server in a new terminal and tail the logs"
  • "open a terminal here, run npm test, and stream the result"
  • "kick off a long-running build in its own terminal so I can keep working"

Right now the agent has to ask the user to open a tab and tell it the id, or — worse — fall back to its own shell via run_command, which doesn't show up in the user's Terminals tab and breaks the "user sees exactly what the agent sees" guarantee.

Goals

  • Add a terminal create CLI subcommand and matching route action that spawns a new persistent terminal in the agent's current worktree.
  • Keep the new terminal immediately visible in the user's Terminals tab (same tmux session, same buffer, same WebSocket stream).
  • Preserve the worktree-scoping property from Add agent-controlled terminal surface (controller terminal CLI + skill) #261: the new terminal must live in the worktree the agent is running in, resolved via findWorktreeByPath like the rest of the surface.
  • Reuse the existing ptyManager lifecycle so the new terminal behaves identically to one the user opened from the UI — same buffer, same onData subscribers, same cleanup.

Proposed shape

Mirrors the existing controller terminal surface.

CLI

controller terminal create <label...>   # or just `terminal create` with a default label

Returns the new terminal's {id, label, worktreeId, projectId} so the agent can chain into run / snapshot / tail.

Route

POST /api/terminal/command gains a create action alongside the existing ones. Takes {cwd, action: "create", params: {label}}, resolves the cwd to (projectId, worktreeId) via findWorktreeByPath, then asks ptyManager to open a new session with a fresh id that matches normalizeTerminalId.

ptyManager

Likely a new create(projectId, worktreeId, label) method (or a thin wrapper around getOrCreate with a fresh id). The renderer needs to be notified that a new terminal exists so it appears in the user's Terminals tab — either:

  • a new WebSocket broadcast / event on the existing /ws/terminal channel, or
  • an HTTP poll on terminal list when the UI is open.

Non-goals

  • Cross-worktree or cross-project creation (same constraint as the rest of the terminal surface).
  • Letting agents delete or rename terminals they didn't create (or any terminal, for that matter — out of scope here, separate issue if we want it).
  • Changing the existing renderer-side Terminal creation flow.
  • Naming/label conflict resolution beyond what normalizeTerminalId already enforces.

Open questions

  • Should the agent be able to choose the working directory of the new terminal, or should it always default to the worktree root? Worktree root is simpler and matches the user-UI behavior; cwd override is more flexible but adds a vector for escape.
  • Should creation emit an event to the renderer, or should the UI just discover the new terminal on its next terminal list (which it doesn't currently poll)? Defining this is the trickiest part of the implementation — happy to take whatever shape the reviewer prefers.
  • Do we want a terminal delete companion in the same change, or strictly creation? My instinct is strictly creation for this issue.

Acceptance criteria

  • controller terminal create [label] opens a new persistent terminal in the agent's worktree and prints its id.
  • The new terminal appears in the user's Terminals tab without a manual refresh.
  • terminal list returns the new terminal alongside user-opened ones.
  • terminal run / snapshot / tail work against the new id exactly like a user-opened terminal.
  • The agent cannot create a terminal in a different worktree (verified by negative test against findWorktreeByPath).
  • Existing Add agent-controlled terminal surface (controller terminal CLI + skill) #261 acceptance criteria still hold — no regression in the other subcommands.

Depends on

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions