# Wanix

Wanix builds a Unix-shaped environment inside a web page. It borrows the two ideas that made Plan 9 interesting — everything is a file, and every process gets its own namespace — and implements them over browser APIs, so a page can run [[webassembly|Wasm]] binaries and, through an x86 emulator, actual Linux, with no server involved. The 0.4 release wraps all of this in custom HTML elements, which is how the demo on wanix.dev gets a working shell out of three tags:

```html
<wanix-term>
  <wanix-bind dst="rc.wasm" type="file"
    src="https://wanix.dev/extras/0.4.0-rc2/rc.wasm">
  </wanix-bind>
  <wanix-task cmd="rc.wasm" term start></wanix-task>
</wanix-term>
```

`rc` there is the Plan 9 shell, compiled to Wasm and fetched into the namespace at `rc.wasm`, then executed as a task with a terminal attached.

## The namespace model

Everything a program can touch is a path, and the kernel exposes its own facilities under `#`-prefixed device paths: `#task` for process control, `#term` for terminals, `#vm` for virtual machines, `#ramfs` for in-memory filesystems (cloned per bind), `#pipe`, `#signal`, and `#web` for browser integration — including `#web/opfs` for the Origin Private File System, which is where persistence comes from. A task inherits its parent's namespace by default and can be given a different one, which is the whole sandboxing story: a program sees exactly the files someone bound in for it, and nothing else. That is a stronger and simpler boundary than the capability wiring [[wasmer]] and other server-side runtimes do through WASI preopens, because the composition happens in the same primitive the program uses to read files.

`<wanix-bind>` is the primitive that builds those namespaces, and it does more than link names. `type="file"` fetches a URL or inlines content, `type="archive"` unpacks a `.tar`/`.tgz` into a directory tree — and layering several archives or directory binds onto the same `dst` produces a recursive union, the Plan 9 union-mount behaviour rather than an overlay filesystem. `type="import"` pulls in a *remote* namespace, spoken as 9P over a WebSocket or embedded as an iframe. A page can export its namespace with an `id` and an `allow-origins` list, so two pages on different origins can share a filesystem across a protocol from 1992.

## Running things

Tasks are dispatched to pluggable drivers selected by a `type` attribute: `js` for plain JavaScript, `gojs` for Wasm built with `GOOS=js GOARCH=wasm`, `wasi` for `wasip1` modules, and `auto` to detect. Keeping `gojs` and `wasi` as separate drivers is the right call — the two targets have genuinely different host contracts, and picking the wrong one is exactly the failure documented in [[adding-go-to-a-browser-code-runner]], where `GOOS=js` hung forever inside a bare V8 isolate because nothing drove the microtask queue.

`<wanix-vm>` is the escape hatch for code that was never going to be Wasm. It runs [v86](https://github.com/copy/v86), an x86 emulator in JavaScript, inside the namespace: bind in the emulator assets and a Linux system image, and it detects the kernel and boots to a shell. Attributes cover RAM size (`mem`), console terminal allocation (`term`, which needs `raw` mode for VM consoles), and `export`, which republishes the guest's internal namespace at `#vm/1/guest` if the image cooperates. So the same page can host a Wasm shell and an emulated Linux and treat both as files.

The heaviest element is `<wanix-workbench>`, an embedded VS Code workbench backed by the Wanix namespace, usable as an editor, a file explorer, a full IDE, or an app shell. It requires an extra `assets` bundle and a task marked `role="shell"` before its terminal works.

Adding it to a page is one script tag:

```html
<script type="module"
  src="https://cdn.jsdelivr.net/npm/wanix@0.4.0-rc2/dist/wanix.min.js"></script>
```

## Caveats

The version on the landing page is `0.4.0-rc2` — a release candidate, not a stable release, and the docs say custom workbench extensions and live-editing them in place are future work. The project comes out of tractordev and has been going since October 2023, at 797 stars and 38 forks as of late July 2026, with the last push on 2026-07-19. That is steady rather than fast, and it is effectively one shop's project.

Worth noting about the source: wanix.dev's per-element examples are rendered by the page's own JavaScript, so a clipped copy of the site arrives with the code blocks empty. The device names and task-driver list here come from the repository README instead.

Tagged `watchlist` — pre-1.0 and single-vendor, see [[toolbox/watchlist]]. The reason to keep an eye on it is that per-process namespaces are a better fit for sandboxing untrusted browser-side code than the ad-hoc capability plumbing most Wasm hosts use, and this is the only implementation of that idea aimed at the web.

MIT, ~797★ as of 2026-07-29. There is a 19-minute talk on the design at [youtube.com/watch?v=kGBeT8lwbo0](https://www.youtube.com/watch?v=kGBeT8lwbo0).
