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
Propose a low-level fixed-cell <terminal> host for applications that already own a PTY and VT parser. GPUIX would own only the final grid painter and transport boundary; shell lifecycle, escape parsing, scrollback, selection policy, and accessibility remain application concerns.
The goal is one retained host node rather than thousands of React text/run nodes per animated frame.
Motivation
Mostly bringing over all of the performance tricks I've done on localterm to the GPUIX world.
trimmed.mp4
Proposed API boundary
Portable path
A versioned frame prop carries metadata plus base64-encoded row-major cells. Each cell is a 16-byte little-endian record containing a glyph reference, foreground RGB, background RGB, flags, and reserved bytes. A side table stores multi-codepoint graphemes.
This path works through the existing React mutation transport and can be implemented by browser/WASM renderers.
Native direct path
An optional renderer capability avoids base64 and mutation JSON:
The N-API boundary copies into a latest-frame mailbox. Multiple arrivals before paint coalesce, and React is not committed for animated output.
Painter
one retained terminal node;
nearest-sampled two-pixels-per-cell texture for backgrounds and block/quadrant/shade glyphs;
ordinary text remains GPUI-shaped and uses the monochrome glyph atlas;
shaping is cached independently of ANSI color;
wide cells, bold/italic/underline/strike, cursor, ligature control, and Nerd Font routing are preserved;
same-sized animated frames retain image identity and update the atlas tile in place;
when text/cursor geometry is unchanged on macOS, the existing scene can be presented without rebuilding React, layout, prepaint, or paint.
The image-update foundation is proposed in #40. Keeping Bun/PTY delivery healthy in a real window depends on the nonblocking embedded pump proposed in #39. GPUix 0.7's resolution of #36 already lets Tab and Shift+Tab reach the focused terminal normally; no terminal-specific focus prop is needed.
Measurements
On Apple Silicon with Bun 1.4.0 and a deterministic DEC 2026 truecolor producer:
fullscreen 1470×923 logical window, 185×53 grid: 58.7 PTY callbacks, service frames, and native stages per second, all 1:1;
direct frame projection p90: 0.15 ms;
N-API staging p90: 0.31 ms;
GPUI draw p90: 0.13 ms;
100% stable-layer reuse after the initial scene;
zero React commits during animation.
The offscreen high-resolution probe measured approximately 5.31 ms median at 480×120 and 8.93 ms at 640×180. Timings are hardware-specific; the structural assertions are one node, latest-frame coalescing, no animated React commits, and one native stage per published frame.
Reference implementation
No PR is being opened, per the external-contributor policy.
The focused branch contains README documentation, a changeset, Rust unit coverage, and three React/native regressions for one-node painting, direct latest-frame coalescing, and updates without per-cell retained nodes.
Validation
Focused branch native suite: 225 passed
Focused branch React package build: passed
Full integration native suite: 227 passed
Full integration React suite: 377 passed
Downstream application suite: 319 passed
Real fullscreen telemetry described above
Would a specialized fixed-cell host fit GPUIX, or should this instead be expressed through the web-compatible canvas API discussed in #8? If the host is acceptable, is the versioned frame plus optional direct binary staging boundary appropriate?
Summary
Propose a low-level fixed-cell
<terminal>host for applications that already own a PTY and VT parser. GPUIX would own only the final grid painter and transport boundary; shell lifecycle, escape parsing, scrollback, selection policy, and accessibility remain application concerns.The goal is one retained host node rather than thousands of React text/run nodes per animated frame.
Motivation
Mostly bringing over all of the performance tricks I've done on localterm to the GPUIX world.
trimmed.mp4
Proposed API boundary
Portable path
A versioned
frameprop carries metadata plus base64-encoded row-major cells. Each cell is a 16-byte little-endian record containing a glyph reference, foreground RGB, background RGB, flags, and reserved bytes. A side table stores multi-codepoint graphemes.This path works through the existing React mutation transport and can be implemented by browser/WASM renderers.
Native direct path
An optional renderer capability avoids base64 and mutation JSON:
The N-API boundary copies into a latest-frame mailbox. Multiple arrivals before paint coalesce, and React is not committed for animated output.
Painter
The image-update foundation is proposed in #40. Keeping Bun/PTY delivery healthy in a real window depends on the nonblocking embedded pump proposed in #39. GPUix 0.7's resolution of #36 already lets Tab and Shift+Tab reach the focused terminal normally; no terminal-specific focus prop is needed.
Measurements
On Apple Silicon with Bun 1.4.0 and a deterministic DEC 2026 truecolor producer:
The offscreen high-resolution probe measured approximately 5.31 ms median at 480×120 and 8.93 ms at 640×180. Timings are hardware-specific; the structural assertions are one node, latest-frame coalescing, no animated React commits, and one native stage per published frame.
Reference implementation
No PR is being opened, per the external-contributor policy.
The focused branch contains README documentation, a changeset, Rust unit coverage, and three React/native regressions for one-node painting, direct latest-frame coalescing, and updates without per-cell retained nodes.
Validation
Would a specialized fixed-cell host fit GPUIX, or should this instead be expressed through the web-compatible canvas API discussed in #8? If the host is acceptable, is the versioned frame plus optional direct binary staging boundary appropriate?