Skip to content

Multi-window: per-client tmux attach for native window-size negotiation (dotted-filler) #613

@h0x91b

Description

@h0x91b

Hi — this is Claude (the AI assistant working on the multi-window branch). Filing this as a future improvement so we don't lose the context. Deferred on purpose: it's a large, high-risk refactor of the core PTY module.

Goal

When the same task is open in two app windows of different sizes, we want real tmux multi-client behavior: the session sizes to the focused / most-recently-active client (window-size latest), and any larger window renders tmux's dotted-filler for the unused area (content top-left, dots filling the rest). Focusing the small window should make the big one show the dotted filler — tmux does this natively once each client is its own attach.

Current architecture (the blocker)

src/bun/pty-server.ts keeps one PtySession per task with a single PTY (session.proc = one tmux attach) and a Set of WebSocket clients. PTY output is broadcast byte-for-byte to every client (flushPendingData); a resize message resizes the one shared PTY. Consequences:

  • All windows render identical bytes — they physically cannot differ (one fitted, one dotted).
  • tmux only ever knows one client size, so it never draws per-client dotted-filler.
  • Remote/browser clients proxy to the same PTY (remote-access-server.ts), so they share it too.

Current mitigation (this branch): the shared PTY is clamped to the smallest connected client (smallest-wins; larger windows letterbox with blank cells — NOT real tmux dots). See smallestClientSize / applyClientSizes in pty-server.ts and decision 060.

Desired fix — per-connection tmux attach

Give each WebSocket connection its own tmux attach-session -t <session> (its own PTY), all attaching to the same underlying tmux session. tmux then negotiates sizes natively (window-size latest) and draws the dotted-filler for larger clients automatically. "Resize on focus" becomes tmux's default behavior.

Why it's deferred (work + risk)

Significant refactor of the most battle-tested module:

  • Remove broadcast — each attach has its own output stream.
  • Dedup side-effects — bell / OSC52 clipboard / idle detection currently hook the single proc; with N attaches they'd fire N times. Need a single "primary" client or session-level detection.
  • Death vs detach — today a proc exit means "task died"; with per-client attach, one attach exiting just means a window closed. Need tmux has-session to distinguish.
  • Many documented edge-case fixes live here (decisions 036, 056, …); regression risk is real.

Acceptance

  • Two windows, same task, different sizes: focusing the small one shrinks the session; the large one shows tmux dotted-filler (matches the screenshot from the originating discussion).
  • No duplicated bells / clipboard copies / idle events.
  • Closing one window does not kill the tmux session for the other.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions