Shirei v0.5
A large step toward a reliable native GUI framework for Go
2026.07.10
Announcing the release of v0.5 of Shirei, the cross-platform GUI framework.
Shirei is a practical GUI framework to create desktop applications as native Go programs, not as webpages, while having a high level of flexibility and fluidity!
Native, Cross-Platform, Immediate-Mode, Flexbox Layout, Robust Text Support.
Shirei v0.5 is a big release — not a polish pass on the same stack, but a rebuild of most of the foundations underneath the API you write against. In volume it is roughly months of engineering work. In wall-clock time it landed in about two weeks, which was only possible because frontier AI coding agents have gotten very good at sustained implementation under clear direction.
The agents that did a large share of the typing on this cycle were Claude Fable 5, Claude Opus 4.5, Codex GPT 5.5, and Grok 4.5. That doesnot mean the project was handed off to a chatbot. The same human engineer who set the architecture of Shirei and hand-wrote most of the code for prior releases stayed in the loop the whole time: choosing what to build, reviewing diffs, rejecting dead ends, rewriting what did not fit, and keeping the design coherent. AI accelerated the volume of change; judgment and direction stayed human.
Shirei is still not “done,” and it is not a production bet for every app yet. It is, however, much closer to a reliable GUI framework: native backends you own end-to-end, a real text input, headless rendering for tests and CI, idle windows that stop thrashing the CPU, and a set of full example programs that exercise the stack the way a tool author would.
If you have been waiting for something more solid than an experiment, this is the release to try.
Why bother with Shirei
The pitch is the same as on the front page, but it is worth restating now that the implementation can back it up:
- Native programs, not browser chrome. One Go binary per platform — typically on the order of a few megabytes for a real utility, not a hundreds-of-MB Electron shell.
- Painless cross-platform builds. The same UI code targets macOS, Windows, and Linux. Linux and Windows backends are pure Go (no CGO), so you can cross-compile from one machine; macOS still needs a Mac host for AppKit.
- Reasonable resource use. Idle frames quiesce instead of re-rendering forever. A quiet window sits around ~1% CPU instead of chewing a core. Dense UIs got a serious caching pass (details below).
- Ergonomic immediate-mode API. Plain Go state, flexbox-style containers,
almost no boilerplate:
SetupWindow, thenRun(RootView). No DOM, no reactive graph, no widget object tree to keep in sync. - Text that is not an afterthought. Complex scripts, bidirectional layout, system fonts, and (on macOS and Windows) real IME composition in the text input.
The whole windowing and rendering path is new
Shirei used to sit on Gio for windowing and rendering. It does not anymore.
There are now four backends, each written against the platform’s native APIs — AppKit on macOS, Win32 on Windows, and both X11 and Wayland on Linux (chosen at runtime). All four feed one core software renderer: a pure-Go path from Shirei’s surface list to a pixel buffer. No GPU dependency, and no per-backend rasterizer to keep in sync.
Owning that pipeline has a practical side effect: headless rendering is a core feature, not a gimmik. Example apps can dump a frame screnshot to a PNG with no window open.
Linux now enjoys first-class support. Shirei makes it really easy to createGUI programs for Linux that are fully self contained.
Wayland is at parity with X11 for the things that matter day to day (clipboard
both ways, HiDPI, transparent client-side decorations, themed cursors with a
pure-Go fallback). Keyboard input is layout-independent everywhere: an AZERTY or
Arabic layout no longer breaks Ctrl+S-style shortcuts.
Text input that can carry real apps
The text field is no longer a demo widget. Multiline is the same input with
wrapping, scrolling, vertical caret motion, undo/redo, and grapheme-aware
editing on one code path (TextArea is a thin helper on top).
IME composition works on macOS and Windows: Japanese and other composed scripts show the in-progress string inline at the caret, the way a native field does. Composition is display-only; it does not pollute undo or the document model. Linux IME is not done yet — that is high on the list, and worth calling out if your workflow depends on it.
Widgets and interaction surface
The catalog grew toward the things tool UIs actually need:
Table[T]— generic, sortable tables (process_monitor,see_pprof)SegmentedControl— grown out of the piano’s voice pickerModal— centered card over a dimmed scrim via the popup layerDirectoryBrowse— an in-app path browser (path field + Browse… dialog), replacing the old path-autocomplete field that was easy to misuse and hard to trust. Defaults to picking folders (du,haystack); setFiles: truewhen you need regular files. This is the intentional alternative to native OS file dialogs, not a stopgap until one lands
Plus the existing virtual list, large text, and the rest of the day-to-day set documented in thetutorial.
Identity rewrite and a lot of performance work
The system that answers “which UI element is which across frames?” (focus, animation, hooked state) was rewritten as an identity tree: stable, value-matched keys scoped to the parent, dynamic string ids fully legal, and duplicate ids reported loudly instead of failing in mysterious ways.
On top of that: a content-addressed partial redraw cache, a shared glyph bitmap cache, and idle-frame quiescing. On a synthetic worst case (a dense rounded, bordered grid), frame time roughly halved with near-zero allocations; a separate render spike went from ~13ms to ~3.5ms and from ~100% CPU to ~32% on the same kind of scene. Idle windows no longer pretend they are always busy.
That is the difference between “immediate mode is fun” and “I can leave this tool open all day.”
Sound
app.StartAudio(sampleRate, fill) sits next to SetupWindow / Run: pull-based
output on AudioQueue (macOS), ALSA via purego (Linux), and winmm (Windows), with
a watchdog that rebuilds the stream if the OS kills it after sleep. Thepiano example
is the demo instrument — a small Go port of awtar’s
Karplus–Strong string synth.
Eight example apps as the proof
Features are easy to list; tools are harder to fake. This release ships a fullexamples showcase on the front page — real utilities, not toy demos:
- haystack — find-in-files into a virtualized list
- process_monitor — live process table on macOS, Linux, and Windows
- see_pprof — native
pprofviewer with a flame graph - see_exe — what modules landed in a built Go binary
- du — disk usage with a background scan
- fontviewer / icons — system fonts and bundled icon fonts
- piano — keyboard + synth (audio path)
Each card links to source and a README written for people who want both “what does this tool do?” and “what shirei patterns should I steal?” Start withhaystack if you only open one.
What is still missing
Honesty matters more than a changelog:
- Accessibility — no screen-reader / a11y story yet
- Linux IME — composed input works on macOS and Windows only for now
- Robust theming — there is no flexible styling system. Some widgets take an
accent color, but if you want a custom button look you implement it yourself
(not hard; the stock
Buttonis a fine reference to copy and restyle) - Rich text, tree widgets, and similar consumer polish — the catalog is still developer-tool shaped
Native OS file dialogs are deliberately not on the roadmap. Path picking goes
through the in-app DirectoryBrowse (and related) browser instead of
shelling out to the platform picker — folders today for the common case, with
file selection supported when you ask for it via attrs, and more file-oriented
UX still being tightened.
Mobile is under consideration, not a settled no. If it happens it will stay true to utility-style apps — not games, not rich multi-touch consumer experiences. Also out of scope for now: multiple windows and fancy GPU graphics.
None of that is meant to dampen the rest of this post. The important part is the foundation: native backends and rendering that are entirely Shirei’s own code, solid enough that leaving a tool open all day is a reasonable thing to do. If you have been waiting for that kind of baseline, try it.
Try it, and if it clicks, star the repo
go get go.hasen.dev/shirei
Clone github.com/hasenj/go-shirei, run
an example (go run ./examples/haystack), and read thetutorial.
If Shirei is the kind of GUI framework you want to exist in the Go ecosystem —please star the repository. Stars are a blunt signal, but they are how people and search engines notice that something is alive. Issues and feedback from real tools are welcome too.
Homepage: judi.systems/shirei