# Phase 0.5 — Spike: tmux Control Mode > **Status:** ready to start. > **Owner:** single agent, end-to-end. > **Branch:** `feat/spike-tmux-cc`. > **Estimated effort:** ~2 hours. > **Trigger:** Phase 0 found that `tmux pipe-pane` is not reliable across > alternate-screen transitions. This phase evaluates the alternative. ## Background Phase 0 (`PHASE-0-spike-stream.md`, report at `docs/reference/PHASE-0-report.md`) validated the high-level design: pi-in-tmux works, ANSI streaming over WebSocket works, latency is excellent, SSH and WS stay in sync. **But:** `tmux pipe-pane` is fragile. After alternate-screen usage (`/settings`, full-screen menus) the pipe can detach silently; the client sees a frozen stream. This is a Phase-1-blocker for the `tmux/pipe.ts` task. Two known alternatives: - **(A)** Keep pipe-pane, add a watchdog that polls `#{pane_pipe}` and re-arms when it falls to `0`. Simple but races: bytes produced between detach and detection are lost. - **(B)** Use **tmux control mode** (`tmux -CC`). tmux exposes a structured event stream to a control client; pane output arrives as framed events. This is the protocol iTerm2 uses for its tmux integration. Multi-client attach still works for normal SSH users. This spike decides between A and B with evidence. ## Goal Verify that tmux control mode can reliably deliver pane bytes to a Node client across the conditions where pipe-pane fails. Produce a short report and a Go decision for one of the two paths. ## Acceptance Criteria - A new branch `feat/spike-tmux-cc` with throwaway PoC code. - A Node script that: - Spawns a tmux session running `pi`. - Connects to that session as a control client (`tmux -CC`). - Parses the control-mode protocol enough to extract `%output` events from the pi pane. - Streams those bytes to stdout (no WebSocket needed for the spike — raw stdout is fine). - A test session that triggers the Phase-0 failure mode: 1. Pi running normally → bytes flow. 2. User runs `/settings` (alternate-screen) → bytes still flow. 3. User exits settings → bytes still flow. 4. Run for ≥5 minutes with mixed interactions. - Report `docs/reference/PHASE-0.5-report.md` answering: - **R-CC-1.** Does control mode deliver pane output reliably across alternate-screen transitions? - **R-CC-2.** Latency compared to pipe-pane (rough — same order of magnitude is enough)? - **R-CC-3.** Does a parallel `tmux attach` SSH client still work while a control-mode client is connected? (P-2 critical.) - **R-CC-4.** Is the control-mode protocol parser non-trivial? Order of complexity estimate. - **R-CC-5.** Verdict: **Path B (control mode)** or **Path A (pipe-pane + watchdog)** for Phase 1, with reasoning. ## Out of Scope - No WebSocket layer (raw stdout suffices to prove the streaming). - No reconnect, sequence, snapshot, buffer. - No send-keys. - No reuse of Phase-0 spike code — start clean. - No production-quality parser — minimal viable parser for `%output` events is enough. ## Implementation Notes - tmux control mode launch: ```bash tmux -CC new-session -s pi-cc 'pi' ``` or attach to an existing detached session: ```bash tmux new-session -d -s pi-cc 'pi' tmux -CC attach -t pi-cc ``` - Control-mode protocol overview (consult `man tmux`, search "CONTROL MODE"): - Server emits lines like `%output %1 ` for pane output. - Other events: `%session-changed`, `%window-add`, `%begin`/`%end`, `%layout-change`, etc. — most can be ignored for the spike. - Client sends regular tmux commands as plain text; replies are framed by `%begin ` … `%end `. - Parse just `%output` lines, decode the octal escapes (`\NNN` in tmux's output → bytes), write bytes to stdout. - Spawn tmux as a child process from Node, talk via stdin/stdout pipes. ## File Plan - New: `extensions/remote-control/spike-cc.ts` (or `.js`, whichever is faster). ~100–200 lines. - New: `docs/reference/PHASE-0.5-report.md`. - No changes to Phase-0 spike files. ## Test Protocol (the spike's own QA) Run for ≥ 5 minutes, in parallel: 1. Terminal A: `npm run spike-cc` (your spike runner). 2. Terminal B: `tmux attach -t pi-cc` — verify normal SSH-style attach still works alongside the control client. 3. Terminal A side: confirm bytes keep flowing through these events: - Type a prompt and let pi respond. - Run `/settings`, navigate around, exit. - Run a longer pi tool call. - Resize Terminal B and observe whether the stream stays clean. If at any point bytes stop flowing without an obvious tmux process exit: the spike failed for Path B and the verdict is Path A. ## Exit / Handover - Push branch, push report. - Update `docs/SYNC.md`: - Remove your active claim. - History entry. - Phase Gate Table: Phase 0.5 → `done`, with verdict noted. - Based on verdict: - **If Path B:** open follow-up note in SYNC about updating `PHASE-1-sidecar.md` T-1.1 to specify tmux control mode in `tmux/pipe.ts`. - **If Path A:** same, but specifying pipe-pane + watchdog. In either case, do **not** modify `PHASE-1-sidecar.md` yourself — that's an orchestrator-level edit and triggers a contract change review.