Binary data (fd 4)
fd 4 carries raw binary payloads that fd 3 metadata rows reference via byteLength. There is no framing on fd 4 itself — the metadata side tells the parser exactly how many bytes to read.
Reading order
Section titled “Reading order”If fd 3 emits these in this order:
{"id":"a","type":"image","format":"png","byteLength":4096}{"id":"b","type":"image","format":"jpeg","byteLength":12000}…the parser reads exactly 4 096 bytes off fd 4, associates them with id: "a", then reads 12 000 bytes for id: "b". Both streams are sequenced.
Named data channels
Section titled “Named data channels”Most use cases stick with the default channel (fd 4, alias "data"). For more elaborate workflows you can declare additional named channels in HYPERTERM_CHANNELS and reference them from metadata:
{"id":"raw-vid","type":"canvas2d","dataChannel":"video","byteLength":65536}The default channel is "data" (fd 4). Custom channels are not exposed by the default client libraries — they’re for advanced integrations that want to multiplex separate data streams (e.g. video frames vs control payloads).
Backpressure
Section titled “Backpressure”Writes are blocking. If τ-mux is busy rendering, the script’s next write to fd 4 will block until the read pipe drains. This is intentional — non-blocking I/O would risk silent frame loss.
Memory
Section titled “Memory”Each panel’s binary payload becomes an ArrayBuffer in the renderer. For images, the buffer is wrapped in a blob URL and assigned to an <img> element — when the panel is cleared, the URL is revoked and the buffer is released.
Security: HTML & SVG are sandboxed
Section titled “Security: HTML & SVG are sandboxed”Panels of type html or svg — whether the markup arrives inline (meta.data) or as an fd 4 payload — render inside a locked-down <iframe sandbox> (no scripts, no same-origin) carrying a strict Content-Security-Policy (script-src 'none'). This holds on both the native app and the web mirror, so a careless or compromised producer can’t run script in the host page (which on the native app holds the app’s full IPC bridge). Inline styles and data:/blob: images are allowed; <script> and inline event handlers (onerror=…) never execute.
If your panel needs to forward clicks/keys back to your script, set interactive: true in the metadata. That panel renders directly (no iframe) so its DOM events can be forwarded — an explicit, opt-in trust boundary. Only use it for markup you fully control.
Limits
Section titled “Limits”There is no hard cap, but practical limits:
- Per-panel payload — up to a few MiB is fine. Multi-hundred-MiB images will exhaust webview memory.
- Burst rate — backpressure protects you, but emitting frames faster than the renderer can consume just means your script blocks waiting for the renderer.