---
This page documents how the FlashOS source was ported from Zig to
[Flash](https://github.com/ajhahnde/Flash) — a self-hosted systems
language that transpiles to Zig. The OS-image modules now carry the
`.flash` extension; `flashc` lowers them to Zig at build time, which Zig
then compiles as before. The port preserved behaviour, not just source:
the boot contract's per-board free-page checkpoints held unchanged from
the first ported module to the last.
> **Lineage.** FlashOS began as a C bare-metal kernel by Wei-Lin Chang
> (rhythm16; see [License](LICENSE.md)), was rewritten in pure Zig +
> AArch64 assembly, and now carries its OS-image code in Flash. This page
> covers the Zig → Flash step: the *OS-image* modules moved to Flash while
> the boot assembly, the host build tooling, and a small, documented set of
> modules stay Zig (see [§4](#4-what-stays-zig)).
## Contents
1. [Flash, and why](#1-flash-and-why)
2. [The toolchain pin](#2-the-toolchain-pin)
3. [What moved to Flash](#3-what-moved-to-flash)
4. [What stays Zig](#4-what-stays-zig)
5. [How the build transpiles](#5-how-the-build-transpiles)
6. [Validation](#6-validation)
End state of the port:
- Every portable OS-image module — kernel core, board drivers, user
space, and the in-kernel test harness — is written in Flash.
- The `.flash` file is the single source of truth; the Zig it lowers to
lives only in the build cache and is never committed.
- The kernel image is behaviourally identical to the pre-port Zig build:
both boot watchdogs assert the same 28-scenario / 32-checkpoint
contract and the same free-page checkpoints, on both boards, with no
re-capture across the entire port.
## 1. Flash, and why
[Flash](https://github.com/ajhahnde/Flash) is a systems language whose
compiler, `flashc`, emits Zig. A `.flash` module is lowered to a `.zig`
module at build time and then compiled by the ordinary Zig toolchain, so
Flash inherits Zig's backend, `comptime`, and `extern struct` ABI while
presenting its own surface syntax.
Because `flashc` lowers to the same Zig the project already compiled, the
port could proceed module by module against a live oracle: each `.flash`
module had to transpile to Zig that was behaviourally identical to the
`.zig` it replaced before the original was removed. The boot contract —
the free-page checkpoints the QEMU watchdog asserts — was the
byte-level witness that nothing drifted.
## 2. The toolchain pin
`flash-toolchain.lock` (repository root) pins the exact `flashc`
revision the tree is transpiled with — a version and a commit. Pinning
keeps the transpile reproducible: port progress never depends on a moving
compiler, and a clean checkout always lowers the same Flash to the same
Zig.
The build resolves the compiler binary through the `-Dflashc=