← Design · c130

research/comparison.md

Comparison: GPUI Kit, Native Shell, Tauri, Electron, the web UI

Use this file to check D2 against the alternatives on our criteria, and to judge the qmap trade-offs D8 asked for. The first table compares the five ways to put a UI on the endpoint. The second costs the four ways to show qmap from the native app. Numbers carry their metric and source; the vendors measure different things, so compare within a row with care and never across vendors as if equal. Every source was read on 2026-11-09.

The five options

CriterionGPUI KitNative ShellTauri 2ElectronWeb UI in the browser
Idle memoryNo published hello figure. A gpui-kit 0.8 app peaked at 72.7 MB on Windows in Longbridge's bench (quotes workload) 1. Zed publishes no idle RSS; review sites report 142 to 222 MB idle with no method stated 34. Discord's early GPUI build: about 290 MB with two accounts, one screenshot 35.macOS ~20 MB footprint / 89 MB resident (TSX); Windows ~15 MB private working set; Linux GTK ~79 MB private / 166 MB resident 2Hello world ~389 MB mprof peak on Linux CI (WebKitGTK) 3; ~172 MB for six WKWebView windows on macOS 4Hello world ~476 MB mprof peak on Linux CI (2023) 3; ~409 MB for six windows on macOS 4One tab: ~76 MB RSS for a static page, ~280 to 380 MB for a web app (Chromium 148, vendor measurement) 5
Idle CPURedraws on notify. Upstream GPUI's animations are costly (a spinner: 85 % of a core); GPUI Fast exists to fix that (11 %) 62 to 5 % on a gallery page at rest (macOS); Direct2D redraws on the main thread, Windows runs hotter 2Webview-dependent; unmeasuredChromium; unmeasuredA tab; a Three.js scene must render on demand or it spins the fans 7
Binary / installerHello app unmeasured. Zed 1.27 dmg 88 MB, exe 58 MB, whole editor 86 to 12 MB zipped hello; 12 to 29 MB executable 22.8 to 3.0 MB bench binary; 8.6 MB .app scaffold; "less than 600 KB" is the claim [3][4]9Runtime zip 121 to 158 MB; "most apps are >100MB" 100; the agent already ships
Tray on 3 OSesAbsent from the kit; a crate is added (see platform.md)main only, TSX only 11tray-icon feature; "Linux: Tray events are not emitted" 12Tray on all three; Linux via StatusNotifierItem 13n/a
NotificationsAbsentmain only; macOS needs a signed bundle 11Plugin; Windows installed apps only; no action buttons on desktop 14Notification; unsigned macOS binaries fail 15Web Notifications API
Auto-updateAbsent; qupdate exists in qcontrolmain only, nsh/updater 11Updater plugin, signed manifests; mac, NSIS, MSI, AppImage 16autoUpdater mac and Windows; "Linux has no built-in auto-updater" 17n/a
Deep linksAbsent; GPUI has on_open_urlsmain only, all three OSes 11Plugin; macOS needs an installed bundle; Linux/Windows need single-instance too 18setAsDefaultProtocolClient 19Browser URL
Single instance / autostartAbsent; crates existPartial / not foundPlugins, desktop only (D-Bus on Linux) 20requestSingleInstanceLock; setLoginItemSettings mac and Windows only 19n/a
Agent fluencyllms.txt 47 KB, llms-full.txt 4.7 MB, a /skills page; small training corpus; two GPUI version lines to confuse 21llms.txt 58 KB, AGENTS.md, skills; three weeks old, absent from training data 22llms.txt 2.8 KB; large corpus 23Largest corpus; no llms.txt 24Vue and Nuxt: huge corpus; our bible and layer
AccessibilityAccessKit in GPUI since 2026-05-27, off by default in Zed; the kit claims roles, states and actions tested; no GPUI app known to work with a screen reader 25Native assistive tech on mobile; documented gaps on Windows and Linux; AccessKit on the GPUI target 26Inherits the webview; tracking issue open since 2019 27Chromium's tree, enabled when assistive tech is detected 28The browser's
Brand reachEvery pixel is ours; themes by semantic tokensTailwind 4 or typed styles over native views; no token system; no backdrop filter on Linux or GPUIFull CSSFull CSSFull CSS; the layer as is
Time to V1Rust; a new framework for us; the pages must be re-expressedTSX plus Rust; weekly API breaksRust shell plus our Vue pages nearly unchangedOur Vue pages unchanged; the heaviest resultNothing to build; the thing Tyler wants to stop shipping
LanguagesRustTSX (QuickJS) and RustRust and webJS/TSVue/TS

Reading the table against the decision: the two web-wrapper rows keep our pages but cost a Chromium or a WebKit process per window, which is the argument that moved the dashboard out of the sensor in the first place. Native Shell's at-rest numbers are small on macOS and Windows but its desktop features are unreleased and its API moves weekly. GPUI Kit has no published footprint for a small app at all; the c131 spike measures that with strobe before anything is promised (R7).

What the measurements do not say

  • No idle RSS of a one-window GPUI Kit app exists anywhere public. The 72.7 MB above is a peak under load on Windows.
  • Tauri's and Electron's figures are mprof peaks during startup on Linux CI, not idle, and the Electron data point is from 2023.
  • The six-window macOS figures come from one blog post, one run.
  • Memory metrics differ per OS: footprint, private working set, private dirty, RSS, PSS. Record the metric with every number we publish.

qmap in the native app (D8)

qmap is Vue and Three.js in the web control plane: pawns, rugs and flows in an isometric scene. D8 keeps it a link in V1; Mark asked for the trade-offs laid out so he can judge which matter. Four options, costed from what the web gives.

OptionMemoryCPUWhat the person losesBuild costNotes
1. Link out to the control plane in the browser0 in the app; one tab in the browser (~76 to 380 MB RSS by page type 5)0 in the app; the tab's, which depends on whether qmap renders on demand 7App context (selection, filters) unless carried in the URL; a single window; offline; an auth hand-off from app session to browser sessionLowest: a URL with stateThe conservative V1 (ruled 2026-11-09)
2. Webview embed inside the GPUI windowA WKWebView / WebView2 / WebKitGTK process per view. No clean idle figure exists; proxies: ~29 MB per WKWebView window (six-window total divided, an estimate) 4; nsh's Windows gallery grew ~280 MB after opening WebView2 (estimate) 2The scene's, continuous unless on demand; GPU memory for Three.jsLittle context (host-to-page messaging exists in wry, not verified for the kit's wrapper); offline unless the build is bundled and served over a custom protocol; the agent's token must be injectedLow to moderate, on an experimental crategpui-webview 0.9.1 is in the kit repo, "still a experimental": WKWebView on macOS, WebView2 on Windows, WebKitGTK on Linux X11 only, Wayland unsupported; without gpui-fast the view "cannot be clipped" and covers menus and dialogs; on Windows it covers them regardless 29
3. Native render in GPUIThe app's own; no second process0 at rest (GPUI redraws on notify); pulses and orbit cost frames while animatingParity with the web qmap: two implementations to keep aligned; Three.js features (camera orbit, pulses) rebuiltHigh: a second renderer for pawns, rugs, flows, hit-testing, hover, zoom and panGPUI exposes canvas(prepaint, paint) and paint_quad / paint_path / paint_image / paint_svg 30; an isometric 2.5-D scene fits those (no perspective, no lighting). No public API hands a wgpu or Metal texture into GPUI's draw list on all three OSes; only a macOS surface with a CVPixelBuffer is visible 31
4. Opt-in local web app: the Nuxt build bundled, served locally, opened in the browser on demandA tab while open; the server is the agent's own Rust HTTP stack (no extra process) or a bundled Node (~20 to 26 MB RSS baseline for Node alone 32; Nitro more, unmeasured)A tab while open; 0 when closedA single window; in-app context (same URL-state fix as option 1). Gains offline and a local loopback tokenLow: nuxt generate output embedded in the agent plus a loopback route; Tauri documents the same pattern as its localhost plugin 33Mark's "optional secondary web app" from the initial prompt. The person opts in, so the cost is theirs to accept

How to weigh them. Options 1 and 4 keep the app's own footprint at zero and move the cost to a browser the person opened on purpose; 4 adds offline and keeps the control plane out of the loop, for a small build. Option 2 puts a browser engine inside the app's process tree on every launch where qmap is open, on a crate its authors call experimental, with Linux Wayland out. Option 3 is the only one that is truly native and truly cheap at rest, and the only one that costs a second implementation. If the native app ever needs a topology view of this one machine (which harnesses talk to which MCP servers), option 3 at small scale is the honest candidate; for the org-wide view, 1 or 4. The spike can measure 2 cheaply if Mark wants a number rather than a proxy; it cannot measure usage, which is why D8 stayed conservative.

Open questions

  1. The idle RSS, CPU and binary size of a one-window GPUI Kit hello app on the three OSes. Only the spike answers this.
  2. The idle memory of an empty WKWebView / WebView2 / WebKitGTK inside a GPUI window, with the metric stated.
  3. Whether gpui-webview exposes host-to-page messaging and whether WebGL content works inside it on each OS.
  4. Whether qmap renders on demand today or runs a continuous loop; this decides the tab's CPU in options 1, 2 and 4.
  5. Whether any GPUI app is usable with VoiceOver or NVDA; this is the accessibility row's real answer.

Sources

  1. https://github.com/longbridge/nsh-perf-bench — Windows 11, gpui-kit 0.8.0 on gpui-fast 0.1.10, PresentMon, median of 3, 2026-10-22; "simplified UI, so it isn't a like-for-like UI comparison"
  2. https://nsh.dev/docs/performance-report.md — nsh's own release-build figures; metric named per OS
  3. https://tauri-apps.github.io/benchmark_results/ (tauri-recent-linux.json, electron-recent.json) — hyperfine and mprof on GitHub Actions ubuntu-latest; method in https://raw.githubusercontent.com/tauri-apps/tauri-docs/v1/docs/references/benchmarks.md
  4. https://www.gethopp.app/blog/tauri-vs-electron — macOS, six windows, one run, 2025-04-09
  5. https://www.superchargebrowser.com/library/chrome-ram-usage-per-tab-2026.md — Chromium 148, Linux smaps_rollup, clean profile; a tab-suspender vendor, low trust but the only stated metric
  6. https://raw.githubusercontent.com/longbridge/gpui-fast/main/README.md — Linux, release, 144 Hz, mean of two runs
  7. https://r3f.docs.pmnd.rs/advanced/scaling-performance — on-demand rendering guidance
  8. https://api.github.com/repos/zed-industries/zed/releases/latest — Zed 1.27.0, 2026-11-04
  9. https://tauri.app/ and https://v2.tauri.app/start/ — the "600 KB" claim; https://v2.tauri.app/concept/size/ gives no number
  10. https://www.electronjs.org/docs/latest/why-electron; https://api.github.com/repos/electron/electron/releases/latest — Electron 45.2.3, 2026-11-04
  11. https://nsh.dev/versions/main/modules/nsh-desktop.md; https://nsh.dev/versions/main/docs/app-updates; https://raw.githubusercontent.com/longbridge/nsh/main/website/modules/nsh.md — unreleased main
  12. https://v2.tauri.app/learn/system-tray/
  13. https://www.electronjs.org/docs/latest/api/tray
  14. https://v2.tauri.app/plugin/notification/
  15. https://www.electronjs.org/docs/latest/api/notification
  16. https://v2.tauri.app/plugin/updater/
  17. https://www.electronjs.org/docs/latest/api/auto-updater
  18. https://v2.tauri.app/plugin/deep-linking/
  19. https://www.electronjs.org/docs/latest/api/app
  20. https://v2.tauri.app/plugin/single-instance/; https://v2.tauri.app/plugin/autostart/
  21. https://gpui-kit.com/llms.txt (47,730 B); https://gpui-kit.com/llms-full.txt (4,737,688 B); gpui-kit pins gpui-pre 0.3.12 while docs.rs gpui is 0.2.2
  22. https://nsh.dev/llms.txt (58,776 B); https://github.com/longbridge/nsh
  23. https://v2.tauri.app/llms.txt (2,798 B)
  24. https://www.electronjs.org/llms.txt returns 404
  25. https://github.com/zed-industries/zed/pull/56065 (merged 2026-05-27); https://github.com/zed-industries/zed/issues/41138 ("Zed doesn't support screen readers", maintainer, 2025-10-28); https://gpui-kit.com
  26. https://nsh.dev/docs/accessibility.md; https://nsh.dev/docs/gpui.md
  27. https://github.com/tauri-apps/tauri/issues/207
  28. https://www.electronjs.org/docs/latest/tutorial/accessibility
  29. https://raw.githubusercontent.com/longbridge/gpui-kit/main/crates/webview/README.md; https://docs.rs/crate/gpui-webview/latest — lb-wry 0.53.3, Longbridge's wry fork
  30. https://docs.rs/gpui/latest/gpui/fn.canvas.html; https://docs.rs/gpui/latest/gpui/struct.Window.html
  31. https://docs.rs/gpui/latest/gpui/fn.surface.html; https://raw.githubusercontent.com/zed-industries/zed/main/crates/gpui/Cargo.toml
  32. https://cirosantilli.com/javascript-memory-usage-benchmark — Node 16, idle loop and hello script, not an HTTP server
  33. https://raw.githubusercontent.com/tauri-apps/plugins-workspace/v2/README.md — the localhost plugin
  34. https://www.devtoolreviews.com/reviews/zed-editor-review-2026 (180 MB idle, dated 2026-02-27, updated 2026-10-21); https://technewsdaily.com/news/how-to-get-started-with-zeds-2026-multiplayer-code-editor/ (222 MB) — secondary, see claims.md
  35. https://www.heise.de/en/news/Discord-is-rebuilding-in-Rust-leaving-React-and-Electron-behind-11516113.html; https://dev.to/jamilxt/electron-vs-gpui-what-discords-290-mb-rust-rewrite-can-and-cannot-prove-34b6 — the 2026-11-04 announcement, see claims.md

Qpoint Brand Style Guide