Files
ClaudeDo/docs/superpowers/specs/2026-07-23-conpty-interactive-sessions-design.md
T

4.7 KiB

ConPTY Interactive Sessions — Design

Date: 2026-07-23 Status: Approved (design), implementation not started

Problem

The current in-app interactive session path streams stream-json from a claude process spawned in the Worker and renders it as a chat log with a composer. It does not surface permission requests, AskUser questions, and other TUI-native interactions well — the rendering is a partial reimplementation of what the real Claude Code TUI already does. We want full fidelity for interactive work without rebuilding the TUI.

Decision

Hybrid execution model:

  • Autonomous queue tasks (Status=Queued, picked by the queue): unchanged. Headless stream-json, full orchestration (status flow, diff, review, merge).
  • Interactive sessions: an embedded ConPTY terminal running the real claude CLI, rendered in the UI process. Full TUI fidelity (permission prompts, questions, colors, everything the standalone CLI does). Detached from the review/merge/status machinery — these are a manual cockpit.

This is the third direction for interactive (external wt terminal → streaming chat → embedded ConPTY). The streaming interactive stack is removed, not run in parallel — accepted as discarded work in exchange for one interactive path and full fidelity.

Architecture

Process location

ConPTY terminal controls render in-process and spawn their child (claude) as a child of the host process. Therefore interactive sessions move out of the Worker and into the UI process. They no longer flow over SignalR. This mirrors the existing ResumeTaskInTerminal behavior (launch real claude), but embedded instead of via external wt.exe.

Worktree preparation (task-based sessions)

Interactive task sessions get the same worktree preparation as autonomous runs: session-skills seeding, agent files, MCP config, environment. The Worker performs the prep and returns a launch spec to the UI:

LaunchSpec {
  cwd:  string   // worktree path
  exe:  string   // resolved claude executable / shell
  args: string[] // e.g. --resume <sessionId>
  env:  Dictionary<string,string>
}

The command construction reuses the existing logic in WindowsTerminalLauncher.BuildResumeCommand. Guards mirror ResumeTaskInTerminal: task not Running/Queued, a persisted SessionId exists, worktree exists and is Active/Kept.

Free / ad-hoc sessions

In addition to task-based sessions, the user can open an ad-hoc terminal in a chosen directory (no task). These also get MCP config + env set up so the claudedo tools are available, but no per-level session-skills seeding tied to a task.

Terminal host control

Embed a ConPTY-capable Avalonia terminal control in the UI. Candidates:

  • SvcSystems.UI.Terminal (IvanJosipovic) — explicit ConPTY, full-screen TUI render + resize reflow, selection/mouse reporting.
  • Iciclecreek.Avalonia.Terminal — XTerm.NET + Porta.Pty, clean TerminalControl embed API.

Selection is resolved by a spike (first plan step): the acceptance criterion is that the real claude TUI renders correctly inside the control — colors, resize/reflow, and a live permission prompt are usable.

Command Center layout

  • MonitorPaneView keeps the streamed log for autonomous tasks.
  • Interactive panes host the terminal control instead of the log+composer.
  • Layout is toggleable: focus mode (tabs, one session large) ↔ overview mode (grid, several sessions at once).

Removals

Worker:

  • StreamingClaudeSession, InteractiveSessionService
  • WorkerHub interactive methods: OpenInteractiveTerminal, SendInteractiveMessage, RemoveQueuedInteractiveMessage, StopInteractiveSession, InterruptInteractiveSession
  • Broadcast events: InteractiveSessionStarted/Ended, InteractiveQueueChanged, InteractiveMessageSent
  • IdleSessionReaper and LiveSessionRegistry iff unused elsewhere (verify during implementation — do not delete blindly).

UI:

  • Composer on TaskMonitorViewModel: ComposerDraft, SubmitComposerCommand, InterruptInteractiveCommand, StopInteractiveCommand, QueuedMessages, IsInteractiveLive.
  • The composer + queued-messages portion of SessionTerminalView (the log portion stays for autonomous panes).
  • IWorkerClient interactive methods.

Open items (implementation time)

  • Whether LiveSessionRegistry is referenced outside the interactive path.
  • Exact env dictionary handed to the ConPTY control (parity with the autonomous run environment).
  • Session-id availability for a never-run task (no --resume → start fresh).

Non-goals

  • No screen-scraping of terminal output back into task status/diff/review.
  • No change to the autonomous queue execution path.