Why Is It Designed This Way?
Why is the session a server separate from the client?
Child processes and workspace state must survive detach, reconnect, and multiple viewers. The client owns one physical terminal; the server owns the durable interactive session.
Why use subsystem-owner threads instead of shared locks everywhere?
Screen layout, PTY lifecycle, plugin execution, and terminal writing have different blocking behavior and invariants. Typed queues serialize each domain’s mutations and make cross-domain causality visible.
Why use Tokio if the main owners are threads?
Waiting for readiness from many PTY file descriptors and timers is exactly where async multiplexing helps. It does not follow that pane geometry or VTE state should become concurrently mutable async state.
Why interpret keybindings on the server?
The server owns current modes, shared-session state, and runtime configuration. A thin client can reconnect or coexist with other clients without becoming a second authority on what a key means.
Why route terminal input through Screen before the PTY?
The same bytes may mean UI rename/search input, synchronized-pane broadcast, plugin interception, or focused-terminal input depending on session state. Screen owns that decision.
Why have a separate PTY writer thread?
Writing a program’s stdin while coupling it to stdout processing can deadlock real terminal applications. The writer also gives partial writes and fairness one explicit owner.
Why bound output admission but leave many control channels unbounded?
PTY output is high-volume and naturally pressure-sensitive. Control messages must often cross ownership boundaries without blocking an owner that is needed to service the destination. The tradeoff is intentional, though unbounded control traffic still requires disciplined producers.
Why debounce rendering?
Terminal programs emit bursts of many tiny updates. Rendering each one repeats layout and ANSI serialization work and can make Screen fall behind. A short window trades imperceptible latency for much less redundant work.
Why attach a oneshot completion token to selected actions?
Channels prove delivery, not logical completion. A token that travels to the last responsible owner lets callers order dependent actions without turning every instruction into heavyweight request/response RPC.
Why use trait objects for panes?
Terminal and plugin panes occupy the same runtime layout and need the same operations. The collection is heterogeneous by product design, so dynamic dispatch belongs exactly at that boundary.