One month ago, I saw someone's hobby OS and thought: "I want to build one too."
One month later, nefuOS boots from a CD, switches into long mode, draws a browser window in software, compiles C++, installs packages, and answers questions with a local LLM. All of it written from scratch — one dev, one AI, one month.
This post is the tour. I'll skip the "it's a hobby OS" humility and just show you how it's built.
What it is
nefuOS is a full OS stack written from scratch:
- Ncore — custom kernel, boots via both BIOS (El Torito) and UEFI (GRUB multiboot2)
- Nbrower — custom browser with HTML/CSS/JS/WebGL2, own TLS 1.3 stack
- nefucpp — C++ → .nefud compiler
-
NPKG — package manager over HTTPS, installs
.deb-style packages - Nshell — 60+ Unix-like commands
- Ngame — 34 built-in games
- NAI — a fine-tuned Qwen2.5-1.5B that actually calls tools (writes files, runs commands)
- NSAI — a TinyStories-33M model running on bare metal: 24 tokens in ~90 seconds. Painfully slow, very much alive.
- Chinese IME, TTF rendering, 107 built-in apps
The boot chain: from CD to long mode
This is the part most people skip, and it's where the fun hides. The BIOS boot path is a real-mode assembly boot sector that loads the kernel from an El Torito no-emulation CD (2048-byte sectors, DL=0xE0, real ATAPI via int 13h AH=42h).
The loader can only reach about 512KB of contiguous real-mode memory (0x20000–0xA0000, just below the VGA/ROM hole) — but the kernel payload is over a megabyte. So it uses a ping-pong loader:
- Load a 512KB window from the CD into 0x20000.
- Switch to protected mode, let a small stub copy the window to a 0x300000 staging area.
- Return to real mode, reset the window, keep loading.
- On the final chunk, the stub inflates the kernel to 0x100000 and hands off to the long-mode entry point.
Boot sector state lives in a "safe zone" (0x7C00–0x7DAA) because BIOS int 10h/13h clobbers the tail of the sector. Two separate DAPs — one for the boot menu, one for the payload — keep the menu round-trip from corrupting the loader state. A direct-register VBE setup (Bochs registers 0x1CE/0x1CF) gets a true 32bpp linear framebuffer on QEMU, where the BIOS VBE modes would otherwise hand you an unusable 24bpp layout.
The UEFI path is a completely different beast — GRUB multiboot2, flat binary, same kernel.
Nbrower: a browser that actually renders
Nbrower is the crown jewel. It does HTML/CSS/JS rendering, WebGL2, its own TLS 1.3 stack, a Chinese IME, and TTF font rendering — all inside the kernel.
JavaScript runs on a QuickJS integration that lives in the kernel itself. The runtime is shared across <script> blocks (global state persists, like a real browser), with a 16MB memory limit and a 256KB stack cap tuned for bare metal (no per-thread guard pages). Script output and browser control share one protocol: DOM commands like \x01setText|id|value\n get parsed by the browser and re-layout the page.
WebGL is bridged the same way: JS-side GL calls are URL-encoded into control lines (\x01gl<sub>|<cid>|<args>\n) and executed by the host on a hidden WGL context. Behind that bridge sits SWGL — 9000 lines of software GL that run WebGL2 with no GPU driver at all.
The old QuickJS 2021 build had a nasty bug: any second JS_Eval in the same runtime threw a message-less exception. That's fixed now — the kernel runs on quickjs-ng, stable and crash-free on bare metal.
The toolchain: nefucpp & NPKG
- nefucpp is a C++ → .nefud compiler pipeline, so you can build native programs inside the OS.
-
NPKG fetches
.deb-style packages over HTTPS, with the browser's TLS stack doing the heavy lifting.
Nshell, Ngame, and friends
60+ Unix-like commands, 34 built-in games, and 107 built-in apps. The OS is meant to be used, not just booted.
NAI & NSAI: two AIs, two personalities
NAI is a fine-tuned Qwen2.5-1.5B running locally — and it's not just a chat box, it can call tools: write files, run commands. Real agent behavior inside a from-scratch OS.
NSAI is the other one: a TinyStories-33M model that runs directly on the bare-metal kernel. It generates 24 tokens in about 90 seconds. That's not a typo — 24 tokens, 90 seconds. It's brutally slow, and it's the most alive thing in the system: a neural network running on an OS written from scratch, no framework, no GPU, just raw CPU grinding out a story one token at a time.
The workflow: one dev + AI
This was the interesting part. I hand-wrote the first ~120k lines — kernel, VFS, IPC, the core architecture. Then I let AI fill in implementation details, about 80% of the rest.
Architecture, decisions, and debugging are mine. AI just made the typing faster.
- Self-developed: ~300k lines (mostly C/C++, plus Python tooling)
- With third-party: ~1.04M lines
- One month
The hard parts
BIOS + UEFI dual boot. Two completely different boot protocols, one kernel, one codebase. The BIOS path is real-mode assembly with all the segment/offset pain; the UEFI path is multiboot2 with flat addressing. Getting both to land on the same long-mode entry took the longest of anything in the project.
TLS 1.3 from scratch. The browser talks to real sites, which means a real TLS handshake, real record layer, real certificate handling — implemented from the ground up.
QuickJS on bare metal. Getting a JS engine into a kernel means no guard pages, no malloc assumptions, and a runtime that can't blow up your address space. The 2021 build's second-JS_Eval crash forced a migration to quickjs-ng — now it runs all day without a hiccup.
SWGL. 9000 lines of software GL to run WebGL2 without a GPU driver. The canvas pipeline is what makes bloxd.io (a real 3D web game) almost render.
What's next
- bloxd.io WebGL rendering (canvas pipeline is almost there)
- Better CSS support (flexbox, descendant selectors)
- DeepSeek login fully wired into the browser
- Browser input widgets — just finished testing native range sliders across negative ranges, step values, and initial positions
GitHub: https://github.com/Nefu-Dev/nefuOS
Happy to answer questions about the architecture, the AI-assisted workflow, or the dual-backend design.
Top comments (1)
Author here. A few things I couldn't fit in the post:
JS_Evalin the same runtime throws a message-less exception. Had to work around it.Happy to answer anything about the architecture or the AI-assisted workflow.