Show HN: Kandelo – a POSIX-compatible multi-process WASM kernel for the browser (kandelo.dev)

1 points by brandonpayton ↗ HN
Kandelo is an open-source, Wasm-based multi-process kernel that runs POSIX programs in browsers and Node.js.

Kandelo is still experimental, but it already runs a substantial range of existing software.

Main ask: Do you have use cases for this?

We are trying Kandelo as a new foundation for WordPress Playground which runs server-side WordPress entirely in the browser. Kandelo also looks like promising as a sandbox for running agents in the the browser and on the command line. On the side, we've been playing with porting games and desktop environments and even compiling runnable programs within Kandelo.

Yet it feels like there are many possibilities we haven't considered. Is there a way you would like to use something like this?

Background

I wanted an authentic OS-level foundation for running systems software in the browser and started this as a vibe-coded exploration. I figured it would end up being too slow and that we would have to offer many different ways to compromise default POSIX behavior to get anything usable. But after weeks of fighting agents, insisting on genuine POSIX compatibility as the default, I was surprised at how well the system worked without those compromises.

Nginx, PHP, Python, Ruby, Redis, and even MariaDB were able to be built using the SDK with minimal hacks.

Then we started porting games, having fun, and playing to see how far we could push it.

Here are some demos:

Some notes: - The demos have been tested in desktop browsers. YMMV on mobile today. - Some of the disk images are large (~50MB) and may take a while to boot initially.

Main set, with Shell (bash, vim, nethack, and more), Nginx, PHP, WordPress, and Doom: Note: There's a Node.js demo, but it is currently broken. https://kandelo.dev/20260819-demo/

LÖVE game engine: https://kandelo.dev/20260819-demo-love/

SNKRX running under LÖVE: https://kandelo.dev/20260819-demo-love/?vfs=love-snkrx-abi44...

Commander Keen running in DOSBox: https://kandelo.dev/20260819-demo-dos/?demo=keen

LXDE desktop PoC: https://kandelo.dev/20260819-demo-lxde/?demo=desktop-lxde

Notes on architecture:

- Central, single-worker kernel, aiming to provide all supportable POSIX syscalls. - Each process is a dedicated worker with independent memory. - Each process thread is a dedicated worker that shares memory with threads from the same process. - Syscalls are done with the process SharedArrayBuffer and the Atomics API. - fork() is supported. - The system is centered around virtual file system (VFS) images. - VFS images can contain lazy references to programs not stored in the images. Vim is such a reference in the shell demo.

On GitHub: https://github.com/Automattic/kandelo

12 comments

[ 0.43 ms ] story [ 29.2 ms ] thread
This is so cool! I'm having trouble thinking of all the different use cases and potential issues with this, but I don't think anyone has done something like this before. Great work
Thanks for taking a look and for kind words!

We've also had a prototype running multiplayer DOOM between browsers via WebRTC. I wonder what kinds of network applications might be interesting here.

I had the idea of achieving build isolation by codemodding the Rust implementations of bash and the GNU coreutils (brush+uutils) to use a VFS (wasmtime's cap-std) backed by the real FS and then disabling anything that remained problematic. It kind of works but I'm still not particularly confident in it and I think this is probably the better approach.

The some points of trouble I ran into were dead symlinks left behind on the FS pointing to real files and escape codes interacting with the terminal (e.g. escape codes reading from the clipboard).

The build isolation approach sounds interesting, but I'm not sure I understand.

Do you mean isolating build scripts by using a VFS mapped to the real FS and masking away everything the build script should not have access to?

> The some points of trouble I ran into were dead symlinks left behind on the FS pointing to real files

Symlinks make this space trickier for sure.

> escape codes interacting with the terminal (e.g. escape codes reading from the clipboard).

Woah. TIL this was possible.

> Do you mean isolating build scripts by using a VFS mapped to the real FS and masking away everything the build script should not have access to?

Yes. Essentially the idea was to find the source control root (or something configurable) and mount the real subtree into a VFS where everything interacts with the filesystem through the VFS. I can run wasm compiled versions of apps I don't really trust or run native patched versions that I do.

For background, I'm writing a UI platform in Roc [1] and using just [2] in order to script things. I had extra tokens so I decided to do an LLM port of just over to Roc to exercise the compiler (it's pre-0.1, pushing the compiler leads to crashes) and people won't have to install Rust to write apps. Like wasm, Roc code can't access the outside world without the host providing the access to the outside world so in the process of the port I thought "I don't have to make posix calls, I can put it in sandbox and lie about it" so that's how I got here. I'm fairly close to being able to do hermetic builds so that's a possibility but this is mostly an exploration of whether the idea works or not.

[1] https://roc-lang.org/ [2] https://github.com/casey/just

Thanks for sharing details. It does seem like a natural place for a Wasm sandbox + VFS.

Hopefully we can make running these kinds of commands easier as the project progresses.

If you have any interest, please feel to suggest what you want or submit a PR at https://github.com/Automattic/kandelo/. It's easy to get stuck in our own heads working on these tools, and hearing from any real/potential user would be good oxygen for the project.

I really like this. I think the possibilities are multiple. I will try it to test the generic POSIX compliance of my main hobby project.

What is the main plus you have over other similar projects or tools like JSLinux?

Which preprocessor directives can I expect to have if I need to write custom code when my executable is compiled for Kandelo?

What is the reason for choosing GPL instead of MIT or similar?

> What is the main plus you have over other similar projects or tools like JSLinux?

Good question! I had to do some research. Here's my understanding:

JSLinux is emulates a complete machine architecture. JSLinux runs in the browser's Wasm runtime, and JSLinux programs run on JSLinux. Both Kandelo's kernel and processes run directly in the browser's Wasm runtime, with the kernel fielding syscalls from processes. Kandelo does not emulate CPUs.

Pre-existing software can run on JSLinux, but software must be rebuilt to run on Kandelo.

Given the lack of CPU emulation, I would expect Kandelo to be more efficient than JSLinux, but for completeness, it's hard to beat JSLinux's actual system emulation.

> Which preprocessor directives can I expect to have if I need to write custom code when my executable is compiled for Kandelo?

In general, we intend user software to be buildable by using standard C/POSIX macros with the Kandelo SDK. Does that answer your question?

> What is the reason for choosing GPL instead of MIT or similar?

We have a mix of GPL and MIT licenses in this project. For software that is not linked with with user programs, we choose the GPL so that folks may build upon our work but cannot make it closed source. Software that links with user programs is intentionally MIT-licensed to avoid forcing user software into the GPL.

Here are our brief notes on the topic: https://github.com/Automattic/kandelo/tree/67ad37130e2ba4c11...

How easy would it be to integrate this into something like this

https://lerc.neocities.org (first page load initialized the filesystem in indexeddb, reload the page to boot off it). I really should automate that.

If there is enough of an API to the processes being run by kandelo, I could even build a full /proc interface for them.

I feel like I'm not properly appreciating what that site does. It fun to interact with the shell and fun to see JS implementations of core utils. How would you imagine Kandelo might integrate with it? Would it be another way to run programs in addition to the JS utils?

There is already a way to list processes that the Kandelo web app uses. To see the info, you can click the Internals button in the dock and click on the Procs tab. I'll try to follow up later with more details.

>Would it be another way to run programs in addition to the JS utils?

That's what I was thinking. While it's reasonable to re-implement a lot of basic commands, once you get to large pre-existing software, having a way to run them from the same environment is what's needed.

The main integration point start wold be that my environment would need to have a way to point at some data filename/url and identify that it is a thing that can be run by Kandelo. Then it would pass it to Kandelo, If it had hooks for allowing the host environment to manage operations for some file descriptors then my environment would be able to assemble something that looked like stdin and stdout to the running process.

There's obviously a lot more going on for things that do graphics. Something that hid KMS stuff inside an iframe doesn't seem like it would be impossible though.

Sorry for the slow response. I was resting after some travel.

> The stdin and stdout that the commands use actually have multiple channels, with html, json, and raw output possible. Commands can provide different output to each channel or just one.

This is pretty interesting!

> The contents are auto downgraded to whatever the reader can handle. So a program can actually output an <img> tag but if it is piped to something that can't handle html input it will receive it as text of the html source.

Like a stream of typed entities? This is a neat idea and one I'll need to digest. What kinds of ways do you use it?

> If it had hooks for allowing the host environment to manage operations for some file descriptors then my environment would be able to assemble something that looked like stdin and stdout to the running process.

I think there should be a protocol for custom mount types and made a Kandelo issue for it [1].

> There's obviously a lot more going on for things that do graphics. Something that hid KMS stuff inside an iframe doesn't seem like it would be impossible though.

We have Linux-style framebuffer support and exploratory devices for direct rendering. IIRC, all target a <canvas> context from a worker, so it seems like there should be a path to rendering to one embedded in an iframe.

[1] https://github.com/Automattic/kandelo/issues/1315