Note

Known limits of a shared persistent terminal

Failure boundaries in shell recovery, cancellation, replay, backpressure, terminal negotiation, and interactive programs.

Related project: code-with-pi

Part 3 of Building code-with-pi

Persistence is useful only if its failure boundaries remain visible. These are the current limits rather than a portability or reliability claim.


  1. Windows requires ConPTY (Windows 10 1809/build 17763 or later). The validated host is Windows 11 build 26200.
  2. Linux/POSIX is validated on Arch Linux with Bash 5.3, zsh 5.9.1, Oh My Zsh/Powerlevel10k, tmux 3.6b, Kitty 0.47.1, GCC 16.1.1, and Pi 0.81.1. This does not yet imply distribution-wide or macOS/BSD portability. Automatic shell restart, the Windows 64 MiB attach writer queue, and the PowerShell-specific 150 ms output-settle path do not yet have POSIX parity.
  3. A command that exits, replaces, or fatally corrupts the shell can destroy shell-local state. The broker reports the loss. Windows can create a fresh shell when configured; POSIX automatic restart is not implemented, and neither platform can reconstruct in-memory variables/functions.
  4. Ctrl+C is delivered first as ETX through the PTY. Agent cancellation escalates after configured grace periods: Windows uses descendant/Job termination, while POSIX signals the foreground process group. Process discovery and ownership transitions are inherently racy.
  5. PowerShell and PSReadLine can render bytes after prompt/end callbacks. The Windows broker therefore waits for a 150 ms output-quiescent window. This adds a small command-completion latency and is a pragmatic terminal boundary, not a guarantee against a deliberately delayed background writer.
  6. Background jobs that continue writing after their launching command has settled are shared terminal output. Later bytes appear in the pane/transcript and can overlap a later command, as they would in a normal interactive shell.
  7. Reconnect replays a bounded 256 KiB byte tail. It does not emulate terminal screen state, so arbitrary alternate-screen TUIs cannot always restore their prior display after detach. The complete raw transcript remains on disk.
  8. Monitor/terminal state is kept outside PTY screen content: Windows uses the active pane title and POSIX uses pane_title displayed by a tmux border. A child program can temporarily set its own title, but the attach client reapplies local mode status after the next complete output record or local input event. A live Kitty screenshot passed basic alternate-screen cursor/color/Unicode rendering and restoration; complex full-screen applications during live resize remain application-specific.
  9. Ctrl+\\ is reserved by the attach client in terminal mode and cannot be sent to the child through that pane. It was selected to avoid interpreting ordinary :m/:t shell text as local commands. Ctrl+] remains reserved for detach.
  10. Monitor mode passes recognized CSI/OSC/DCS terminal-generated replies while blocking ordinary human input. Exotic private terminal reply formats outside that recognizer may be ignored; switch to terminal mode if an unusual application requires them.
  11. Windows attach delivery is bounded to 64 MiB. A terminal that falls more than that far behind is disconnected to protect broker memory. POSIX attach writes are currently synchronous and do not yet provide equivalent queue/backpressure behavior.
  12. PowerShell object output is passed through a streaming text formatter so the model and transcript receive visible output before completion. Complex formatting can differ slightly from an unwrapped top-level pipeline. Native/TUI programs still write directly to the ConPTY.
  13. The prompt/helper functions can be intentionally overwritten by a command. The wrapper reinstalls the marker prompt where possible, but this is not a sandbox against hostile same-user shell mutation.
  14. Marker nonces are random and prevent accidental/foreign OSC collisions. Code running inside the same shell can inspect process state and may forge markers; it already has the user's authority and is outside the isolation boundary.
  15. Session transcripts and command files are not redacted. Commands, paths, output, and secrets printed by programs remain on disk until cleaned.
  16. pio uses wt.exe -w last when invoked inside Windows Terminal. -w 0 was rejected because it targets the first Terminal window rather than reliably following the caller on multi-window desktops. A different Terminal window becoming most-recently-used during the short launch interval can still affect Windows Terminal's own routing.
  17. The extension overrides bash only when all workspace environment variables are present. pi-raw intentionally retains stock Pi behavior.
  18. The optional -SetAsDefaultPi path edits a marker-delimited profile block after making a backup. It was not enabled on the validation machine; the default no-profile install and uninstall were tested.
  19. POSIX commands are dot-sourced to preserve shell state. If a timeout interrupts a foreground command in a multi-statement script, Bash can continue with later statements before returning to the prompt. The broker still reports TIMED_OUT/130, but this is not yet a strict stop-the-script guarantee; destructive multi-step commands should use explicit failure guards.
  20. The extension currently returns failed/timed-out/interrupted status as structured tool text rather than throwing. Pi therefore does not set its native isError: true flag even though the broker status and exit code are correct.
  21. Because commands run in an interactive PTY, programs may enable pagers or interactive UI that would be disabled in a pipe. Agent commands should use noninteractive flags such as git --no-pager; timeout recovery works, but an unexpected pager can otherwise wait indefinitely.
  22. zsh startup plugins and precmd hooks are intentionally preserved. Their output, latency, network calls, or side effects become part of shared prompt recovery and may enter command output before the private marker. A broken user .zshrc can prevent shell readiness; pio fails after its bounded startup wait instead of launching Pi against an unsettled shell.
  23. The zsh adapter reloads configured startup files in a new process; it cannot clone non-exported variables, temporary aliases/functions, directory stacks, ZLE buffers, or other in-memory state from the caller's already-running zsh.