# Makepad Builder This is the generic app builder/compiler. Scope is catalog data, not a separate installer. Keep the legacy CLI compatible. ## Architecture and validation - Platform dependency installation, network requests, extraction and source checkout belong on the persistent setup worker. The UI only submits bounded commands and receives progress/results. - The Windows ZIP is flat and ships one executable, `makepad-builder.exe`. It hosts `MpTerm` and launches itself in `tui` mode for setup; the internal native CLI target is for development/SDK extraction, not distribution. Start the PTY at the measured widget/font grid size. The setup process owns blocking work, and child shells/agents inherit its ConPTY instead of opening another window. macOS/Linux use the invoking terminal. The TUI follows `makepad-windows-preview.sh` (Windows) and `makepad-mac.sh`: plain terminal colours (dim secondary text, bold selection, green ✓, yellow pending, cyan marker and bar; no panels or boxed dialogs), a header with the email, SETUP in the order people meet them (Account, Graphics, Agreements, Build tools or Rust + Xcode tools/System packages, optional CUDA, Disk, Update), YOUR APPS, MAKEPAD APPS and CODING AGENTS rows with name, license and status columns and the action hint ` ⏎` on the selected row only, one status line and a key-hint footer. App states and actions come from `menu.txt` (download / resume / compile / update / run / merge with agent); the subtitle is `about.txt`. Questions sit on the status line with their options on the next line; progress is one self-rewriting bar there, with detail in `builder.log`. App agents require both compiler and source. Do not show a Project shortcut or a second top menu bar. - Dependency setup progress comes from real installer events. Each component (Build tools, Windows SDK, Rust, CUDA) has one forward-only bar over the byte sizes of all its payloads, known before it starts (manifest sizes, cached files, Content-Length), each counted once downloaded and once unpacked; a line above lists the components that run (✓ done, ● now, ○ next). Never list package or file names on screen; they go to `builder.log`. Keep terminal redraws throttled; never invent an overall byte percentage from package counts. The same events serve the Windows terminal host and SDK extraction CLI. - Run installed agents only after an explicit menu action. Keep compiler output in the log and suppress new Windows consoles for setup/build probes and application launch: children inherit the setup process's pseudo console when it has one and only a console-less parent requests a hidden console. Do not install agents or runtimes implicitly. Preserve the user's PATH after the selected compiler paths so installed tools remain reachable. Project children inherit the selected project directory and no email credential. - GPU driver notice: Linux and Windows setup show the Graphics screen ("Makepad heavily relies on your GPU to draw its UI and implement AI functionality. Old hardware and broken drivers can cause your computer to reboot unexpectedly.", `I understand` selected, Cancel) before any probe, catalog refresh, download or compile until it is read; Cancel/Escape/closed input quit setup. "I understand" is recorded in the install folder (`graphics-notice-read`, temp+rename) and the notice is not shown on later starts; the SETUP Graphics row then shows "✓ driver notice read" and reopens the screen, where Cancel does not un-read it. macOS does not show it. It is a general acknowledgement, separate from vendor license consent (`Setup::consent`). On Windows the terminal host already renders with the GPU before the menu appears; the notice precedes payload downloads and installs, not GPU use itself. - Compiler policy is platform specific. Windows always downloads and uses the Builder-private pinned Rust; it never offers, reads or uses an installed rustc/cargo or the `selected-rust` file. macOS/Linux may reuse the user's installed Rust only when the user explicitly chooses it and it meets the pinned version on this host; the choice (sysroot or `private`) is recorded in `selected-rust`, re-validated on every start and before every build, and never auto-switched. Cargo home, target and temp directories stay in the installation either way. `rust-tools.sh` is the single read-only probe/validator shared by the bootstrap and Builder; it runs the toolchain's own binaries, never installs, and never repairs an external toolchain. - Downloaded Windows ZIPs are portable: keep Rust, Cargo home, sources and build output beside `makepad-builder.json` in the extracted folder. Unpersonalized development/legacy runs fall back to `~/.makepad/loader`; explicit root overrides remain supported. Do not modify global compiler PATH, rustup defaults or system compiler installations. The Builder never edits the user PATH or shell profiles. The terminal and CLI must use the same `runtime::Environment`. - Publish the compiled Windows app beside the loader (for Scope, `scope.exe`). Unix keeps its shell command beside `scope.bin`. Compile with `MAKEPAD_PACKAGE_DIR=.` and write per-executable `makepad-package-paths` from the successful build's Cargo compiler artifacts. Map actual library/binary crate names to source directories relative to the executable; all fonts/icons/crate resources remain in the downloaded repositories. Recompute tool paths on each launch; validate after physically moving the installation and launching from an unrelated directory. - App agents start in the app Cargo workspace with the private build environment and session-only instructions pointing to `agent-context.txt`. The CODING AGENTS Shell row also receives `MAKEPAD_AGENT_CONTEXT`; the Claude/Codex rows inject the startup instruction automatically (Grok reads the context file); rows appear only for agents found on PATH. Shells and agents use the current CUDA selection and clear inherited Rust compiler wrappers/encoded flags. Preserve repository instructions and user authentication/permissions. Never install an agent implicitly or expose the bootstrap credential. `makepad-builder.exe rebuild` / `makepad-builder rebuild` rebuild existing edited sources and refresh the root executable/resource map without fetching a release. - Compiler setup has one consent screen ("› Install build tools": what is installed in this folder, each agreement by name and host with Return opening it in the browser, then "Agree to all" selected and Cancel) covering all required terms (Makepad commercial license, Microsoft tools/SDK and private Rust on Windows); never prompt again between those components. The Agreements screen shows each agreement's state and offers Agree to all / Disagree; `agreements-accepted` records it, consent screens skip what is already accepted, and disagreeing only withdraws the record (nothing installed is removed). The Build tools row is ✓ only when both tools and the selected Rust (private pinned, or the recorded installed Rust on macOS/Linux) are ready. The CUDA compiler is optional on x64 Windows, including releases that do not require it by default. Offer it only with an NVIDIA driver present, behind its own consent screen (NVIDIA CUDA Toolkit); enabled builds use the private toolkit and require CUDA kernels when the app includes that backend. macOS developer tools are checked, not silently installed or licensed. On macOS the "› Apple developer tools" screen offers Apple's installer (`xcode-select --install`, then polls) or runs `sudo xcodebuild -license` on the real terminal, plus Check again and Cancel; it follows the agreements on first run and compiling requires it. Unix dependency readiness uses the same `check-tools.sh` in the bootstrap and Rust frontend. If setup is needed, pause the TUI for Apple or the distro package-manager interaction, then resume it. Never interpret Linux as Apple-ready. macOS uses Metal; the Windows CUDA option is not shown. - Email is the only customer identity and access credential. Downloads are not personalized: `makepad.nl/builder/{macos,linux,windows}` serve the same bootstrap to everyone; the TUI opens with a "› Log in" screen once per folder (empty continues with the open source experiments), saves the email in the folder's `makepad-builder.json` and never asks again; without an email only public experiments show and the menu offers "log in". The user explicitly requested personalized URLs: `/{app}/windows?email=...`, `/{app}/mac?email=...`, `/{app}/linux?email=...`, and `/{app}/git?email=...`. Percent-encode values and never follow credentialed redirects. Keep email out of Git remotes, build environments, logs and source releases. The downloaded bootstrap stores app/email; CLI and environment overrides remain supported. Catalog and legacy API authentication still use `X-Makepad-Email`. This deliberately does not verify ownership of the email address. - Check/build from the main workspace with `cargo check -p makepad-loader`, `cargo build --release -p makepad-loader`, and existing `cargo test --release -p makepad-loader -p makepad-git -p makepad-strict-json`. Verify Windows and native macOS UI using owned standalone `--remote` instances. Do not treat a successful compiler build as proof of the installation flow. ## Shared apps - Makepad experiments (the free apps) is one scrolling list, with selection retained when returning from an app. Keep the selected row visible after keyboard/wheel input and terminal resizes; do not split the list into numbered pages. - Builder opens the downloaded Makepad repository by default. Only an explicit `MAKEPAD_LOADER_PROJECT` overrides that; installer scripts must not set it to the invoking shell's directory. The standalone `scope` command still opens the invoking directory. - `apps.json` lists the public Cargo workspace apps and their binary/required features, with explicit menu placement for the curated list; the shared TUI uses it. Scope alone requires an enabled email. The public catalog projects only the verified public Makepad repository from the matching release and never exposes the Scope pack. - Licensed apps (Scope first) are rows under YOUR APPS. Makepad experiments lists Makepad WM and the registry entries marked `menu: other`; choosing any of them immediately sets up any missing compiler, builds and launches that app, then returns to Builder with the list's selection kept. No app opens a nested checklist. Launching an app uses cached release metadata (a built app just runs), projecting only its public Makepad repository; check for newer sources only through setup/update actions. The active app is recorded in `selected-app` for rebuilds and restored to Scope on return. Sources share `sources//makepad`; verified per-repository receipts allow adding the nested Scope checkout without resetting edited Makepad sources. Stage missing repositories individually and leave unverified existing directories untouched. - Use one `target/` and one selected compiler environment across apps and agents. Shared artifacts need shared source paths: a release builds from its own `sources/` when that exists, otherwise from an existing snapshot whose receipts pin the same commits (receipts match on the commit, not the pack hash), so a public app at the installed Scope's Makepad commit builds from Scope's checkout; only a differing Makepad commit creates a new snapshot, and the activity log says which case applies before anything downloads. Builds and agent shells strip inherited Cargo profile/target/rustflags overrides and pin `RUSTFLAGS`. Installed app metadata lives in `installed/.json`. Publish each executable with its own adjacent `.makepad-package-paths`, retaining the shared map for older runtimes. This keeps previously built apps bound to their matching source resources. - GUI launches return immediately to Builder. Poll child exits without blocking the menu; shell/agent sessions still return when their interactive session ends. On macOS publish a stable `.app` beside the root command/binary, with a real executable, Dock icon and relative resource link. Dock launches reopen the saved project; the terminal command opens its invoking directory. Keep project state outside the app bundle and preserve relocation of the complete installation folder. - Opening Builder starts compiler setup, source download, compilation and Scope launch automatically on every platform. Resolve one release for the sequence and reuse ready dependencies. Required license/install confirmations remain interactive; cancellation and failures return to the menu without advancing or retrying automatically. Updates refreshes licenses and pulls clean sources for installed apps with a newer release; edits in the old snapshot are first saved as `changes/-.diff` and `.files`, the app then offers "merge with agent". Disk shows the folder total and the build data; "clean build" deletes `target/` only, never the apps. Returning from Makepad Apps or a launched app must not restart the startup sequence. - On macOS Builder explicitly opts Scope into foreground activation with the `--focus` argument. Preserve the default activation policy of other apps and remote inspection windows. ## Building the Windows download - `python3 tools/makepad_builder/windows/package.py --out makepad-builder.zip` writes the ZIP (and its `.sha256`) from HEAD; the same commit gives the same bytes. It compiles the Builder for `x86_64-pc-windows-gnu` (a check; the target's standard library must be installed) and ships exactly the source files that build reads. The server keeps it as `windows-x86_64.zip` and serves it as `makepad-builder.zip`. Runtime-check it on Windows before publication (unzip into a new folder, run the .bat); compiler success alone is not runtime proof. - `makepad-builder windows-sdk --root DIR --accept-ms-license` downloads Visual Studio 2022 payloads from Microsoft and uses the same Rust VSIX/MSI/CAB extraction as Windows setup (after explicit installation/license approval). Never copy SDKs from a developer's Windows machine. ## Commercial release service Default endpoint: `https://makepad.nl/api/loader`. The server lives in the makepad/webserver repository. - `GET /catalog`: permitted releases, no quota charge. - `POST /source/{app}/{release}/{repository}.pack`: one self-contained Git pack for the pinned commit. Charge one repository-transfer attempt before streaming; failed/interrupted transfers count. No redirects or query parameters. - `GET /{app}/git?email=...`: latest app repository pack; optional `release` and `repository` pin a catalog entry. Source transfers use the same atomic quota; HEAD and installer downloads do not consume repository quota. - Windows downloads stream a common ZIP plus a small personalized bootstrap suffix using `libs/loader_bundle`. No per-email ZIP is written to server disk. `MAKEPAD_LOADER_RUNNERS` selects the artifact directory, containing `windows-x86_64.zip` (the source ZIP; `builder/makepad-builder.json` is added to it). - macOS and Linux get no compiled Builder: `makepad.sh` is the whole Builder, one POSIX shell script (macOS bash 3.2 and dash; no `case` inside `$( )`, `${var}` before UTF-8 text, no `local`), served as one static file (`curl -fsSL https://makepad.nl/builder/unix | sh`). The outer part writes the Builder (the quoted MAKEPAD_BUILDER here-document) to a temporary file and runs it on the terminal, so it works when piped; keys come from `/dev/tty`. It needs no placeholders: it reads the public catalog and, with `X-Makepad-Email`, the licensed one when it runs (a personalized download may fill in `@EMAIL@`, which only suggests the email). The first run asks the email (empty = public), then the folder (default `~/makepad-commercial`; an empty folder or an earlier Builder folder), then Rust (`private` default, or a compatible installed Rust recorded in `selected-rust`), and copies itself into the folder as `makepad`, which reopens the Builder and also takes `build|run|list|env|agent-context` for coding agents (`AGENTS.md`, `CLAUDE.md` and `agent-context.txt` are written into the folder). Everything else is the Windows TUI's behaviour and folder layout (`makepad-builder.json`, `.login-asked`, `agreements-accepted`, `graphics-notice-read`, `available/`, `installed/`, `sources//.builder-repositories`, `target/sources/