Skip to content

refactor(terminal): per-client zellij attach replaces shared PTY + replay ring#194

Merged
yyovil merged 2 commits into
aoagents:mainfrom
yyovil:refactor/terminal-per-client-attach
Jun 12, 2026
Merged

refactor(terminal): per-client zellij attach replaces shared PTY + replay ring#194
yyovil merged 2 commits into
aoagents:mainfrom
yyovil:refactor/terminal-per-client-attach

Conversation

@yyovil

@yyovil yyovil commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

What

Each WebSocket client that opens a pane now gets its own server-side zellij attach PTY (backend/internal/terminal/attachment.go), replacing the shared-PTY + bounded replay-ring model (ring.go, session.go — both deleted).

Why

Zellij answers every fresh attach with its full init handshake (alt screen, SGR mouse tracking, bracketed paste) followed by a faithful repaint — but it emits that handshake once, at the head of the stream. The ring replay handed late subscribers everything except that handshake, so reconnecting clients lost mouse reporting and wheel scroll went dead. A fresh attach per client makes zellij re-send the handshake every time, by construction. The cost is one zellij client process per open pane per connection, which the zellij server is built for (yyork ships the same model).

Changes

  • attachment.go (+ unit/integration tests): per-client attach lifecycle, liveness gating, re-attach resilience
  • manager.go: tracks per-client attachments instead of fan-out sessions
  • pty_unix.go: answers every resize frame with an explicit SIGWINCH
  • frontend useTerminalSession: after each debounced resize settles, one follow-up resize frame with the same grid (RESIZE_REASSERT_MS) — a resize update the zellij client loses (raced mid-attach, coalesced during a drag) would otherwise desync the session layout until the next real grid change; paired with the backend's explicit SIGWINCH this is a no-op when already in sync
  • terminal hook/component comments updated from ring-replay vocabulary to the per-client attach model
  • docs/backend-code-structure.md updated

Testing

  • go build ./... && go test -race ./... green (terminal package: unit + integration)
  • frontend tsc --noEmit + vitest suite green

🤖 Generated with Claude Code

yyovil and others added 2 commits June 12, 2026 15:00
…play ring

Each WebSocket client that opens a pane now gets its own `zellij attach`
PTY (attachment.go) instead of sharing one PTY whose output was replayed
from a bounded byte ring. Zellij answers every fresh attach with its full
init handshake (alt screen, SGR mouse tracking, bracketed paste) and a
faithful repaint — the ring replay lost exactly that handshake, leaving
late subscribers without mouse reporting (dead wheel scroll). The cost is
one zellij client process per open pane per connection, which the zellij
server is built for (yyork ships the same model).

ring.go and session.go (fan-out, replay buffer) are deleted; manager.go
now tracks per-client attachments with liveness gating, and pty_unix.go
answers every resize frame with an explicit SIGWINCH.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-client attach

After each debounced resize settles, send one follow-up resize frame with
the same grid (RESIZE_REASSERT_MS). xterm only fires onResize on actual
grid changes, so a resize update the zellij client loses (raced mid-attach
or coalesced during a drag) would otherwise desync the session layout from
the pane until the next real change. The backend answers every resize
frame with an explicit SIGWINCH, so the re-assert is a no-op when already
in sync.

Comments in the terminal hook/components now describe the per-client
attach model (fresh server-side `zellij attach` per open, no replay ring).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@yyovil yyovil merged commit 7c97ee7 into aoagents:main Jun 12, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant