k23 puts WebAssembly inside the kernel instead of on top of it
Experimental WASM Microkernel Operating System
At a glance
- What is it?
- k23 is an experimental microkernel operating system written in Rust that treats WebAssembly as its primary execution environment. Its roadmap shows a finished bootloader phase with RISC-V support and KASLR, a mostly complete WebAssembly phase, and drivers, the component model and Kotlin support still to come.
- Who is it for?
- k23 earns attention from OS researchers, language runtime authors and anyone building sandboxed extensions, because it treats WebAssembly as a kernel-level execution environment with guest memory management, guest ASLR, trap handling and kernel integrity rather than as an application payload. It is the wrong tool for shipping anything: the driver phase has not started, the component model and Kotlin support are unchecked boxes, and there is no application ecosystem to borrow.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
WebAssembly is the kernel's execution environment, not a guest payload
k23 is described as an active research project exploring a more secure, modular and easy to develop for operating system by using WebAssembly as the primary execution environment. That last phrase is the whole design, and it separates k23 from the more common arrangement where a WebAssembly runtime runs as a program inside an existing operating system.
In that arrangement the host kernel still owns memory, threads and processes, and the WebAssembly sandbox is enforced by the runtime sitting on top of it. k23 inverts the layering. The kernel itself exposes WebAssembly semantics: guest memory management, guest address space layout randomization, trap handling, module imports and exports, and execution of WASM in userspace. The isolation model is the kernel's job rather than a runtime library's.
The consequences run both ways. In exchange, a guest gets memory isolation and randomization from the kernel, with cryptographic kernel integrity and KASLR in the same phase of the work. In return, you give up the ordinary POSIX surface, and you inherit the hard problem of talking to real hardware, which is the phase that has not started.
The audience is narrow and stated in the project's own terms: people who want to hack on a kernel, fork it for experiments, or think about better computer systems. The manual lives at jonaskruckenberg.github.io/k23 and the community is a Discord.
Phase 0 is finished: bootloader, RISC-V, kernel integrity and KASLR
The roadmap is a checklist, and the first block of it is entirely ticked. Phase 0, bringup, lists a bootloader stage, RISC-V support, cryptographic kernel integrity, compressed kernel support, a test runner that tests against the WebAssembly specification, kernel backtraces, proper error handling and KASLR, the kernel address space layout randomization.
Three items in that list matter more than the rest for anyone judging the project. Cryptographic kernel integrity means the kernel verifies itself rather than trusting whatever is in memory at boot. KASLR moves the kernel's own address layout, so an attacker cannot rely on fixed kernel addresses. And the test runner testing against the WebAssembly specification is what keeps a from-scratch implementation honest, since a kernel that boots is not the same as a kernel that implements the spec correctly.
Backtraces and proper error handling being on the same list tells you something about the stage of the project. A kernel that can report where it failed is a kernel you can debug, and a research OS that produces only panics is not much fun to work in.
RISC-V is the only architecture named in the roadmap, which is a reasonable constraint for a bringup phase and also the main portability limit today.
Phase 1 has WASM running in userspace, with the proposals still pending
Phase 1 covers the basic WebAssembly features, and most of them are marked done: guest memory management, guest ASLR, executing WASM, handling guest traps and fault recovery, WASM module imports and exports, executing WASM in userspace, support for WASM builtins, and handling WASM traps.
The word userspace in that list is the interesting one. A microkernel that can only run WebAssembly is not yet an operating system with an operating system inside it; the kernel is the trusted layer and the WebAssembly code runs with less privilege than the kernel, but the kernel still needs to own the machine.
What is not ticked in Phase 1 is the short list of things a modern runtime expects. Syscall context switching and basic host functions are open, which means a guest cannot yet make host calls in the normal way. Then come the specification proposals: extended constant expressions, multi-value, tail call, reference types, fixed-width SIMD, relaxed SIMD and multiple memories. Every one of those unchecked boxes is a real constraint for a language runtime that compiles to WebAssembly, because a compiler that emits reference types or multi-value returns will not run as-is.
That pending list is the honest measure of how far along the WebAssembly story is, and it is the first thing to check against your own guest's requirements.
Buck2 drives the build, a justfile wraps it and QEMU runs the result
The repository is unusual in a good way: it carries a .buckconfig, a BUCK file, reindeer.toml, a Nix flake, a justfile, fuzz directories and a manual directory, all at once. Buck2 is the build system, and the justfile wraps it in recipes with a stable interface.
The recipes look like this, with the Buck2 invocation left in template form:
build target *buck2_args="":
{{ _buck2 }} build {{ target }} {{ _platform_args }} {{ buck2_args }}and running a target passes extra arguments through to QEMU:
run target buck2_args="" *qemu_args="":
{{ _buck2 }} run {{ target }} {{ _platform_args }} {{ buck2_args }} {{ qemu_args }}The default recipe only lists the available recipes, which is the fastest way to see the surface:
@just --listThe platform handling is worth noting because it is what keeps a mixed-target tree buildable. The file drops riscv-only and host-only targets that do not match the active platform instead of erroring out, and a --target-platforms flag can narrow the set further.
The check recipe is where the project's discipline shows. It renders diagnostics as JSON, filters for entries whose level is error, and fails on any match, with a comment explaining that the prelude's diagnostics action is infallible by design and the rendered output has to be gated manually. The preflight recipe runs the checks CI runs, ordered cheapest first so an obvious failure does not wait behind QEMU. Along the way the justfile also requires cargo-deny for dependency policy and typos for spell checking.
Drivers, the component model and Kotlin are all still boxes to tick
Phase 2 covers concurrency, and here the split is interesting: kernel concurrency and a scheduler are done, while the threads proposal, atomics, and shared-everything threads are not. A kernel that schedules WASM jobs can run concurrency without giving guests shared memory, which is a defensible position for a sandboxing-first design, but it also means guest code that expects shared memory has to be restructured.
Phase 2.5 is named Kotlin on k23, and its two items are the WebAssembly garbage collection and exception handling proposals. That naming is a statement of intent: the goal is not only to run C and Rust compiled to WebAssembly, but to host a managed language runtime, which needs a collector and a way to propagate exceptions through WebAssembly frames.
Phase 3 is drivers, and it is where the hardware problem lands. Supporting MMIO regions depends on either the WebAssembly Memory Control proposal or typed multiple memories, and the same phase lists the component model and component linking. Until that phase moves, the kernel has no story for talking to devices.
Read together, the roadmap is coherent: a microkernel with a strong sandbox model first, then drivers, then a component model on top so that independently compiled components can be composed. It is a research sequence, and the parts you would need for a real system are the parts furthest from done.
Weekly nightlies, a dual licence and a small research community
The release list shows three nightly tags in October alone, on 2026-10-02, 2026-10-09 and 2026-10-16, and the last push was on 2026-10-17. Nightly tags rather than numbered releases is the honest pattern for a research OS: there is no stability promise to make, and the tags exist to mark what the tree looked like on a given day.
The licence needs a careful reading. The repository badge says MIT licensed, the tree contains both LICENSE_MIT and LICENSE_APACHE-2.0, and the project metadata lists Apache-2.0. So the code is offered under the usual dual terms, and any specific file you copy should be checked against the two licence texts rather than the badge.
The repository also carries AGENTS.md and CLAUDE.md next to a .claude directory, plus a renovate configuration, rust-toolchain.toml and rustfmt.toml. For a Rust kernel that is a sensible tooling set, and the presence of agent instruction files is unusual enough to be worth a look if you plan to contribute.
The contribution guide is short and unusually warm: the author frames OS development as something that should be fun, easy and approachable, invites forks for experiments, and points at a small but growing Discord community. That is an invitation, not a production support commitment, and the difference between the two matters if you are planning to depend on this for anything long-lived.
Editorial conclusion
k23 earns attention from OS researchers, language runtime authors and anyone building sandboxed extensions, because it treats WebAssembly as a kernel-level execution environment with guest memory management, guest ASLR, trap handling and kernel integrity rather than as an application payload. It is the wrong tool for shipping anything: the driver phase has not started, the component model and Kotlin support are unchecked boxes, and there is no application ecosystem to borrow. Read the roadmap before you invest time, confirm that the WebAssembly proposals your guest needs, such as reference types, multi-value or tail calls, are on the pending list if your runtime needs them, and follow the manual rather than the README for anything beyond building and running the kernel in QEMU.
Frequently asked questions
What is k23?
k23 is an experimental microkernel operating system written in Rust that uses WebAssembly as its primary execution environment. The project presents itself as an active research project into a more secure, modular and approachable operating system.
Which hardware does k23 support?
RISC-V is the architecture named in the roadmap, in the completed bringup phase. The build tooling drops riscv-only and host-only targets that do not match the active platform rather than failing.
Can k23 run WebAssembly in userspace yet?
Yes, executing WASM in userspace is marked done, along with guest memory management, guest ASLR, trap handling and module imports and exports. Syscall context switching and basic host functions are still open, and so are proposals such as reference types, multi-value and tail call.
How do I build and run k23?
The project uses Buck2 with a justfile wrapper, so the just recipes build or run a target and pass arguments through to QEMU. The manual is published at jonaskruckenberg.github.io/k23.
What license is k23 released under?
The tree carries both LICENSE_MIT and LICENSE_APACHE-2.0, and the repository badge states MIT. Check the two licence files for the terms that apply to the code you use.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jonaskruckenberg-k23)