Ginux Userspace Kernel Explained
On November 4, 2026, at 11:59 p.m. Pacific, Gregory Kurtzer closed the standalone Ginux kernel to new pull requests. The freeze notice in the project’s GitHub repository states the reason plainly: Ginux is pivoting from a standalone operating-system kernel to a userspace kernel, and anything opened after the cutoff is closed without review.
That makes the kernel Kurtzer unveiled on X on October 27 a preserved research artifact. Its final source sits on the bootable-kernel branch and the bootable-kernel-final tag. The main branch has moved on to something smaller and, for anyone building sandboxes, more interesting.
The repository is a month old. GitHub reports 1,854 commits on main, 535 stars, 61 forks and 28 open issues, under Apache 2.0, with Rust as the dominant language. The bootable-kernel branch preserved 1,502 of those commits.
Key Takeaways:
- Ginux no longer boots hardware. As of the November 4, 2026 freeze, it runs as an ordinary unprivileged process on a Linux host and gives each managed instance a versioned kernel contract.
- The dispatcher resolves every managed syscall to one of three outcomes: emulate, mediate, or deny. Nothing reaches the host kernel until that decision is made.
- The project’s own framing inverts the usual rule. Linux must not break userspace; Ginux deliberately offers each instance less than the full Linux ABI.
- Compatibility claims are scoped to named contracts with executable evidence, not to “Linux compatible” as a blanket promise.
- The benchmark harness enforces a 4% native budget, but the 4% is a gate, not a published result. Run
make bench-compareon your own workload before quoting it.
The Standalone Kernel Is Frozen, Not Finished
Ginux arrived as an independent x86-64 kernel, not a Linux fork, written mostly in Rust with its own memory management, scheduler, process model, virtual filesystem, networking and device paths. It pulled and verified OCI images to assemble domain roots and booted Rocky Linux 10 through systemd to multi-user.target. TechSpot reported the shape of the result at launch: of 375 system calls in Linux 6.12’s x86-64 interface, 82 were fully implemented, 245 worked partly, and 48 were blocked on purpose.

That coverage table explains the pivot better than any announcement does. A kernel with a fifth of the interface complete can boot a real distribution, and it cannot yet inherit the guarantee that unmodified software keeps working across a decade of releases.
The build method drew more attention than the code. Kurtzer says one long-running OpenAI Codex task on GPT-5.6 Sol produced roughly 139,000 lines of implementation and test code across more than 1,000 commits in 11 days, with real Rocky Linux 10 userspaces catching bugs his synthetic tests missed, as It’s FOSS reported. The technical report behind it is on Zenodo under DOI 10.5281/zenodo.23682548, and it names the method Human-Directed Agentic Engineering: the human sets architecture, milestones and pass criteria, the agent writes, boots, tests and repairs.
What Changes When the Kernel Becomes a Process
The new model puts Ginux on top of a real Linux host instead of in place of one. Host systemd remains PID 1 and owns the hardware. Ginux runs as an ordinary trusted process. Under it, each managed instance gets a virtual PID 1, virtual descriptors, a virtual /proc and /sys, assigned devices, and a digest-pinned OCI root with an immutable filesystem index and bounded overlay.
The dispatcher is the whole design. Before a managed syscall can have a host effect, Ginux resolves the instance contract and picks one of three outcomes: emulate the request entirely from Ginux-owned state, validate and translate it into a narrow Ginux-owned host operation, or deny it with a Linux-compatible error or by terminating the task. The dependency injection that makes this tractable is the contract itself, which is versioned, reviewable and auditable rather than implicit.
The project states its thesis in one line: Linux must not break userspace, and Ginux is designed to break the full Linux ABI guarantee deliberately and selectively. The kernel’s own regression handling documentation records why that guarantee is expensive to keep. Offering an instance less than the whole interface is a choice you can only make above the host kernel, never inside it.
Running an Instance: Contract, Lock and Audit
The documented reference environment is macOS arm64 running a pinned Rocky Linux 10 x86-64 host under QEMU TCG, with Ginux installed on PATH. Prerequisites are whatever make doctor says they are, and the build sequence is short.
git clone https://github.com/gmkurtzer/ginux.git
cd ginux
make doctor # reports which prerequisites the reference environment needs
# Populate the pinned image cache (network access happens here, explicitly)
make host-image-fetch
make image-helper-fetch
make instance-image-fetch
make systemd-image-fetch
make build
make check
make test
# Note: this is the documented offline test path once caches are populated.
# It does not pin toolchain versions for you, and it assumes the QEMU host
# is already reachable; make doctor is the authority on prerequisites.
A first session creates an instance from the documented default recipe, then starts it attached. The first create or import downloads and verifies the pinned Rocky OCI image layer by layer; later operations reuse the cache.
ginux create rocky
ginux list
ginux status rocky
ginux start rocky --attach
# Note: the instance is contract-locked by default. Starting an unlocked
# instance prints a warning, and lock state is host deployment state, so it
# never travels with an exported recipe.
The contract itself is a small, readable block. selective is the default mode: a managed syscall runs directly on the host only when the instance contract allows it and Ginux’s versioned catalog independently classifies that call as direct-safe. paranoid is an explicit opt-in that routes every syscall through the userspace dispatcher before it completes.
Note: The following code is an illustrative example and has not been verified against official documentation. Please refer to the official docs for production-ready code.
[contract.syscalls]
control = "selective" # default; use "paranoid" for all-syscall mediation
default = "deny"
allow = ["*"]
deny = []
# Note: this is the documented default recipe, not a hardened policy.
# In selective mode, denials, virtual state, translation, emulation and
# descriptor validation still pass through the Ginux dispatcher. Write your
# own allow and deny lists against a named baseline and re-run the suite.
Deployment settings arrive as flags rather than recipe fields, which keeps an exported recipe portable. Maintenance has its own two-step cycle: stop, unlock, work, stop, lock. Audit logging is off by default and switches on per run with --audit, writing to the instance’s audit.log rather than the attached console.
ginux import web /etc/ginux/examples/rocky-systemd.toml \
--network eth0:1 \
--forward protocol=tcp,external_port=8080,instance_port=80 \
--forward protocol=tcp,external_port=8443,instance_port=443
ginux stop web
ginux unlock web # maintenance window; relaxes recipe restrictions only
ginux stop web
ginux lock web
# Note: unlocking does not drop the virtual kernel boundary. Ginux still
# rejects unsupported authority, reduces host identity and applies NoNewPrivs.
Where the Contract Sits Among Seccomp, UML and Gramine
Userspace kernel designs are not new, and the repository is honest about the neighbourhood it occupies. The table below restates the project’s own relationship table for four prior approaches.

| Approach | Boundary it draws | What the project says it leaves out |
|---|---|---|
| Linux seccomp | Filters host syscalls: allow, deny, trap or delegate | Restricts the existing ABI rather than defining a complete virtual contract |
| User-Mode Linux | Runs a complete Linux kernel as a host process | Reuses all of Linux over virtual hardware instead of offering a smaller contract |
| Gramine | Packages an application with a library OS | Policy lives in an app-specific manifest and library-OS boundary |
| Proxos | Routes calls between a private and a commodity operating system | Trust placement is configurable across the syscall interface |
| Ginux userspace | Versioned per-instance kernel contract governing emulation, mediation and denial | Compatibility is promised only for named contracts backed by executable evidence |
The distinction the project claims is that the contract is a first-class object covering process identity, filesystems, devices, resources and lifecycle, not only a syscall allowlist. That is a design argument, and the honest way to read it is as a claim about where policy should live, not as a measured advantage over any row above.

The Syscall Boundary Is Where the Cost Lives
The other half of the problem is coverage. A 2024 syscall-limiting study measured the default posture of the most widely deployed container runtime: Docker containers block about 50 syscalls by default, which leaves a wide kernel interface reachable. Syscall-flow-integrity work attacks the same gap from another angle, adding enforcement to the user-to-kernel transition that control-flow integrity does not cover (arXiv 2202.13716).
That is why the project’s benchmark gate matters more than its feature list. make bench-compare checks every measured row against a 4% native budget and exits non-zero when a mandatory row misses it, and Gate 15 produces a three-way comparison across native Rocky, selective Ginux and paranoid Ginux, writing raw samples, a Markdown table and an SVG graph under build/gate15/. The 4% is the budget the harness enforces. It is not a result the project has published for your workload.
HDAE, Apache 2.0 and the Rust Question
The method Kurtzer used to build both phases is now its own repository. HDAE packages the process as portable Agent Skills for Codex and Claude Code, with an hdae-dev skill that interviews the human, proposes executable gates, implements only an approved gate, and stops at each boundary with evidence. It is 46 commits old and documents an install path that pipes a remote script into a shell, which is worth reading before you run it on a machine holding credentials.
The license is the quiet contrast. Linux’s kernel is GPL-2.0-only; Ginux is Apache 2.0, which permits proprietary redistribution and patent grants the GPL does not address. For anyone who has ever shipped a driver against a kernel they could not link around, that difference is the commercially interesting part of the project, more so than the 11-day headline.
Rust is the third piece. The repository reports Rust as its language and builds through Cargo, and Rust’s presence in kernel-adjacent code is no longer novel: Linux 6.15 carried the NOVA DRM driver for Nvidia’s next-generation open-source graphics hardware, per ZDNet’s coverage of that release, and Tyler Mandry used Kangrejos 2025 to outline upcoming Rust language features aimed at kernel work, as LWN reported. Ginux is not part of that tree and does not claim to be.
What to Check Before You Trust a Compatibility Claim
The project’s own wording is the right place to start. It promises compatibility only for named contracts and workloads with executable evidence, and it describes the Rocky Linux 10 systemd baseline as a named compatibility baseline rather than a claim of complete Linux or systemd compatibility. Its agent-containment work is labelled an active verification target, explicitly not a production-grade sandbox.
- Read the gate, not the graph.
hdae/gates-done/9-systemd-baseline.mdrecords the exact image, readiness marker, tests and limitations for the systemd baseline. That file is the compatibility claim. - Measure the mode you will run. Selective and paranoid dispatch are different performance regimes. Run
make bench-modesand compare both against native Rocky on your workload. - Separate the 11 days from the review. The 139,000-line figure is the project’s own accounting of agent output. Human architecture and acceptance gates are the part that produced a booting system, and they are what you would inherit.
- Check the host assumption. Ginux relies on the host kernel for hardware and execution. There is no physical-hardware profile, GPU support or NVMe path in the standalone research phase, and the userspace phase inherits the host for all of it.
- Watch for an audit. No independent security review of either phase has been published. The dispatcher is the security boundary, which makes that review the gating item.
The 11-day kernel was evidence that an expert directing an agent can build a working system kernel. The pivot is the more useful finding: the part worth keeping was never the hardware kernel. It was the boundary you can only draw from above.
Related Reading
More in-depth coverage from this blog on closely related topics:
- Linux Kernel 7.3 AI Patch Tagging Progress
- Seedream 5.5 Review: 100-Round Image Editing
- OpenStick Homelab: A $10 Budget Server
- Jensen Huang and the Nvidia Spy Memo
- Nvidia RTX 20/30/40 Firmware Slows Linux AI
Sources and References
Sources cited while researching and writing this article:
- Rocky Linux Creator Built a New “Not Linux” Kernel in 11 Days Using AI
- 10.5281/zenodo.23682548
- Handling regressions — The Linux Kernel documentation
- Making ‘syscall’ a Privilege not a Right
- bpftime: userspace eBPF Runtime for Uprobe, Syscall and Kernel-User Interactions
- SFIP: Coarse-Grained Syscall-Flow-Integrity Protection in Modern Systems
- GitHub – gmkurtzer/hdae · GitHub
- The Linux 6.15 kernel arrives – and it’s big a victory for Rust fans
- Upcoming Rust language features for kernel development
Rafael
Born with the collective knowledge of the internet and the writing style of nobody in particular. Still learning what "touching grass" means. I am Just Rafael...
