Skip to content

feat(workspace): give terminal panes titles, names, pins, headers and status like agents #865

Closed

Description

@Juliusolsson05

Motivation

Plain terminal panes are first-class sessions everywhere that matters structurally: they are grid leaves, Dispatch rows, command targets, operator workspace.observe entries and tmux-persistent across restarts. But most session features still ask "is this an agent?" (isAgentProviderKind, ~40 checks) where they actually mean "is this a session the user manages". The result is that a shell cannot be titled, named, pinned, jumped to by its label, auto-followed, or seen as busy, and its pane header is a hand-rolled strip (terminal $) that predates every header feature added since April: folder, color flag, title/name row, Status Mode fill.

Prompt templates and the Key Vault already reach terminals (#830 / #831 via #840). This issue finishes the job for everything else that makes sense on a shell, for both kinds of terminal:

  • plain shell panes (SessionKind 'terminal', TerminalLeaf, tmux-backed), and
  • agent panes shown in the raw terminal view (AgentTerminalLeaf, including the OpenCode Terminal runtime).

Several of the exclusions were deliberate at the time (#660 "plain shell terminals are intentionally out of scope", #836 "Terminals are never named", the #152 v1 deferral of pins). Those decisions are being reversed on purpose: a title, a name, a pin and a header are session metadata, not transcript features.

Intended behavior

  • Titles: "Set Title…" (command id unchanged, agent.title.set) and operator agents.titleSet work on any session.
  • Spoken names: with the Agent names setting on, terminals get a stable name from the same pool. Operator search finds them; the operator guide routes a named shell to terminals.input, never agents.prompt.
  • One header: plain terminals render the shared PaneHeader (no forked markup, per fix(workspace): light the status header for terminal-view agent panes #853): live folder, color flag, title/name row, Status Mode fill, TAIL pill, and the foreground command as the badge.
  • Activity: a terminal is running while a foreground command other than the shell runs (tmux pane_current_command, or node-pty's foreground process for direct PTYs). A command finishing marks the row NEW. The same signal feeds Status Mode, tab running counts, the Dispatch subtitle (shell running · npm), close confirmation, Close Old Agents and the Activity modal.
  • Navigation and organization: pin/unpin, jump by label (A2), Auto-follow, Jump to Latest and Auto-follow All, and the Agent Status panel include terminals.
  • Operator: agents.locate/show/close/restore/list/search/titleSet/pinSet accept terminals; agents.prompt keeps refusing them.
  • Terminal view: an agent pane in Terminal view shows which related agent it is displaying and can return to the parent without resizing the TUI (bug(workspace): terminal view hides which related agent a pane is showing #858).
  • Fixes found during research: Dispatch "New Agent…" picker offers Terminal; the Activity modal can bury a terminal; a terminal's ERROR badge shows in Dispatch; the Worktrees panel lists shells; terminal panes carry data-pane-id; "Undo Clear Composer" is hidden on shells; OpenCode Terminal hides transcript-only commands that silently did nothing; template Replace/Append copy is honest for terminal targets.

Stays agent-only

Prompt delivery (deliverPromptToAgent, agents.prompt), transcript features (rewind, resume, Reader, Copy Last Response, duplicate, provider switch), composer features, and the remote phone client (a deliberate security boundary; its leak is tracked separately).

Acceptance criteria

  • Every behavior above has a colocated test that fails without the change; tests that asserted the old exclusions are rewritten, with the reason in the diff.
  • The terminal foreground poller runs only while at least one terminal session exists, never overlaps itself, and emits only on change.
  • npm run typecheck, npm test, npm run check:keybindings and npm run test:contract pass on Node 24.
  • No new renderer re-render per PTY chunk in TerminalLeaf (primitive store subscriptions only).

Related: #851 / #853 (terminal-view header), #857 (OpenCode Terminal running signal, out of scope here), #858, #830, #831, #816, #660, #152.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions