constanos: an experimental x86-64 OS in Rust — SMP, UEFI, Linux syscall ABI, mlibc + BusyBox, its own compositor, and an NVIDIA GA106 driver up to Vulkan via Mesa NVK
Rust
2
479 commits
updated Oct 7, 2026
English · Español
Status: experimental. A personal project, developed by one person with a lot of help from Claude Code. Everything listed below runs today, in QEMU and on one real machine; the gaps are listed under What's missing.
A kernel written from scratch in Rust (no_std, UEFI, SMP) with a Linux-numbered
syscall ABI, mlibc as its libc, BusyBox as its
userland, a desktop with its own compositor, and a driver for an NVIDIA RTX 3050
(GA106) that goes all the way up to Vulkan through Mesa's NVK. It runs in QEMU and
on a physical machine (AM4 / Ryzen 9 5900X) that has no serial port, where
everything — keyboard, mouse, disk — comes in over USB.

The desktop with the Luna 2026 theme: term (BusyBox ash) and cpumon in
windows, a taskbar with buttons for the open windows and the clock. A real QEMU
screenshot with 4 CPUs.
![]() | ![]() |
Start menu (Luna): the applications from /mnt/etc/gui/apps and the theme picker. | The same desktop in modern 9x, switched from the menu (or with F12). |

Glass in the GPU compositor (vk_comp): the taskbar and the menu copy what is
behind them, blur it with a Gaussian blur in a compute shader and draw on top. This
frame comes from the probes/nvk/host-comp.sh harness, which runs the real renderer
on lavapipe and compares it pixel by pixel with the CPU rasterizer.
![]() | ![]() | ![]() |
| DOOM, with mouse and sound. | Quake, a real game with QuakeC. | cmatrix on a port of ncurses. |
bootloader crate), GOP framebuffer, kernel log on serial, in
/proc/dmesg and — on the real machine — in a partition of the USB stick.CLAUDE.md.memfd_create, MAP_SHARED), DMA for drivers.fork with COW, execve of static ELF64 binaries
(static-pie included), clone with real threads, futex, POSIX signals with
sigaltstack and ucontext, job control, wait4, pidfd_open, credentials, CPU
time accounting.SCM_RIGHTS), ptys,
poll/epoll/eventfd./tmp, devfs, procfs (BusyBox's ps
and top read it), and read-write ext2 on /mnt (ATA or the USB stick), with
a block cache and repair at mount time.abi-bits headers are Linux's, so what compiles
against Linux usually runs unchanged.mlibc-port/), with a few upstream bugs patched (one fix
sent upstream: managarm/mlibc#1925).
Unmodified BusyBox 1.36.1: ash is the shell, with ~60 applets (vi, less,
grep, awk, tar, ps, top, wget, nc, ping, httpd...).x86_64-unknown-linux-musl programs run as they
are, tokio included (multi-threaded runtime, timers, sockets, tokio::fs,
processes); tested with loads of 10,000 tasks (scripts/run-tokio-probe.sh).wget, nc and
ping work.gui crate): shared or GPU buffers,
commit, frame callbacks, popups, panel roles. The window manager (move, resize,
maximize, F11 fullscreen, focus) is pure logic with ~90 host tests.compositor: paints on the CPU into /dev/fb0 — works anywhere (QEMU included);vk_comp: composites on the GPU with Vulkan on NVK on the RTX 3050 — rounded-box
SDFs, gradients, borders, shadows, premultiplied transparency and blurred glass.
The same frame is rasterized on the CPU and compared pixel by pixel in the tests.gui::theme): Luna 2026 and modern 9x, switched live from the
start menu or with F12.panel (taskbar and start menu), term (a terminal emulator with
its own VT parser, the vt crate), cpumon (per-CPU graphs, memory, processes),
textdemo (antialiased TrueType text, the text crate), imgview (PNG), snake,
fire, and DOOM and Quake in windows.scripts/gui-e2e.sh drives the desktop in QEMU with keyboard and mouse and checks
the screenshots pixel by pixel.Behind the gpu= boot option (off by default), in steps that are tested one at a
time on the real machine (docs/reference/gpu.md, plan in docs/gpu/gpu-plan.md):
/dev/nvgpu: the interface for a port of Mesa's NVK driver (mesa-port/).
Vulkan works: compute, 3D, a swapchain on the display, buffers and timelines shared
between processes. snake3d (Vulkan, 60 fps) and vk_comp run on it.The Ryzen has no serial port, no PS/2 and no IDE. That is why there are:
/mnt
lives in a partition of the boot stick);scripts/usb-log.sh read reads it from Linux);scripts/metal-run.sh): a job on the stick, a watchdog, the
verdict in the log;seq 1 400: from
875 s down to 0.75 s on metal; docs/fb/console-perf.md);cpumon.doom-port/): the
Freedoom IWAD from /mnt, mouse-look and sound effects through its own AC97 driver.quake-port/): the shareware pak0.pak, a new game with QuakeC and sound.The kernel can't run cargo test, so all the logic that can be written against plain
types lives in separate crates with host tests (hal, mm, vfs, ext2, sched,
usock, tty, net, nvgpu, gui, vt, text, ...). The rest is tested in QEMU:
| What | How |
|---|---|
| Pure crates | cd <crate> && cargo test |
| Kernel in QEMU | scripts/run-kernel-tests.sh |
| Linux ABI (raw C tests) | scripts/run-abi-suite.sh |
| Rust std / tokio | scripts/run-std-probe.sh, scripts/run-tokio-probe.sh |
| Desktop | scripts/gui-e2e.sh [term|wm|text] |
| GPU renderer (lavapipe) | probes/nvk/host-comp.sh |
| Networking | scripts/net-e2e.sh |
A test counts only once it fails when the code it covers is sabotaged; several
subsystems have mutation scripts (scripts/gpu-mutate*.py, nvgpu/mutations/).
kernel/ the kernel (no_std): init, memory, processes, syscalls, fs, drivers,
usb, networking, gpu, cpu/smp, interrupts, time
hal/ mm/ sched/ pure logic with host tests: hardware (xHCI, virtio, APIC, ACPI,
vfs/ ext2/ usock/ GPT...), memory, scheduler, VFS, ext2, AF_UNIX, ptys,
tty/ net/ diag/ networking, lock diagnostics
nvgpu/ the GA106 driver (pure logic) + the /dev/nvgpu uapi
gui/ gui-capi/ protocol, window manager and themes; its C API
draw/ text/ img/ drawing primitives, TrueType text, PNG
vt/ terminal parser
vk-comp/ the GPU compositor (Rust std on musl)
probes/ test programs: NVK/Vulkan, compositor renderer, std, tokio
userspace/ programs in Rust (shell, compositor, panel, term, cpumon...) and C
mlibc-port/ mesa-port/ doom-port/ quake-port/ the ports
mlibc/ busybox/ doomgeneric/ quakegeneric/ upstream submodules
disk-image-root/ contents of /mnt (disk.img)
docs/ per-subsystem reference (docs/reference/) and plans
scripts/ QEMU, tests, deploying to the stick, metal runs
build.rs src/ host side: builds the UEFI image and disk.img, launches QEMU
The per-subsystem reference (docs/reference/) is in English; many of the design
plans elsewhere in docs/ are still in Spanish.
Requirements: Rust nightly (pinned in rust-toolchain.toml),
qemu-system-x86_64, OVMF, clang/llvm/lld, meson, ninja, make,
e2fsprogs, and curl/unzip to download Freedoom and the Quake shareware.
On Arch:
sudo pacman -S qemu-system-x86 qemu-img qemu-ui-gtk edk2-ovmf clang llvm meson ninja lld e2fsprogs
cargo run # builds everything (mlibc, BusyBox, programs, kernel) and boots in QEMU
cargo build # just the UEFI image and disk.img
From the shell, compositor opens the desktop (Ctrl+Alt+Backspace closes it), and
doom, quake, cmatrix, cpumon... run from there or in a window.
scripts/qemu-debug.sh boots QEMU headless for debugging (keyboard, mouse,
screenshots, gdb).
The USB stick has three GPT partitions: boot (FAT, the kernel), constanos-data
(ext2, /mnt) and constanos-log (the log).
scripts/deploy-usb-boot.sh # kernel → boot
scripts/sync-usb-data.sh # disk-image-root/ → constanos-data
scripts/usb-log.sh read # afterwards: the log of that boot
Never dd the whole image onto the stick: it replaces the GPT and takes the other
two partitions with it. Boot options (gpu=, nic=) go in /mnt/etc/kernel.conf.
PT_INTERP; file-backed mmap and mmap
address hints are missing. It comes next after an HTTPS client
(docs/userland/roadmap.md)./dev/nvgpu sessions share page
tables.vk_comp with a software backend instead of two programs
(docs/gui/compositor-visual-plan.md, step 2e); icons.The code in this repository is free software, licensed under your choice of
MIT or Apache 2.0 (MIT OR Apache-2.0, like the
Rust ecosystem). Unless you say otherwise, any contribution you submit is licensed
the same way.
Submodules and third-party files keep their own licenses: mlibc (MIT), BusyBox
(GPLv2), doomgeneric and quakegeneric (GPLv2), ncurses (MIT-X11), cmatrix (GPLv3),
Mesa (MIT) and Freedoom (disk-image-root/freedoom-COPYING.txt). Binaries that link
GPL code (BusyBox, DOOM, Quake, cmatrix) are distributed under the corresponding
GPL.
A personal project to learn how to build an operating system in Rust, with plenty of help from Claude Code along the way.
constanos: an experimental x86-64 OS in Rust — SMP, UEFI, Linux syscall ABI, mlibc + BusyBox, its own compositor, and an NVIDIA GA106 driver up to Vulkan via Mesa NVK
Rust
2
479 commits
updated Oct 7, 2026
English · Español
Status: experimental. A personal project, developed by one person with a lot of help from Claude Code. Everything listed below runs today, in QEMU and on one real machine; the gaps are listed under What's missing.
A kernel written from scratch in Rust (no_std, UEFI, SMP) with a Linux-numbered
syscall ABI, mlibc as its libc, BusyBox as its
userland, a desktop with its own compositor, and a driver for an NVIDIA RTX 3050
(GA106) that goes all the way up to Vulkan through Mesa's NVK. It runs in QEMU and
on a physical machine (AM4 / Ryzen 9 5900X) that has no serial port, where
everything — keyboard, mouse, disk — comes in over USB.

The desktop with the Luna 2026 theme: term (BusyBox ash) and cpumon in
windows, a taskbar with buttons for the open windows and the clock. A real QEMU
screenshot with 4 CPUs.
![]() | ![]() |
Start menu (Luna): the applications from /mnt/etc/gui/apps and the theme picker. | The same desktop in modern 9x, switched from the menu (or with F12). |

Glass in the GPU compositor (vk_comp): the taskbar and the menu copy what is
behind them, blur it with a Gaussian blur in a compute shader and draw on top. This
frame comes from the probes/nvk/host-comp.sh harness, which runs the real renderer
on lavapipe and compares it pixel by pixel with the CPU rasterizer.
![]() | ![]() | ![]() |
| DOOM, with mouse and sound. | Quake, a real game with QuakeC. | cmatrix on a port of ncurses. |
bootloader crate), GOP framebuffer, kernel log on serial, in
/proc/dmesg and — on the real machine — in a partition of the USB stick.CLAUDE.md.memfd_create, MAP_SHARED), DMA for drivers.fork with COW, execve of static ELF64 binaries
(static-pie included), clone with real threads, futex, POSIX signals with
sigaltstack and ucontext, job control, wait4, pidfd_open, credentials, CPU
time accounting.SCM_RIGHTS), ptys,
poll/epoll/eventfd./tmp, devfs, procfs (BusyBox's ps
and top read it), and read-write ext2 on /mnt (ATA or the USB stick), with
a block cache and repair at mount time.abi-bits headers are Linux's, so what compiles
against Linux usually runs unchanged.mlibc-port/), with a few upstream bugs patched (one fix
sent upstream: managarm/mlibc#1925).
Unmodified BusyBox 1.36.1: ash is the shell, with ~60 applets (vi, less,
grep, awk, tar, ps, top, wget, nc, ping, httpd...).x86_64-unknown-linux-musl programs run as they
are, tokio included (multi-threaded runtime, timers, sockets, tokio::fs,
processes); tested with loads of 10,000 tasks (scripts/run-tokio-probe.sh).wget, nc and
ping work.gui crate): shared or GPU buffers,
commit, frame callbacks, popups, panel roles. The window manager (move, resize,
maximize, F11 fullscreen, focus) is pure logic with ~90 host tests.compositor: paints on the CPU into /dev/fb0 — works anywhere (QEMU included);vk_comp: composites on the GPU with Vulkan on NVK on the RTX 3050 — rounded-box
SDFs, gradients, borders, shadows, premultiplied transparency and blurred glass.
The same frame is rasterized on the CPU and compared pixel by pixel in the tests.gui::theme): Luna 2026 and modern 9x, switched live from the
start menu or with F12.panel (taskbar and start menu), term (a terminal emulator with
its own VT parser, the vt crate), cpumon (per-CPU graphs, memory, processes),
textdemo (antialiased TrueType text, the text crate), imgview (PNG), snake,
fire, and DOOM and Quake in windows.scripts/gui-e2e.sh drives the desktop in QEMU with keyboard and mouse and checks
the screenshots pixel by pixel.Behind the gpu= boot option (off by default), in steps that are tested one at a
time on the real machine (docs/reference/gpu.md, plan in docs/gpu/gpu-plan.md):
/dev/nvgpu: the interface for a port of Mesa's NVK driver (mesa-port/).
Vulkan works: compute, 3D, a swapchain on the display, buffers and timelines shared
between processes. snake3d (Vulkan, 60 fps) and vk_comp run on it.The Ryzen has no serial port, no PS/2 and no IDE. That is why there are:
/mnt
lives in a partition of the boot stick);scripts/usb-log.sh read reads it from Linux);scripts/metal-run.sh): a job on the stick, a watchdog, the
verdict in the log;seq 1 400: from
875 s down to 0.75 s on metal; docs/fb/console-perf.md);cpumon.doom-port/): the
Freedoom IWAD from /mnt, mouse-look and sound effects through its own AC97 driver.quake-port/): the shareware pak0.pak, a new game with QuakeC and sound.The kernel can't run cargo test, so all the logic that can be written against plain
types lives in separate crates with host tests (hal, mm, vfs, ext2, sched,
usock, tty, net, nvgpu, gui, vt, text, ...). The rest is tested in QEMU:
| What | How |
|---|---|
| Pure crates | cd <crate> && cargo test |
| Kernel in QEMU | scripts/run-kernel-tests.sh |
| Linux ABI (raw C tests) | scripts/run-abi-suite.sh |
| Rust std / tokio | scripts/run-std-probe.sh, scripts/run-tokio-probe.sh |
| Desktop | scripts/gui-e2e.sh [term|wm|text] |
| GPU renderer (lavapipe) | probes/nvk/host-comp.sh |
| Networking | scripts/net-e2e.sh |
A test counts only once it fails when the code it covers is sabotaged; several
subsystems have mutation scripts (scripts/gpu-mutate*.py, nvgpu/mutations/).
kernel/ the kernel (no_std): init, memory, processes, syscalls, fs, drivers,
usb, networking, gpu, cpu/smp, interrupts, time
hal/ mm/ sched/ pure logic with host tests: hardware (xHCI, virtio, APIC, ACPI,
vfs/ ext2/ usock/ GPT...), memory, scheduler, VFS, ext2, AF_UNIX, ptys,
tty/ net/ diag/ networking, lock diagnostics
nvgpu/ the GA106 driver (pure logic) + the /dev/nvgpu uapi
gui/ gui-capi/ protocol, window manager and themes; its C API
draw/ text/ img/ drawing primitives, TrueType text, PNG
vt/ terminal parser
vk-comp/ the GPU compositor (Rust std on musl)
probes/ test programs: NVK/Vulkan, compositor renderer, std, tokio
userspace/ programs in Rust (shell, compositor, panel, term, cpumon...) and C
mlibc-port/ mesa-port/ doom-port/ quake-port/ the ports
mlibc/ busybox/ doomgeneric/ quakegeneric/ upstream submodules
disk-image-root/ contents of /mnt (disk.img)
docs/ per-subsystem reference (docs/reference/) and plans
scripts/ QEMU, tests, deploying to the stick, metal runs
build.rs src/ host side: builds the UEFI image and disk.img, launches QEMU
The per-subsystem reference (docs/reference/) is in English; many of the design
plans elsewhere in docs/ are still in Spanish.
Requirements: Rust nightly (pinned in rust-toolchain.toml),
qemu-system-x86_64, OVMF, clang/llvm/lld, meson, ninja, make,
e2fsprogs, and curl/unzip to download Freedoom and the Quake shareware.
On Arch:
sudo pacman -S qemu-system-x86 qemu-img qemu-ui-gtk edk2-ovmf clang llvm meson ninja lld e2fsprogs
cargo run # builds everything (mlibc, BusyBox, programs, kernel) and boots in QEMU
cargo build # just the UEFI image and disk.img
From the shell, compositor opens the desktop (Ctrl+Alt+Backspace closes it), and
doom, quake, cmatrix, cpumon... run from there or in a window.
scripts/qemu-debug.sh boots QEMU headless for debugging (keyboard, mouse,
screenshots, gdb).
The USB stick has three GPT partitions: boot (FAT, the kernel), constanos-data
(ext2, /mnt) and constanos-log (the log).
scripts/deploy-usb-boot.sh # kernel → boot
scripts/sync-usb-data.sh # disk-image-root/ → constanos-data
scripts/usb-log.sh read # afterwards: the log of that boot
Never dd the whole image onto the stick: it replaces the GPT and takes the other
two partitions with it. Boot options (gpu=, nic=) go in /mnt/etc/kernel.conf.
PT_INTERP; file-backed mmap and mmap
address hints are missing. It comes next after an HTTPS client
(docs/userland/roadmap.md)./dev/nvgpu sessions share page
tables.vk_comp with a software backend instead of two programs
(docs/gui/compositor-visual-plan.md, step 2e); icons.The code in this repository is free software, licensed under your choice of
MIT or Apache 2.0 (MIT OR Apache-2.0, like the
Rust ecosystem). Unless you say otherwise, any contribution you submit is licensed
the same way.
Submodules and third-party files keep their own licenses: mlibc (MIT), BusyBox
(GPLv2), doomgeneric and quakegeneric (GPLv2), ncurses (MIT-X11), cmatrix (GPLv3),
Mesa (MIT) and Freedoom (disk-image-root/freedoom-COPYING.txt). Binaries that link
GPL code (BusyBox, DOOM, Quake, cmatrix) are distributed under the corresponding
GPL.
A personal project to learn how to build an operating system in Rust, with plenty of help from Claude Code along the way.