# 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 env: Dictionary } ``` 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.