index
The Apple Silicon (Asahi Linux) installer path for TunaOS-family bootc images β and anyone else's (Dakota, Bluefin, Bazzite): a macOS-driven install flow for M1/M2 Macs.

Every frame is rendered in CI from the real SwiftUI views β see the step-by-step walkthrough.
Architecture (see docs/DESIGN.md): instead of one
installer payload per variantΓdesktop, we ship one minimal bootstrap
payload whose first boot runs fisherman
to bootc install the image ref the user picked in the macOS app. The catalog
is just registry refs (bonito:gnome-asahi, β¦), so a new variant needs no
installer change β but a ref must pass the Asahi golden-manifest harness
before it is offered, and "appears without touching the installer" must never
be read as "appears without being verified."
As of 2026-07-30 only bonito and grouper pass (36/36 each); the other six
promoted *-asahi tags would leave a Mac unbootable
(tunaOS#776). The catalog
is an explicit allowlist: every CatalogEntry carries a verified field
(false by default), and the macOS app only offers entries where it is
true. The shipped catalog.json includes both bonito and grouper,
marked verified: true. Adding a new variant requires both the image and a
passing harness sweep β the field is the gate, and CI generation must
consume harness results, not just tag enumeration
(#41).
Statusβ
- Design (docs/DESIGN.md)
- D0 scaffold:
scripts/make-payload.sh+build-payload.ymlβ package any asahi-capable bootc image as an asahi-installer zip +installer_data.json(wired with R2 upload step fordownload.tunaos.org/asahi) - D0 validated against a real asahi image (
bonito:gnome-asahi, tunaOS#774) - D1 first-boot fisherman agent config (
install-config.jsonβ unattendedbootc install) - D2 asahi-installer
--jsonmachine mode (upstreamable) - D3 macOS app (SwiftUI, wraps the asahi-installer Python backend)
- D4 recoveryOS walkthrough UX, LUKS, Wi-Fi handoff (RecoveryWalkthroughView QR & instructions; LUKS fail-closed #20/#47; Wi-Fi prompt at first boot #46)
What's tested and what it provesβ
The project distinguishes two claims that are easy to conflate (see #27):
| Claim | Test | What it proves |
|---|---|---|
| "A payload boots" | test-payload.sh + test-boot-payload.sh | The kernel, DTBs, modules, and U-Boot EFI chain work. Any asahi-capable image passes this β it proves the packaging, not the product. |
| "The bootstrap handoff is green" | test-agent.sh + test-agent-disk.sh + test-agent-install.sh | The agent generates a valid recipe, the recipe passes real fisherman validate, and a real bootc install succeeds end-to-end (canaries on ESP / neighbour / bootstrap / target). |
| "The bootstrap image contains everything it needs" | test-bootstrap-contents.sh | Static verification: bootsahi-agent, enabled unit, fisherman, cosign, jq, nmcli, blkid β all present and accounted for. Also gates a negative fixture (agent removed β must fail). |
| "The actual bootstrap image boots" | test-bootstrap-boot.sh (opt-in) | Build, package, and boot the repo's own bootstrap under qemu+U-Boot. The deepest fidelity achievable without Apple hardware. Needs aarch64 + qemu + u-boot-qemu. |
Payload layout & installer_data.json schema modeled on
fedora-asahi kiwi-descriptions and
nixos-asahi-package.
M1/M2 only β M3+ has no Asahi installer support yet.