Build GPUI Apps
Build native GPUI software that is correct before it is glossy, genuinely
platform-aware before it is Apple-styled, and verified in the running app
before it is called complete.
This is a routed umbrella skill. Read only the reference layers needed for the
task, but always follow the core contract and workflow below.
Core contract
- Inspect the target checkout before changing it: branch, dirty state,
manifests, lockfile, pinned GPUI source, app entrypoint, root view, theme,
components, assets, tests, and platform code.
- Treat the target checkout as the API authority. GPUI is pre-1.0; examples
from , Zed main, crates.io, or this skill can differ from the pinned
revision.
- Preserve working state ownership, commands, shortcuts, persistence, window
behavior, and platform integration. A visual request is not permission to
replace the app architecture.
- Keep render work deterministic and cheap. Move blocking I/O and CPU-heavy
work off the application thread, then update a live entity through the
appropriate async context.
- Give interactive elements stable IDs, semantic roles, keyboard access,
visible focus, disabled behavior, and immediate input feedback.
- Use glass as a functional navigation or control layer, not as decoration on
every surface. Never describe a flat translucent rectangle as native Liquid
Glass.
- Respect reduced motion, reduced transparency, increased contrast, and
differentiate-without-color. Provide an opaque fallback.
- Validate compilation, behavior, launch, and visuals. alone
does not prove focus, fonts, window chrome, scale factor, clipping, motion,
or material behavior.
- Do not rasterize text, controls, panels, or whole screens to fake fidelity.
- Preserve unrelated changes and report every unverified platform or runtime
path plainly.
- Treat text input, clipboard, menus, drag/drop, and window lifecycle as OS
contracts. Preserve Unicode range units, composition, focus, command state,
and stable ownership.
- For a new application, establish product identity, a pinned toolchain and
GPUI revision, observable startup, storage policy, CI, and packaging gates
before calling the starter production-ready.
Route the task
| Task | Read first | Also read when relevant |
|---|
| Set up or harden a production-ready starter app | production-starter.md | project-versioning.md, testing-qa.md |
| Orient a GPUI checkout or choose dependency features | project-versioning.md | testing-qa.md |
| Design state, events, actions, or component boundaries | architecture-state.md | async-performance.md |
| Build views, controls, layout, themes, overlays, or lists | components-layout.md | worked-patterns.md |
| Add Apple-like glass, translucency, depth, or macOS material | apple-glass.md | accessibility-platform.md |
| Add animation, drag, momentum, springs, or gesture behavior | motion-input.md | accessibility-platform.md |
| Add focus, keyboard, screen-reader, typography, or platform behavior | accessibility-platform.md | components-layout.md |
| Add editable text, IME, clipboard, drag/drop, menus, multi-window behavior, or restoration | input-windows.md | accessibility-platform.md, testing-qa.md |
| Add async loading, background work, virtualization, or performance fixes | async-performance.md | architecture-state.md |
| Add or review tests, launch checks, screenshots, or release gates | testing-qa.md | visual-validation.md |
| Translate a Paper.design selection into GPUI | paper-to-gpui.md | paper-mcp.md, visual-validation.md |
| Need complete, copyable patterns | worked-patterns.md | The domain reference for the pattern |
| Verify why a rule exists or refresh time-sensitive claims | sources.md | Current target source and official docs |
Workflow
1. Establish scope and current truth
Run the read-only inspector:
sh
scripts/inspect_gpui_project.sh /path/to/project
Then inspect directly:
- Read repository instructions and determine whether the request authorizes
edits or only diagnosis/review.
- Confirm the owning crate and the smallest surface that can satisfy the task.
- Record the GPUI declaration and exact lockfile version or Git revision.
- Find a similar component that compiles in this checkout.
- Identify current theme access, asset loading, focus conventions, actions,
overlay system, async patterns, and test support.
- Note the platform and minimum OS versions. Do not silently make a
cross-platform component macOS-only.
Read project-versioning.md before creating a
new app, changing startup, changing GPUI versions, or copying an upstream API.
For a greenfield or starter-hardening request, read
production-starter.md before choosing the
crate layout. It uses
lassejlv/gpui-starter as a concrete
minimal example, then adds the missing production contracts without pretending
every app needs every subsystem.
2. Write the behavioral contract
Before implementation, state:
- source of truth for state;
- user actions and resulting events/state transitions;
- loading, empty, disabled, error, and cancellation states;
- focus owner, tab order, shortcuts, pointer and touch behavior;
- text index units, composition, clipboard, menu, and window ownership when in
scope;
- resize and scrolling behavior;
- material tier and fallbacks;
- reduced-motion, opaque, and high-contrast behavior;
- target platforms and what must be verified on each.
For a visual translation, add the exact source frame, viewport, theme, fonts,
assets, and screenshot evidence.
3. Choose the smallest correct GPUI register
Use:
- an ordinary element tree for normal layout and styling;
- for stateless, value-like reusable components;
- an implementing for independently changing state;
- a project model entity for shared domain state;
- or a custom only when ordinary layout or painting cannot
meet the requirement;
- a narrow platform bridge only for behavior GPUI cannot supply.
Do not create an entity for every wrapper. Do not keep meaningful state in
ephemeral render-local values. Read
architecture-state.md and
components-layout.md.
4. Implement one vertical slice
Build one end-to-end path before broad extraction:
- Domain state or model operation
- Typed action or event
- Entity update
- or emitted event
- Rendered default state
- Pointer, keyboard, focus, and accessibility behavior
- Error/cancellation state
- Targeted test
Only extract a reusable component or token after a repeated semantic or visual
pattern is proven. Keep public APIs narrow and predictable.
5. Apply Apple design without lying about capability
Select the material tier in this order:
- Existing system or project component
- Native macOS 26+ behind an availability boundary
- or GPUI whole-window blur when that is the actual need
- Cross-platform GPUI approximation using semantic tint, border, highlight,
shadow, and opacity
- Opaque/high-contrast fallback
Do not stack glass on glass. Keep content surfaces mostly solid. Use concentric
geometry, restrained tint, adaptive light/dark tokens, and clear elevation.
Read apple-glass.md.
6. Make interaction physical and interruptible
- Respond on press/down, then commit on release/click.
- Keep direct manipulation 1:1 and preserve the grab offset.
- Carry velocity from gesture to settling motion.
- Retarget from current presentation state and velocity.
- Keep input active while motion runs.
- Use symmetric enter/exit paths and anchor presentations to their source.
- Prefer
AnimationExt::with_animation
for decorative finite motion when the
pinned version supports it; it integrates with GPUI reduced-motion state.
- Use explicit state plus frame requests for interactive springs. The bundled
spring.rs is a pure-Rust starting point, not a substitute
for target-version integration.
Read motion-input.md before implementing custom
animation or gestures.
For editable text, native command surfaces, drag/drop, or more than one window,
read input-windows.md. Prefer a maintained editor
component over implementing the platform input contract from scratch.
7. Protect lifecycle and performance
- Hold a returned when dropping it should cancel work; detach only when
app-lifetime completion is deliberate and errors are observed.
- Hold a when the observer has an owner; detach only when entity
lifetime semantics are correct.
- Capture in long-running work.
- Use for blocking/CPU work and or
for application-thread orchestration.
- Virtualize large collections with or .
- Avoid filesystem, network, sleep, parsing, and unbounded allocation in
.
- Request animation frames only while something is changing.
Read async-performance.md.
8. Validate in widening rings
Run repository-native checks first, then adapt this baseline:
sh
cargo fmt --check
cargo check -p <owning-crate>
cargo test -p <owning-crate>
cargo clippy -p <owning-crate> --all-targets -- -D warnings
Also:
- launch the real app;
- exercise mouse, keyboard, focus, resize, scroll, and relevant touch paths;
- verify light, dark, inactive-window, reduced-motion, opaque, and
high-contrast states where supported;
- capture matching screenshots for visual work;
- check at 1x and a high-DPI scale;
- inspect logs and task/error states;
- run at least one targeted when behavior uses GPUI input,
focus, actions, timing, or windows.
Read testing-qa.md and
visual-validation.md.
This skill includes a compile-checked, exact-revision fixture at
. It demonstrates startup, actions, entity events,
owned async work, accessibility, menus, multiple windows, virtualization,
preference-aware material fallbacks, and spring orchestration. It is a pattern
fixture, not a production component framework. Validate it with:
sh
scripts/validate_reference_app.sh
Production starter path
For “create a GPUI app,” “set up a starter,” or “make this starter
production-ready”:
- Gather the product name, package/binary slug, owned application ID,
supported platforms, minimum OS versions, distribution route, durable data,
and update owner.
- Inspect the target and the exact starter/example commit. Never copy over an
existing checkout or delete its Git history without authorization.
- Keep the minimal / split until domain code proves a separate
headless crate.
- Pin the Rust toolchain and GPUI Git revision, commit , and make
the first clean CI baseline reproducible.
- Rename identity across crates, binary, action namespace, app ID, menus,
storage, icons, packaging, and update metadata.
- Add observable startup, configuration/migrations, secret storage,
lifecycle-owned async work, accessible controls, diagnostics, and recovery
only where the product requires them.
- Replace the demo with one real vertical slice and test it from domain state
through action, GPUI update, persistence/error state, restart, and release
launch.
- Build, sign, install, upgrade, and exercise real artifacts on every claimed
platform. Report cross-compilation separately.
Do not call a raw release binary, a green
, or the unmodified
minimal example production-ready. Use the complete acceptance matrix in
production-starter.md.
Paper.design path
For any Paper-to-GPUI request:
- Require a live Paper MCP connection and one exact selected frame or node ID.
- Verify the open file with and intent with .
- Capture a 2x screenshot, hierarchy, JSX as structural evidence, computed
styles, fonts, tokens, and actual exportable assets.
- Preserve the GPUI app architecture and translate layout semantics, not DOM
wrapper count.
- Implement geometry, typography, paint, assets, and interactions in that
order.
- Compare Paper and native screenshots at matching logical bounds.
If Paper is unavailable, stop the design extraction path and explain how to
connect it. Do not recreate the design from memory. Read
paper-to-gpui.md and
paper-mcp.md.
Review standard
Rank findings by user impact and confidence. Require evidence for claims about:
- stale or dropped tasks/subscriptions;
- missed calls;
- unstable or duplicate element IDs;
- focus traps or pointer-only controls;
- blocking application-thread work;
- unbounded render allocation;
- incorrect fixed sizing or clipping;
- unsupported blur/material claims;
- missing accessibility role, label, state, or action;
- animation that ignores reduced motion;
- platform API use without availability guards;
- green compilation presented as visual or runtime proof.
Do not turn style preferences into correctness findings.
Completion report
Report:
- GPUI version/revision and target platforms;
- files and architectural boundaries changed;
- material tier and fallback behavior;
- interaction, focus, accessibility, async, and performance behavior;
- text/IME, command, window lifecycle, and restoration behavior when relevant;
- tests, builds, launch, and visual comparisons actually performed;
- remaining deltas, unverified platforms, and version-sensitive assumptions.
For the research snapshot behind this skill, read
sources.md. Refresh upstream APIs when the target
revision differs or the snapshot is no longer current.
After substantial suite changes, run the realistic prompts and reviewer-only
rubrics in forward-tests.md with fresh agents. Fix
routing or instruction gaps before publishing.