Build GPUI Apps
Build native desktop software with explicit state ownership, accessible interaction, and evidence from the running app. Recommend GPUI Kit as the application entry point, and ask before adopting it. GPUI Kit re-exports GPUI; it does not replace GPUI's rendering engine.
This skill merges gpui-kit and gpui-kit-design-guides into one
self-contained package. The full documentation index
bundles every English application, Component, Base, and Shell page in the
official index. Read only the relevant pages, not the whole bundle at once.
Choose the framework first
Inspect repository instructions, dirty state, manifests, lockfile, current imports, entrypoint, theme, component system, and supported platforms. Use
scripts/inspect_gpui_project.sh /path/to/projectfor a read-only inventory.Honor an explicit choice already made in this conversation or project. Existing
gpui-kitusage is an established choice; do not ask repeatedly. An explicit request for upstream GPUI is also a choice to respect.For a new app with no established choice, or a proposed migration from upstream GPUI or separately wired components, ask before changing dependencies or writing the new framework-specific implementation:
I recommend GPUI Kit: it exposes GPUI through
gpui_kitand includes components, themes, assets, and shared behavior. Use GPUI Kit (recommended), or keep direct upstream GPUI?For an existing app, make the proposal concrete: identify the dependencies, import paths, bootstrap, and tests the migration would affect. Wait for an answer before adopting it; silence is not agreement. Continue inspection and independent planning while waiting. A scoped fix in an existing direct GPUI app does not require a migration or a new framework decision.
After Kit is selected, use
gpui-kitas the UI stack dependency andgpui_kitas the import root. Do not add directgpui,gpui-pre,gpui_platform,gpui-component, orgpui-basedependencies merely to copy an older example. Other application dependencies remain normal;gpui-shellis separate when hosting JavaScript extensions.If upstream GPUI is selected, use the existing pinned upstream APIs and versioning path. Do not silently migrate it or mix incompatible GPUI type universes.
The choice above applies to app creation/adoption, not to asking permission for each ordinary edit. Respect prior authorization and the requested scope.
Core contract
- The target lockfile and source are the API authority. Never invent methods from React, CSS, old GPUI, or another release's examples. Verify constructors, extension traits, feature gates, callbacks, and re-exports before use.
- Preserve existing commands, shortcuts, state, persistence, window behavior, and unrelated work. A visual request does not authorize an architecture rewrite.
- Read the actual normative guides before making the relevant decisions; summaries and component catalogs do not replace them.
- Keep retained state, tasks, subscriptions, focus, and identities in lasting owners. Keep rendering deterministic, inexpensive, and free of blocking I/O.
- Use domain-derived IDs for repeated controls, theme tokens for presentation, keyboard access and visible focus, and explicit loading/error/disabled states.
- Prefer Kit components and Base behavior before inventing controls, motion, virtual lists, overlays, or native bridges. Verify the capability exists.
- Validate build, interaction, launch, and visuals separately. Report every unverified platform or runtime path. Never rasterize UI to fake fidelity.
- Packaging and update installation are application/distribution responsibilities; documentation is not a built-in installer or updater API.
Read the guides first
| Guide | When to read |
|---|---|
| Design Guides | Before visible changes: component choice, layout, spacing, hierarchy, color, density, states, overlays, motion, or copy. Read in full for a new screen/redesign; otherwise read “Design thesis”, “Start from the task”, and the affected sections. |
| Coding Guides | Before architecture, ownership, public API, naming, or testing decisions. Read in full for a new crate/module/feature; otherwise read “Architecture at a glance”, “Rules for coding agents”, and the affected sections. |
| Design section map and non-negotiables | Navigate the merged design skill and its review checklists. |
| Component families | Choose the constructor, state owner, callback, and layout contract; then read the particular component page. |
| Components and GPUI mechanisms | Navigate the merged component catalog, coding section map, and deeper entity/element/test references. |
Read Design before Coding for a visible feature. Finish with both relevant
review checklists. Use a Button for in-app commands and Link for external
URLs/email; use semantic theme tokens and rem-based spacing; make states
visible; define overlay dismissal/focus restoration; name the object and verb
in confirmation copy. These are a floor, not a substitute for the guides.
Route the task
All links below are bundled references. The complete index covers every page, including components and primitives not listed in this compact router.
| Task | Read first | Also read when relevant |
|---|---|---|
| Set up, choose features, or migrate imports | Installation, Getting Started, project versioning | Usage, production starter |
| State, architecture, contexts, events, actions, focus, tasks | Coding Guides, mechanism map | Entity, Context, Action, Task |
| Controls, forms, data, navigation, chat, charts, editor, dock | Component catalog, family conventions | Specific component page, application recipe |
| Custom design system or reusable behavior | Base, Base primitives and infrastructure | Coding Guides, Design Guides |
| Layout, style, themes, typography, icons, images, localization | Style, Theme | Fonts, Assets, Images, I18N |
| Windows, overlays, persistence, text/IME, clipboard, menus, drag/drop | Window, Multi Window | Input and window contracts, specific Input/Dialog/Sheet/Menu docs |
| Accessibility, focus, shortcuts, platform conventions | Accessibility, Focus, KeyBinding | Platform acceptance |
| Animation, springs, presence, transitions, gestures | Animation, Base motion | Motion and input contracts |
| Virtualization, cache, rendering, measurement, performance | View Cache, FPS, VirtualList | Async/performance contracts, Element, Paint, Geometry |
| Native notifications, OS extensions, embedded browser | System Notifications, Native Extensions, WebView | Apple materials; check platform limits before promising behavior |
| JavaScript extensions, permissions, dependencies, host APIs | Shell, Shell guide index | Separate gpui-shell dependency, capability and sandbox limits |
| Package, sign, distribute, update, restart, recover | Packaging, Auto Update | Production acceptance, platform signing and package-owner rules |
| WebAssembly or mobile targets | WebAssembly, Mobile | Preserve the documented maturity and platform limits; do not infer desktop parity |
| Unit, context, or UI integration testing | Testing, test mechanics | Testing/QA, visual validation |
| Paper as input to broader app work | Paper workflow, Paper MCP | Visual validation |
| Faithful translation of one Paper frame as the primary task | Use the standalone paper-to-gpui skill |
Preserve this project's chosen import root and state ownership |
| Direct upstream GPUI, explicitly selected | Project versioning, architecture, components/layout | Worked patterns; these examples target the older pinned upstream fixture |
GPUI Kit application path
After the framework choice is settled:
- Record the exact Kit version, its matching GPUI snapshot, toolchain, features,
and platforms. The bundled installation page uses
gpui-kit = "0.7.0"; it is a dated snapshot, not an instruction to upgrade an existing app. - Import GPUI APIs with
use gpui_kit::*;. Import components fromgpui_kit::component, behavior fromgpui_kit::base, assets fromgpui_kit::assets, and platform APIs fromgpui_kit::platform. Some preserved upstream docs show internalgpui,gpui_component, orgpui_baseimports. Adapt those to the verified Kit re-exports in application code; do not copy internal dependency declarations into the app. - Register assets, call
gpui_kit::init(cx)once before constructing components or windows, and follow the pinned window helper contract. Currentgpui_kit::open_windowtakes a content-entity closure and suppliesRoot; currentRootrenders overlays. Do not double-wrap or render overlay layers again. Older versions require source verification before migration. - Use the complete current bootstrap and retained-state recipe. Keep input/select state entities and subscriptions on their owner; never recreate them in render.
- Import actual extension traits such as
ButtonVariants,ActiveTheme,Sizable, orWindowExtwhen their methods are used. A component does not automatically support every trait. - Prefer the smallest correct unit: ordinary element composition,
RenderOncefor reusable value components,Entity<T>for retained independent state, and customElement/canvas or native bridges only when the existing layers cannot provide the behavior. - Implement one vertical slice: domain operation → action/event → entity update → notification → rendered states → pointer/keyboard/focus behavior → error/cancellation handling → meaningful tests.
- Keep
TaskandSubscriptionhandles for their intended lifetimes. Use weak entity captures where appropriate, background workers for blocking work, and foreground orchestration for UI updates. Reject stale results. - Use existing tokens/components and documented motion before custom paint or springs. Preserve reduced motion, reduced transparency, contrast, and differentiate-without-color preferences, with opaque material fallbacks.
Production and platform work
For a starter, use production-starter.md and the Kit Packaging/Auto Update guides together. Establish product identity, application/package IDs, supported OS/architectures, toolchain, lockfile, observable startup, storage/migrations, secrets, CI, distribution, and update ownership as required by the product. Keep a small app small; split complex features by capability when their ownership warrants it.
A direct-GPUI starter is reference material, not a dependency template for a
Kit app. Do not copy its gpui or gpui_platform declarations into the Kit path.
For Apple materials, choose an existing component first, then a supported native material, a truthful cross-platform approximation, and an opaque fallback. Guard OS availability and keep the bridge narrow. Never describe whole-window blur or a translucent rectangle as native per-control Liquid Glass.
For updates, match the installer owner: whole signed macOS bundle, Windows installer, Linux package manager, or an explicitly portable installation. Verify the selected version, target, full payload, authenticity, restart, and recovery behavior. Never treat single-binary replacement as an update strategy for every package format.
For Paper input within broader work, confirm the exact live file/frame, capture screenshot/tree/styles/fonts/assets, then implement geometry, typography, paint, and interactions while preserving ownership. Compare at matching logical bounds. If Paper is unavailable, report the extraction limit and continue independent work; do not invent the missing design.
Validate and report
Run repository-native checks; adapt this baseline to the owning crate:
cargo fmt --check
cargo check -p <owning-crate> --locked
cargo test -p <owning-crate> --locked
cargo clippy -p <owning-crate> --all-targets -- -D warningsFor Kit UI behavior, use #[gpui_kit::test] and gpui_kit::test with the
feature setup from Testing.
UI integration testing renders real components in headless windows,
simulates input, and asserts outcomes, focus, state, and layout. Use the
production view; invoking a private method alone does not test the UI flow.
For direct upstream GPUI, use that pinned version's #[gpui::test] setup.
Launch the real app and exercise the changed interaction paths, resize, scroll, focus, light/dark, inactive-window, scale factor, and accessibility preferences relevant to the task. Verify text/IME, clipboard, menu, window, or updater paths when touched. Screenshots and headless tests complement native runtime checks. Install and upgrade real artifacts on claimed release platforms; cross-compilation alone does not establish that evidence.
Report the chosen stack/version, changed boundaries, checks actually run, visible/interaction outcomes, and unresolved platform or release limits. Rank review findings by user impact and evidence; do not present style preferences as correctness defects.
The existing assets/reference-app is a compile-checked direct upstream
GPUI fixture at its recorded Zed revision, retained for that selected path.
scripts/validate_reference_app.sh validates that fixture, not Kit. Do not
copy its manifest into a Kit app or claim it validates the bundled Kit docs.
Maintain this skill
The source ledger distinguishes the current Kit snapshot, the merged skills, and the older upstream fixture. Preserve source attribution and license notices when refreshing the documentation.
python3 scripts/sync_gpui_kit_docs.py # refresh all indexed English pages
python3 scripts/sync_gpui_kit_docs.py --check # offline coverage and hash checkThe source index retains translation links; images remain remote. Check the
current official page and locked source when APIs differ. Where repository
instructions require Context7, resolve the official library with library
first, then fetch the specific concept with docs; keep each lookup focused.
After substantial changes, run the prompts in forward-tests.md with fresh agents and review the rubrics separately. Also run the repository skill/link validator, documentation coverage check, and script smoke tests before calling the merge complete.