You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We drive an interactive PTY (execd /pty/{id}/ws) from a client app and we'd like a second frontend to watch the same live session in real time — e.g. an iOS app actively typing while a web dashboard mirrors the exact same terminal (a shared terminal, like tmux attach or VS Code Live Share). Use cases: pair-debugging, support/observability, multi-device continuity for a coding-agent session.
Today execd allows only one WebSocket per PTY session: PTYSessionWebSocket locks the session (session.LockWS() in components/execd/pkg/web/controller/pty_ws.go) and a second connection gets a 409 until the first closes. So two clients can't attach to the same shell at once. The only way to "share" is to multiplex in front of execd (hold one upstream WS and fan it out to N clients), which every integrator has to re-implement.
How could it be?
A multi-attach / shared mode for PTY sessions in execd:
Allow N concurrent WebSocket clients on the same /pty/{id}/ws.
Output is broadcast to all attached clients (each receives the same stdout/replay stream). The existing replay buffer + ?since= already lets a late joiner catch up to the current screen — ideal for "attach and see what's already there".
Input policy (pick one, or expose it as a query flag):
?mode=viewer → read-only attachment (receives output, stdin ignored). Simplest, zero contention; covers the "watch only" case.
default / ?mode=rw → collaborative (any client's stdin is forwarded), like a shared tmux.
Resize policy when client sizes differ: use the smallest common rows/cols (tmux-style) so no client is clipped.
Backwards compatible: today's single-client behaviour stays the default; sharing is opt-in via a flag, so nothing breaks. The 409 lock could remain for exclusive rw and be relaxed for viewers.
Input: the same /pty/{id}/ws endpoint + an optional mode/readonly query param. Output: each client receives the normal frame stream (binary 0x01 stdout, 0x03 replay, JSON control frames).
Other related information
Constraint in code: components/execd/pkg/web/controller/pty_ws.go (LockWS/UnlockWS, 409 on the second client).
Late-join catch-up already exists via the replay buffer (?since=), which is most of the hard part — this request is mainly about lifting the single-WS lock and fanning out the output stream to multiple clients.
Why do you need it?
We drive an interactive PTY (execd
/pty/{id}/ws) from a client app and we'd like a second frontend to watch the same live session in real time — e.g. an iOS app actively typing while a web dashboard mirrors the exact same terminal (a shared terminal, liketmux attachor VS Code Live Share). Use cases: pair-debugging, support/observability, multi-device continuity for a coding-agent session.Today execd allows only one WebSocket per PTY session:
PTYSessionWebSocketlocks the session (session.LockWS()incomponents/execd/pkg/web/controller/pty_ws.go) and a second connection gets a 409 until the first closes. So two clients can't attach to the same shell at once. The only way to "share" is to multiplex in front of execd (hold one upstream WS and fan it out to N clients), which every integrator has to re-implement.How could it be?
A multi-attach / shared mode for PTY sessions in execd:
/pty/{id}/ws.?since=already lets a late joiner catch up to the current screen — ideal for "attach and see what's already there".?mode=viewer→ read-only attachment (receives output, stdin ignored). Simplest, zero contention; covers the "watch only" case.?mode=rw→ collaborative (any client's stdin is forwarded), like a shared tmux.rwand be relaxed for viewers.Input: the same
/pty/{id}/wsendpoint + an optionalmode/readonlyquery param. Output: each client receives the normal frame stream (binary0x01stdout,0x03replay, JSON control frames).Other related information
components/execd/pkg/web/controller/pty_ws.go(LockWS/UnlockWS, 409 on the second client).?since=), which is most of the hard part — this request is mainly about lifting the single-WS lock and fanning out the output stream to multiple clients.agent-sandbox).