4.7 KiB
Phase 0 — Spike: tmux Stream PoC
Status: ready to start. Owner: single agent, end-to-end (too small to parallelise). Branch:
feat/spike-stream. Estimated effort: ~1 day.
Goal
Verify the foundational assumption of the entire spec: that we can run pi
inside tmux, tee the pane output via pipe-pane, push it as a binary
WebSocket stream, and consume it from a client without rendering artefacts
or unacceptable latency.
Output is a decision: green light for Phase 1, or list of blockers that need spec revision.
Acceptance Criteria
- A new branch
feat/spike-streaminpi-remote-control. - A CLI invocation (e.g.
pi-remote spike) that:- Spawns a tmux session
pi-spikerunningpi. - Pipes the pane via
pipe-paneto a WS endpoint onws://127.0.0.1:7799/spike. - Attaches the local terminal to the same tmux session.
- Spawns a tmux session
- A test client (raw
wscatscript or a tiny throwaway HTML page) that connects, dumps incoming binary frames to stdout (or a hex viewer) and optionally re-renders them viaxterm.js. - A written PoC report
docs/reference/PHASE-0-report.mdanswering:- R-1. Does pi run cleanly inside tmux? (Ink redraws OK, no escape sequence loss, no crashes during 10min uptime.)
- R-2. Does alternate-screen-buffer (
\e[?1049h) work? Is the stream parseable on the other side? - R-3. Is per-chunk latency acceptable (< 50ms localhost, < 200ms WAN)?
- R-4. Does the SSH session attached to the same tmux pane stay in sync with the WS stream byte-for-byte?
- R-5. Edge cases observed (mouse mode, title sequences, very wide output, etc.).
Out of Scope for Spike-0
- No authentication, no TLS — bind to 127.0.0.1 only.
- No reconnect, sequence numbers, snapshot or buffer.
- No
send-keysdirection (read-only stream is enough to verify rendering). - No multi-session — one fixed
pi-spikesession. - No iOS code.
Task Breakdown
T-0.1 — Branch + skeleton
Create feat/spike-stream. Add a new file
extensions/remote-control/spike.ts and a CLI entry (a new flag
--spike on the existing extension or a separate npm-script —
whichever is faster).
T-0.2 — tmux helper
Spawn tmux session, attach pipe-pane to a Unix FIFO or a pseudo-stream we can read from Node. Reference command:
tmux new-session -d -s pi-spike 'pi'
mkfifo /tmp/pi-spike.fifo
tmux pipe-pane -t pi-spike -o "cat > /tmp/pi-spike.fifo"
Node opens the FIFO read-side (fs.createReadStream) and exposes the byte
stream.
T-0.3 — WS server
Stand up a minimal ws server on port 7799, route /spike, send the FIFO
bytes as binary frames. No backpressure handling, no permessage-deflate yet.
T-0.4 — Test client
Two options, pick whichever is faster:
- (a)
wscat -b ws://127.0.0.1:7799/spikeand pipe throughod -cfor raw inspection. - (b) A 50-line HTML page with
xterm.js, plain WebSocket, no styling.
T-0.5 — Attach + dual-render test
Open a second terminal, run tmux attach -t pi-spike. Type into pi. Verify
that what you see in the SSH attach is identical to what arrives on the WS
client.
T-0.6 — Stress / edge cases
Briefly try:
- Resize the SSH terminal — see how tmux/pi react.
- Run a slash command that opens a full-screen menu (alternate screen).
- Paste a multi-line block.
- Let pi do a long tool call.
T-0.7 — Report
Write docs/reference/PHASE-0-report.md. One paragraph per R-question,
plus a "go / no-go for Phase 1" verdict.
File Plan
- New:
extensions/remote-control/spike.ts - New:
docs/reference/PHASE-0-report.md - Modified:
extensions/remote-control/index.ts(add--spikeflag or separate entry). - No changes to existing server.ts / html.ts / messages.ts.
Dependencies
tmuxinstalled on the dev host. macOS: already present orbrew install tmux.wslibrary: already inpackage.json.mkfifoshell command (POSIX): already present on macOS/Linux.
Risks
- R-A. Ink may refuse to run inside tmux due to TTY detection. If so,
set
FORCE_COLOR=1,TERM=xterm-256color, pass-ttto tmux. Fall back to spawning pi viaunbufferif necessary. - R-B. FIFO can have buffering issues. If line buffering causes visible lag, switch to a Unix domain socket and have Node read directly from the socket.
- R-C. tmux's
pipe-panereproduces ANSI but may drop sequences during bursts. If lossy, the alternative is to run pi inside our ownnode-pty(a much larger change, but a fallback option).
Exit / Handover
When Phase 0 closes:
- Merge
feat/spike-streamintomainonly if PoC code is reusable for Phase 1; otherwise close the branch and keep the report. - Update
SYNC.mdwith the verdict and any spec revisions needed. - Trigger Phase 1.