0.1 · macOS, Windows, Linux · MIT
Native interfaces in Rust and Luau that do no work when nothing changes.
zgx is a retained-mode GUI framework in Rust for macOS, Windows and Linux. Components mount once and fine-grained signals update only the nodes that depend on them, so an idle window does no work and a busy one repaints only what changed. Interfaces are written in Rust or in Luau scripts that hot reload without losing state. It is young (0.1, used from git) and its API still changes.
use zgx::compose::prelude::*;
use zgx_desktop::{Application, WindowOptions};
fn main() -> Result<(), Box<dyn std::error::Error>> {
Application::new()
.window(WindowOptions { title: "Hello".into(), ..Default::default() })
.run(|cx| {
let count = cx.ui.signal(0);
let shown = count.clone();
cx.render(
row()
.p(24.)
.gap(12.)
.child(button().child(text("Add")).on_click(move || {
count.set(count.get() + 1);
}))
.child(text_signal(move || format!("Clicked {} times", shown.get()))),
);
})
}local count = ui.state("count", 0)
return ui.row {
p = 24,
gap = 12,
ui.button { on_click = ui.add(count, 1), "Add" },
ui.text { "Clicked {count} times" },
}zgx-run hello/ opens it. Save, and the window updates with the count kept.
Measured, not claimed
zgx uses the least CPU in 10 of 10 tests and the least GPU power in 9, against GPUI Fast, MyGo and Rune, and none of its frames run long.
- CPU, heavy dashboard (both)
- 9.0%
- GPUI Fast 43% lessMyGo 48% lessRune 59% less
- GPU power, heavy dashboard (both)
- 154 mW
- GPUI Fast 7% lessMyGo 32% lessRune 68% less
- Long frames (over 25 ms)
- 0%
- GPUI Fast, MyGo and Rune: up to 20.6%
- CPU while idle
- 0.00%
- GPUI Fast 0.37%MyGo 0.00%Rune 0.00%
One Apple M5 Max, macOS, 2026-10-25; zgx at c3c0dc9. Medians of fresh launches, lower is better.Every scene, every trial
Documentation
Five sets, each with its own sidebar. Every page is the repository's own docs, rebuilt as they change.
What it has
- Layout as CSS's flexbox and grid do it, defaults included: children stretch across and shrink to fit (
min-width: auto), grids, wrapping, percentages, absolute positioning,display: contents, right-to-left with logicalstart/endedges, and layouts that answer the room they have. - Text shaped rich text with font fallbacks, selectable documents (drag, double and triple press, copy as HTML), editors with undo, clipboard, spellchecking, IME (Japanese, Chinese, Korean) and bidirectional text.
- Paint a wgpu renderer (Metal, Direct3D 12, Vulkan; GL on Linux where no Vulkan driver is) that redraws only damaged regions, with rounded borders, gradients, shadows, backdrop blur, SVG, images, canvas drawing and custom WGSL fills.
- Controls buttons, inputs, checkboxes, sliders, progress, virtual lists, scroll views with native scrollbars and rubber-banding, menus, popovers, modals, tooltips, web views (WebKit on macOS, WebView2 on Windows) and terminals (Ghostty, on macOS).
- Components (
zgx-components): a data grid, a tree view, a calendar, a date picker and a time field, a combobox, a select, tabs, toasts, a command palette, a segmented control, a stepper, a disclosure and an accordion, built on the controls above, keyboard complete and accessible. - The platform native menus and dialogs, multiple windows, the clipboard and primary selection, drag and drop, touch and pen, the system's accent, appearance, text size, reduced motion, contrast and transparency, and the user's language direction.
- Accessibility through AccessKit (VoiceOver, Narrator, Orca): roles, headings, live regions, selection and keyboard-only use, with focus groups as ARIA's composite widgets.
- Scripting Luau with types, a linter, hot reload that keeps state, anime.js-style animation, sandboxed plugins, and
zgx-runto run a script as an app. Release builds carry scripts compiled into the binary.
Built to be driven by agents
zgx inspect reads a running app's tree, states, errors and frame costs, and clicks, types and presses keys by the same targets its tests use. As an MCP server, any agent can use it.
claude mcp add zgx -- zgx inspect mcp
zgx inspect tree --depth 2
zgx inspect click '"Send"'
zgx inspect frames 5