← Overview

Local Development

Build xgpui and run its native examples on Windows, Linux or macOS. These instructions assume Rust, the platform C/C++ toolchain, SDKs and native development libraries are already installed. The commands below use just and Bash. On Windows, put Git for Windows Bash on PATH (including when launching just from PowerShell). Run commands from the repository root.

Get the source

git clone https://github.com/gpui-luma-dev/xgpui.git
cd xgpui

Use a current stable Rust toolchain with Rust 2024 support. The first build needs network access to download registry and pinned Git dependencies. Keep the committed lockfiles. Recipes allow dependency downloads; they do not force offline mode.

Local crates and published dependencies

XGPUI keeps ten framework and backend crates in gpui/crates/: gpui, gpui-macros, gpui-platform, gpui-apple, gpui-macos, gpui-linux, gpui-windows, gpui-web, gpui-wgpu and gpui-ios. The seven XGPUI extension crates live under extensions/crates/.

Downstream versions vary by package. The iOS implementation follows the captured upstream 1.27.0 source, with XGPUI package wiring; other packages retain their existing independent version histories. Local directory names and Rust import names stay stable; Cargo package names use the XGPUI prefix:

Local directory / import nameRelease package
gpuixgpui
gpui-applexgpui-apple
gpui-iosxgpui-ios (1.26.4)
gpui-linuxxgpui-linux
gpui-macosxgpui-macos
gpui-macrosxgpui-macros
gpui-platformxgpui-platform
gpui-webxgpui-web
gpui-wgpuxgpui-wgpu
gpui-windowsxgpui-windows

All seven extension packages keep their existing xgpui-* names. scripts/release-packages.json is the authoritative name/version map. The xgpui facade is a subsequent packaging step; these package identities prepare the release and do not mean it has been published.

The supporting crates below are dependencies from the published gpui-unofficial distribution. They are no longer copied into this repository. Cargo downloads them from crates.io; manifests keep familiar Rust import names using dependency aliases. For example, the collections dependency uses the package collections-gpui-unofficial, currently at =1.27.0 to match the captured upstream release, rather than the independent downstream package versions.

Former local crate namesPublished crates.io packages
collections, gpui-util, gpui-shared-stringcollections-gpui-unofficial, gpui-util-gpui-unofficial, gpui-shared-string-gpui-unofficial
scheduler, sum-treescheduler-gpui-unofficial, sum-tree-gpui-unofficial
refineable, derive-refineablerefineable-gpui-unofficial, derive-refineable-gpui-unofficial
http-client, http-client-tls, reqwest-clienthttp-client-gpui-unofficial, http-client-tls-gpui-unofficial, reqwest-client-gpui-unofficial
util, path, perf, util-macrosutil-gpui-unofficial, path-gpui-unofficial, perf-gpui-unofficial, util-macros-gpui-unofficial
zlog, ztracing, ztracing-macrozlog-gpui-unofficial, ztracing-gpui-unofficial, ztracing-macro-gpui-unofficial

Cargo builds only the dependencies needed for the selected platform, features and targets. Some helpers are used only by optional functionality, examples or tests. The mapping is maintained in scripts/registry-crates.json, and upstream.json records the matching release and local source provenance. The website's crate pages cover local crates only.

When building a separate application against this checkout, override only the retained framework/backend packages using their xgpui-* package identities. For example, gpui = { package = "xgpui", path = "../xgpui/gpui/crates/gpui" } keeps the gpui import name. Remove old patches pointing at helper paths such as gpui/crates/collections; those directories no longer exist. Run Cargo once without --locked to refresh the application's lockfile after this dependency change, then resume locked builds.

Extension labs and benchmarks

See xgpui-ext-lab for its targets, purpose and unpublished status, and how it differs from the separate xgpui-lab application.

All native labs, repeatable benchmarks and browser demos live in the unpublished xgpui-ext-lab package under apps/xgpui-ext-lab/. They share one manifest and lockfile, with a separate binary target for each lab. Its publish = false setting keeps development workloads out of the extension library release.

Use just lab-build to compile all native lab/benchmark binaries and just lab-test to run unit and compatibility tests. The individual launch recipes below retain their names. Browser build scripts select the web feature without the default native targets; hosted demo URLs remain the same.

Choose a sample app

Run just (or just --list) to list recipes without opening a window. All native app recipes use release mode, committed lockfiles, the repository compatibility configuration and the shared target/ directory.

CommandOpens
just lab-canvasSpatial canvas, navigation and selection
just lab-mediaImage mipmapping ↗, filters, GPU surfaces and path effects
just lab-shaderShader examples and typography
just lab-paintPaints, gradients, brushes and layer effects
just lab-gamutNative wide-SDR gamut ↗ comparison
just lab-colorSwatches and CIE chromaticity/FP16/ICC workspaces
just lab-text / just lab-parleyNative/Parley text, live font-axis sliders, paragraphs and scrolling
just lab-svgSVG rendering, zoom and scheduling
just lab-quad-benchQuad rendering benchmark
just lab-color-field-benchColor-field rendering benchmark

Every lab accepts --help to list its complete command-line options without opening a window. Arguments after the recipe name go directly to the app, including quoted paths. The short names media, shaders, paints, gamut, color, text and svg, and the previous *-lab names, remain aliases with identical options. Canonical launch commands start with lab- so they appear together in just --list.

just lab-media --help
just lab-shader --help
just lab-shader --example composition # Positional `composition` also works.
just lab-media --paths
just lab-media --tiled # Generated 72 MP canvas; pan/zoom/cache pressure, blur/quality
just lab-media --float-images # Supplied RGBA16F pixels; native wide/sRGB comparison
just lab-media --adjustments
just lab-media --image "photos/my image.png"
just lab-media --headless --wgpu --png "target/media preview.png"
just lab-color --chromaticity
just lab-color --help
just lab-text --help
just lab-parley --backend parley --workload paragraph

The text comparison has independent weight, width, slant and optical-size sliders on native and Parley windows. macOS and Windows labs/tests are verified. Run just text --backend both to compare them, just lab-test for the suite, or just lab-test live_axis -- --nocapture for slider interactions. The existing lab-test command enables backtraces automatically. See font controls for capabilities, preview limits and the core 3.0 migration.

Parley uses the same text lab; pass --backend parley for only that engine or leave the default to compare both. Color lab has Swatches/Chromaticity tabs; --chromaticity, --uv, --photo and its ICC flags select the chromaticity workspace. Preset, mapping and alpha controls remain available in the window. It no longer needs the sibling lab. Shader/typography controls also remain available in the window.

Native launch recipes enable runtime-shaders, portable-shaders and wgpu so feature-gated app options are available without changing the Cargo command. Host/GPU restrictions still apply: media's synthetic video option supports macOS Metal (BGRA/NV12), Windows D3D11 (BGRA), and Linux Vulkan DMA-BUF (linear BGRA); native wide output requires a supported backend/display. Select a debug build with just profile=dev lab-media. App arguments are not Cargo arguments. The app-level justfiles remain available for specialized captures and benchmarks.

iOS backend

The iOS source now follows captured upstream 1.27.0 with XGPUI package and shared renderer integration. Its selected downstream version is 1.26.4, with core 3.0.0 and Apple 4.0.0 pins; final public API review and publication remain pending. Simulator compilation is checked; interactive simulator/device validation remains pending. Install Xcode, select its developer directory, and add the simulator target:

rustup target add aarch64-apple-ios-sim
cargo check --locked --features full-capture,runtime-shaders --target aarch64-apple-ios-sim
bash gpui/crates/gpui-ios/examples/ios/build-simulator.sh --locked

The script builds and ad-hoc signs target/gpui-ios-example/GPUIIosExample.app. Launching it requires an installed iOS Simulator runtime. CI checks library, example and native protocol-test compilation; those checks do not establish runtime behavior. The backend currently uses standard color presentation; XGPUI's wide-gamut SDR compositor remains macOS-only.

Windows

Use PowerShell in a Visual Studio Developer terminal with the Windows SDK and MSVC tools available. Select the native MSVC Rust toolchain, such as x86_64-pc-windows-msvc on an x64 machine; the native renderer uses Direct3D 11.

rustc -vV
just build
just lab-shader

The first recipe builds the libraries for Windows. The second builds and opens the shader example application. Commands below also work in PowerShell; they use single lines rather than shell-specific continuation characters.

Windows validation

On 2026-11-04, the project owner confirmed that all native labs and just lab-test passed on Windows using the existing Git/Bash, Rust/Windows build tools and Just setup. This includes the shared BGRA video-surface demo on codex/extension-lab-commands. The Windows testing issue records the original reports and fixes; the successful retest was reported in the development chat. This supersedes blanket descriptions of these labs as Windows-untested or cross-compilation-only.

CoverageEvidence
Native lab applications, including media/video, color/chromaticity, gamut, shaders, canvas, SVG and textUser-confirmed Windows pass, 2026-11-04
Root just lab-test: native lab binary tests and compatibility targetUser-confirmed Windows pass, 2026-11-04; native-window tests remain opt-in
Media video capture and snapshot lifecycle checks selected by lab-testWindows lab-test pass; same-device generated BGRA/D3D11 path
Windows x64 source and lab test compilationCross-check passed from macOS with the installed LLVM resource compiler; a separate compile result
Earlier native paint/gamut backend baseline2026-10-25 CI: Windows D3D11/WARP, Windows wgpu/DX12 and Linux Vulkan jobs passed at ece8ddfb88969e43503a8ab3f37315718383b2ac

lab-test selects lab binary tests and the compatibility target; it is not a claim that every standalone library suite, opt-in desktop test or external producer was exercised. Keep dedicated keyed/shared-handle ownership tests, IME and assistive-technology acceptance, physical display/calibration checks, new backend features and sustained performance measurements separately scoped. Windows NV12, decoder/pool APIs, playback and recovery remain tracked in issue #134. Linux and browser results retain their own host/backend scope.

Linux

Build in a native Linux environment with a working graphical session and Vulkan driver. The root harness enables both Wayland and X11; the corresponding headers and libraries must be available, along with fontconfig, FreeType and xkbcommon. The app uses the wgpu renderer. An SSH shell without a display can build the libraries but cannot open the example window.

just build
just lab-shader

Run inside your normal Wayland or X11 desktop session. Native labs provide a shared title bar and resize frame when the compositor requires client-side decorations (including GNOME Wayland); server-decorated windows retain their normal window-manager chrome. The frame follows the desktop button layout and is omitted for hidden captures and fullscreen windows.

lab-gamut and lab-color attempt wide-gamut SDR presentation and fall back to standard SDR with a visible notice when it is unavailable. The gamut lab keeps its sRGB baseline; the color lab keeps its mapped sRGB swatches and chromaticity workspace. Native P3 content and unsupported wide-gamut controls are disabled. This fallback does not add native wide-gamut presentation to the Linux backend. just lab-gamut --sdr still explicitly selects the standard SDR baseline.

For windowing diagnostics only, env -u WAYLAND_DISPLAY just lab-text selects X11/XWayland when DISPLAY is set. Vulkan rendering is independent of that window-system selection.

Run inside your normal Wayland or X11 desktop session. The repository's Linux Vulkan CI workflow lists the native packages used on Ubuntu if a linker reports a missing system library.

macOS

Use the native Rust toolchain for your machine. The default renderer is Metal; the active Xcode installation must include the Metal compiler.

just build
just lab-shader

If the build fails because the Metal compiler is unavailable, the root harness can embed shader source for compilation at runtime:

just build --features runtime-shaders

Features belong to the selected manifest. For the shader example application, pass the platform dependency's feature explicitly:

cargo run --release --locked --config .cargo/validation.toml --manifest-path apps/xgpui-ext-lab/Cargo.toml --bin shader-examples --features gpui_platform/runtime_shaders --target-dir target

Runtime compilation still needs a functioning Metal-capable system. It avoids the build-time Metal compiler invocation; it does not replace the native SDK.

Without just

The recipes wrap ordinary Cargo commands. If just or Bash is unavailable, build and launch directly (these commands also work in PowerShell):

cargo build --release --locked
cargo run --release --locked --config .cargo/validation.toml --manifest-path apps/xgpui-ext-lab/Cargo.toml --bin shader-examples --target-dir target

Understand the Cargo layout

The root workspace contains xgpui-build, a private harness that builds captured GPUI libraries for the host platform. It does not launch an application or build all extension libraries and labs. The labs share the separate xgpui-ext-lab workspace and lockfile; extensions and repository tools retain their own workspaces. Select a lab with --manifest-path apps/xgpui-ext-lab/Cargo.toml --bin <name>.

The generated root Cargo.toml patches the ten retained framework/backend crate names to local source. Workspace patches apply only inside the root workspace, so the standalone tools under tools/ don't see them. Supporting crates retain their published identities and are not overridden. Standalone commands also pass .cargo/validation.toml for the pinned compatibility overrides used by CI. Run from the root so Cargo discovers the local configuration. Do not copy the command into an unrelated working directory.

Use --target-dir target to share the root output directory across native labs. Without it, standalone workspaces use their own target directories. No personal Cargo configuration or manifest edits are required for these recipes.

Run the media lab

The lab generates its own image samples; no photo or video file is needed.

just lab-media

Compare atlas ↗ and mipmapped images, change filters, zoom and pan. Run just lab-media --adjustments for linear exposure ↗ and vignette ↗ with a shared-source original/adjusted comparison. Open the path effects view with:

just lab-media --paths

Use release mode for visual performance testing. Debug builds are useful for stepping through code, but are not representative of rendering performance. Keep 60 Hz as the baseline; a 120 Hz monitor is optional. Media surface runtime validation on Windows/Linux remains tracked in issue #23. See the media guide for backend limits and measurements.

The tiled lab's blur controls use a bounded sRGB ↗ preview so the capture and halo fit the compositor's 1,024-device-pixel limit. just lab-media --video also offers linear adjustments, vignette and blur on generated native macOS Metal frames; no video file is needed. See the media pipeline guide for resource reuse, output color and backend limits.

Check a change

Build the host framework/backend libraries without launching an app:

just build
just build-full # Also build every retained local library supported on this host.

For faster compile checks and an example extension test:

cargo check --workspace --locked
cargo test --locked --config .cargo/validation.toml --manifest-path extensions/crates/xgpui-color/Cargo.toml --lib

The first command checks the root harness and its dependencies. The second runs the CPU color-math library tests as an example of selecting an extension directly. Choose tests for the crate you changed. A root cargo test only tests the harness; it is not a repository-wide test suite. Native GPU/window tests need the matching platform and, where applicable, a graphical session.

Build harness and test runner

Run these commands from the repository root:

cargo build --locked

The private root harness builds GPUI and the selected platform backend by default. Nine framework/backend crates remain local. Seventeen supporting crates come from the published gpui-unofficial release, currently pinned to =1.27.0. Optional integrations and development-only support are not direct default build inputs. Metal shaders compile at build time by default. The harness launches nothing.

Use the explicit full-capture mode to compile every captured library supported by the selected target:

cargo build --locked --features full-capture
# Equivalent recipe:
just build-full

Full-capture adds every retained local library supported by the selected target, including the WGPU renderer on macOS. Supporting registry crates are compiled when required by those libraries; full-capture no longer directly builds the upstream utility and test tools. Neither mode enables every optional feature or standalone test, benchmark, example, or binary target. Windows and Linux still require their own native checks.

just test runs CI's full native-library and platform-benchmark compilation gates before its runtime suites. The extension suites enable ICC, canvas GPUI integration and media wgpu coverage; Linux additionally checks media without GPU backends and Parley with system fonts. Use just test --only native-libraries or just test --only gpui-bench-build to isolate compilation failures. Hosted Linux extensions/labs, Windows lab applications, and the three platform paint workflows are manual-only (workflow_dispatch). Run them from Actions → the selected workflow → Run workflow when hosted verification is needed. Validate repository tooling is also manual-only, including its tooling checks, macOS/Linux/Windows native-library matrix, iOS compilation and WASM build. PR acceptance is verified in the local test environments; record the tested commit SHA, command and result in the PR.

Local results cover the current host; platform-specific tests still require their native operating system. The release/version preflight checks package versions and pins; its success does not establish that builds or tests passed.

The test runner uses Bash and a small Rust helper built from tools/release-sync; warning capture and artifact indexing require no Python. The helper reuses the release tool's dependencies. Its bootstrap build retains text diagnostics in cargo/bootstrap.stderr.log; subsequent Cargo invocations retain structured JSON.

just test keeps warnings visible and writes a combined report to target/test-logs/warnings.log, with structured records in warnings.jsonl. The summary prints the unique warning count and report paths, including on failed runs. Shared and isolated Cargo invocations retain raw JSON messages and stderr under target/test-logs/cargo/. Set TEST_ALL_LOG_DIR to retain a run elsewhere; the next run replaces the Cargo diagnostics and warning reports in that directory.

Compiler warnings are deduplicated by package, target and complete diagnostic (including source spans), ignoring rendered formatting. Records retain occurrence counts and the contributing build/suite names. Cargo stderr warnings are grouped with their continuation text and deduplicated by that text; they may lack package or source locations. Cargo's compiler-warning count summaries are omitted from the combined count because the individual structured diagnostics already cover them. Raw stderr remains available. Runtime output stays in the suite logs; warning-prefixed stderr from programs launched by Cargo can also appear in the stderr warning report. Warnings do not change the build/test exit status.

The benchmark compilation gate checks that every requested executable was produced and exists; it does not launch benchmarks, including with --help. Forwarded arguments to just test are Cargo options, applied to the shared build and isolated Cargo invocations. They are not forwarded to prebuilt test binaries. The runner owns Cargo's --message-format option for diagnostic capture.

Build options and cleaning

Cleaning build outputs

The repository Cargo configuration shares the root target/ directory across standalone crates too, so root cargo clean removes normal build outputs. Older branches or explicit overrides can still leave nested target directories. Stop active builds, then run just clean-preview to list all of them and just clean to remove them. Without Just, use bash scripts/clean_build_outputs.sh and add --apply to delete. The cleaner skips symlinks and refuses directories containing tracked files or not ignored by Git. It leaves source assets intact. Browser demo bundles live in pages/examples/; remove them with just pages-demos-clean. Build outputs outside this checkout (such as an external CARGO_TARGET_DIR) are not included. Use --target-dir target for standalone builds to share the root output directory, as the lab recipes already do.

Build prerequisites

# Optimized native libraries.
cargo build --release --locked

# Embed shaders for runtime compilation instead of invoking the Metal compiler.
cargo build --locked --features runtime-shaders

# Static checks on the root harness and its dependency graph.
cargo check --workspace --locked
cargo clippy --workspace --locked
cargo fmt --package xgpui-build --check

Root Clippy and formatting checks target the harness; imported libraries are dependencies, not root workspace members. Existing platform/library validation is still run separately by validate.yml.

Compile the captured examples

cargo build --config .cargo/validation.toml \
  --manifest-path gpui/crates/gpui/Cargo.toml \
  --examples --features gpui_platform/font-kit --target-dir target

This builds example executables under target/debug/examples/ without launching them. Add gpui_platform/runtime_shaders to the comma-separated feature list if you need runtime shader compilation. Standalone example builds use their own Cargo.lock; the root lockfile applies to the root harness build.

cargo test at the root tests only the harness. For the imported library's headless tests, follow the integration steps; its dependency override and feature flags remain required. No test or application is launched by cargo build.

Benchmark support

The platform benchmarks require bench-support. Their test targets also need test-support when using cargo check --benches:

cargo check --locked --config .cargo/validation.toml --manifest-path gpui/crates/gpui-platform/Cargo.toml --features bench-support,test-support,runtime_shaders --benches

The core package includes Zed's benchmark metrics source at the captured Zed commit. bench-metrics-provenance.json records that source and the local test adaptation. It is compiled only with bench-support; the Linux perf-event2 dependency is optional and only activated by that feature. The public benchmark measurement and allocator types remain available through gpui.

Benchmark collectors use process-wide tracing and allocation state. Run their unit tests with --test-threads=1 to isolate measurements from other test cases. Native CI compiles all platform benchmarks and runs the metrics and benchmark context tests on Windows, Linux and macOS.

Preview this website

The website is the static pages/ directory. Serve and check it without building anything:

just pages-serve
just pages-check

Both use python3 on macOS/Linux and python on Windows. If Windows only provides the Python launcher, use just python=py pages-serve. Choose another port with just pages-serve 8001, then open localhost:8000. Python is not needed for native app builds.

The browser demos are the only part that needs a build. Install the Wasm target and the CLI version pinned by the build scripts:

rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.129 --locked
just pages-demos
just pages-serve

The build scripts need Bash; on Windows run them in a Bash environment with the same Rust tools on PATH. Rebuild after changing demo code, then reload the page. Use localhost for browser WebGPU access.

Edit this website

The website at https://xgpui.dev/ is the static pages/ directory. Edit an HTML file, refresh the browser. There is no generator, Markdown conversion or content index. The only build step is compiling the two browser demo collections to WebAssembly.

just pages-serve        # serve pages/ at http://localhost:8000
just pages-check        # check links, anchors, assets and legacy routes

pages-check runs scripts/check_pages.py (Python 3, standard library only). It reads the checked-in pages and runs no build. It does not render pages or run the demos.

Layout

Pages work without JavaScript. Scripts only highlight code and forward legacy URLs. Every page carries the same navigation rail; when adding a guide or crate, add it to the rail on every page and to the forwarding lists in index.html. pages-check reports anything missing.

All documentation lives in pages/. docs/ keeps only release records and upstream investigations (docs/release-reviews/, docs/upstream/), which release tooling and audits read. It is not published.

index.html states the upstream source baseline. pages-check fails when it no longer matches upstream.json, so update it after a release sync.

Browser demos

Both entry points belong to apps/xgpui-ext-lab/Cargo.toml. Install the WASM target and the wasm-bindgen CLI pinned in .github/workflows/pages.yml:

rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.129 --locked
just pages-demos        # write bundles into pages/examples/
just pages-serve
just pages-demos-clean  # remove only the generated bundle files

build.sh writes the JavaScript bindings, the .wasm module, build-id.txt and the data files shared with native labs (Italy photos, SVG samples, color reference data and font licenses). These are ignored by Git. The extension gallery compares build-id.txt with the ID compiled into the module and asks for a reload when a browser cached a mismatched pair.

Open http://localhost:8000/examples/extensions/ and http://localhost:8000/examples/shaders/. Use localhost or 127.0.0.1. Wildcard bind addresses such as [::] and 0.0.0.0 are not trustworthy WebGPU origins, so the demo loaders redirect them to localhost.

Rebuild WASM after changing demo code or switching branches. After rendering changes, smoke-test the affected demos with &backend=webgpu and &backend=webgl, and check the console and network panels for errors.

Publishing and the custom domain are covered in Releasing.

Common build problems

SymptomWhat to check
Missing native library or linkerCheck the selected host toolchain, SDK and platform libraries. On Windows use MSVC tools; on Linux check the development package named by the error.
Missing Metal compilerCheck the active Xcode installation, or use the macOS runtime-shader commands above.
Build succeeds but nothing opensThe root harness only builds libraries. Launch an app using its manifest.
Lockfile needs an updateCheck the branch and manifest you selected. For an intentional dependency change, regenerate that workspace's lockfile and review the diff; do not delete all lockfiles.
Patch location does not contain collections or another removed helperRemove stale helper path patches from the consuming app and refresh its lockfile; use the published packages listed above.
Local GPUI changes do not appearRun from the repository root and keep its checked-in Cargo configuration enabled.
Browser demos are absent or staleRun just pages-demos; the pages in pages/ do not include the Wasm bundles.

Linux CI coverage

The Linux extension workflow runs all seven extension suites, native lab tests, Vulkan image/path captures and real window smoke probes under headless Weston and Xvfb/Openbox. Its path filters include all lab and shared app code. Existing paint and native font checks remain independent. Hosted Mesa results may use software rendering and do not establish physical GPU DMA-BUF or desktop input acceptance.

A separate opt-in workflow-dispatch job targets a configured xgpui-vulkan self-hosted runner and runs strict native DMA-BUF/video checks with synchronization validation. See runner setup and local commands.