You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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).
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).
Summary
Extend the
controller terminalsurface from #261 with acreateaction 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, andtail, 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:npm test, and stream the result"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
terminal createCLI subcommand and matching route action that spawns a new persistent terminal in the agent's current worktree.findWorktreeByPathlike the rest of the surface.ptyManagerlifecycle so the new terminal behaves identically to one the user opened from the UI — same buffer, sameonDatasubscribers, same cleanup.Proposed shape
Mirrors the existing
controller terminalsurface.CLI
Returns the new terminal's
{id, label, worktreeId, projectId}so the agent can chain intorun/snapshot/tail.Route
POST /api/terminal/commandgains acreateaction alongside the existing ones. Takes{cwd, action: "create", params: {label}}, resolves the cwd to(projectId, worktreeId)viafindWorktreeByPath, then asksptyManagerto open a new session with a fresh id that matchesnormalizeTerminalId.ptyManagerLikely a new
create(projectId, worktreeId, label)method (or a thin wrapper aroundgetOrCreatewith a fresh id). The renderer needs to be notified that a new terminal exists so it appears in the user's Terminals tab — either:/ws/terminalchannel, orterminal listwhen the UI is open.Non-goals
normalizeTerminalIdalready enforces.Open questions
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.terminal deletecompanion 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.terminal listreturns the new terminal alongside user-opened ones.terminal run/snapshot/tailwork against the new id exactly like a user-opened terminal.findWorktreeByPath).Depends on
controller terminalsurface this extends).