← All lessons

A System That Can Reproduce Itself Is a Different Kind of System

The Umbilical Cord You Stop Noticing

For most of its modern life, uBixOS was built the way almost everything is built: on a host machine. My Mac ran a cross-compiler, produced a disk image, and QEMU booted it. That workflow is so normal you stop seeing it. The OS ran, the desktop came up, apps launched — it felt like a complete, self-standing system.

It wasn’t. It was a system with an umbilical cord. Every binary it ran was manufactured somewhere else, by a toolchain that would never itself run on uBixOS. Unplug the host and the OS couldn’t produce a single new program. It could execute, but it couldn’t reproduce. And a thing that can’t reproduce itself isn’t really standing on its own — it’s a very convincing output of the machine that actually is.

I decided the real milestone wasn’t another driver or another app. It was cutting the cord.

What Cutting the Cord Actually Took

“Self-hosting” is a short word for a long chain of dependencies that all have to be satisfied at once, on the target, with nothing borrowed from the host. To compile a single C file on-device, uBixOS needed:

  • A compiler and linker that run on uBixOS. I ported LLVM — Clang and lld — plus a freestanding libc++/libc++abi/libunwind, and made clang/lld the default toolchain for both architectures. Not cross-clang on the Mac. Clang running under uBixOS, emitting uBixOS binaries.
  • A build tool. I ported bmake, first cross-built, then built and run inside the OS itself, with SRCTOP walk-up so a build launched from a subdirectory can still find the root of the tree.
  • A shell for the build to drive. A port of oksh as /bin/sh, which meant fixing musl’s vfork ABI and the exec bit along the way, because a Makefile that can’t spawn a shell can’t run a recipe.
  • The coreutils a recipe assumes exist. Twenty-plus busybox tools — sed, awk, printf, diff, install — because a build system without sed isn’t going to build anything.

The moment it all lined up, bin/cat compiled and ran on-device: clang and lld, running under uBixOS, driven by bmake, invoked from a uBixOS shell, producing a working uBixOS binary. No Mac in the loop. That one small program is the whole point — it’s the first thing uBixOS ever made entirely by itself.

The Bugs Living in the Gap

The most telling part: closing the loop surfaced a run of bugs that had been there all along, invisible precisely because the host had been covering for them. A non-deterministic syscall argument layout from unpinned PADL_/PADR_ endianness. A getrlimit/setrlimit syscall number colliding with sigprocmask. A SIGSEGV after a copy-on-write fork that came down to execve failing to reset caught signal handlers to SIG_DFL.

None of these mattered when the toolchain lived on the host, because the host never exercised those paths hard enough to hit them. The act of making the system self-sufficient is what forced every one of its own primitives to actually work under load. Self-hosting isn’t just a capability — it’s the most thorough integration test a system can run on itself.

The General Principle

There’s a category difference between a system that produces outputs and a system that can produce itself. The second kind has no external point of failure you’re quietly depending on — no host, no golden image, no one machine that, if it disappeared, would take your ability to make progress with it.

This shows up everywhere the moment you go looking for the umbilical cord:

  • A deployment that only works from one engineer’s laptop, with their exact tool versions, is that laptop’s output. It becomes a real system the day CI can reproduce it from a clean checkout.
  • An infrastructure setup with no path to rebuild itself from source — just a running server nobody dares reboot — is a fossil, not a system. It exists at the mercy of the box it happens to be on.
  • A dataset or model you can’t regenerate from a committed, runnable pipeline is a lucky artifact. If you can’t reproduce it, you don’t really own it; you’re just holding it.

The question worth asking of anything you’ve built is: if the machine that made this vanished, could the thing remake itself? If the answer is no, you don’t have a self-standing system — you have an output, and a hidden dependency on whatever produced it. Closing that loop rarely adds a feature a user will notice. What it adds is independence, and the brutal, valuable side effect of forcing every primitive the system relies on to prove it actually works.

uBixOS didn’t become a real operating system the day it booted. It became one the day it could build the next version of itself without asking my Mac for help.

← All lessons