The ts/ workspace ships the anyfs stack as Node and browser libraries. The
wasm kernel build (LKL + QEMU block layer compiled with Emscripten) is wrapped
by a small set of @anyfs/* packages and consumed by two reference apps.
A live build of the browser demo is hosted at https://anyfs.kosaka.moe.
ts/
├── packages/
│ ├── core/ @anyfs/core — wasm kernel + JS bindings (browser + Node)
│ ├── react/ @anyfs/react — React hooks/provider over @anyfs/core
│ ├── trees/ @anyfs/trees — AnyfsFileBrowser (Chonky-based file UI)
│ └── anyfs-native/ @anyfs/native — Node N-API addon (uses the native lib, no wasm)
├── examples/
│ ├── vite-demo/ — browser demo, deployed to anyfs.kosaka.moe
│ └── electron-demo/ — Electron wrapper around vite-demo
├── package.json (pnpm workspace root)
└── pnpm-workspace.yaml
ts/ is a pnpm workspace; packages reference each other via workspace:*.
The runtime. Exports a wasm kernel build of anyfs (LKL + QEMU block layer + 35 filesystems) plus a thin JS surface for mounting disks and walking the VFS.
Ships four wasm bundles via package exports:
| Export | Target | QEMU block layer | Notes |
|---|---|---|---|
@anyfs/core/wasm/anyfs.mjs |
browser | yes | Runs inside a dedicated Web Worker |
@anyfs/core/wasm/anyfs.worker.js |
browser | yes | Worker bootstrap for the above |
@anyfs/core/wasm/anyfs.node.mjs |
Node | yes | Same wasm, Emscripten Node environment |
The browser bundle must run in a dedicated Web Worker — WORKERFS asserts
ENVIRONMENT_IS_WORKER, and Chrome forbids Atomics.wait on the main thread.
A worker-client.ts helper handles message passing.
Source layout (packages/core/src/):
boot.ts— kernel bringup + dmesg routingdisk.ts—anyfs_disk_*bindings (add/list/meta/remove)module.ts— Emscripten module wrapperurl-fs.ts— sync XHR + 512 KiB Range + 32-chunk LRU; mounts http(s) disk imagesworker.ts— runs inside the Web Workerworker-client.ts— main-thread proxynode.ts— Node entrypointindex.ts— public re-exports
Build:
pnpm -C ts -F @anyfs/core build # tsup TS bundle; wasm is committed pre-built
pnpm -C ts -F @anyfs/core test # smoke-tests against single/multi/big disk imagesThe wasm itself is produced out-of-band by
scripts/build_anyfs_wasm.sh (set ANYFS_TARGET=browser or node); see
scripts/build_lkl_wasm.sh for the kernel side.
React 18/19 hooks over @anyfs/core. Source (packages/react/src/):
provider.tsx—<AnyfsProvider>boots the worker, exposes disk handlesuse-dir.ts— directory listing hook (lklgetdents→ SWR-ish cache)use-file.ts— file read hook (chunked, suspense-friendly)
Build:
pnpm -C ts -F @anyfs/react buildA drop-in <AnyfsFileBrowser> component built on
Chonky 2.3.2 +
chonky-icon-fontawesome. Hands a mounted disk root to Chonky and wires
double-click into useDir / useFile.
Known footguns (from working on this UI):
- Chonky 2.3.2 silently drops
FileDataentries with falsyname. Use ZWSP ('') for icon-only crumbs. - Chonky 2.3.2's auto-extname splitter prepends
.to extensionless names — setextonFileDatayourself to short-circuit it.
A Node N-API addon that links against the native liblkl.so /
libanyfs-qemublk.so instead of the wasm build. Same JS surface as
@anyfs/core, ~10× the throughput, Linux/macOS only. Built with node-gyp.
pnpm -C ts -F @anyfs/native build # node-gyp rebuild
pnpm -C ts -F @anyfs/native testVite + React 19 + Tailwind 3. The deployed app at
https://anyfs.kosaka.moe serves this build. It boots @anyfs/core during the
landing screen (project_anyfs_landing_prewarm), accepts file drops and HTTP
URLs (@anyfs/core/url-fs), and renders the disk tree with @anyfs/trees.
pnpm -C ts -F vite-demo dev # http://localhost:5173
pnpm -C ts -F vite-demo build # static output in ts/examples/vite-demo/distThe wasm bundle is loaded via anyfs.mjs and always includes the QEMU
block layer (qcow2/vmdk/vdi/vhd + raw). If you modify any of the C glue,
rebuild with scripts/build_anyfs_wasm.sh or the demo will keep running
the stale wasm.
Electron wrapper around the vite-demo build, packaged for Linux x64 and macOS
arm64 via @electron/packager. The renderer is loaded through a custom
anyfs:// protocol — file:// can't carry the COOP/COEP headers Atomics
needs.
pnpm -C ts -F electron-demo dev # vite + electron, live reload
pnpm -C ts -F electron-demo package # Linux x64
pnpm -C ts -F electron-demo package:mac # macOS arm64preload.ts is currently a placeholder; the renderer talks to @anyfs/core
the same way the browser demo does. A future iteration will bridge to
@anyfs/native via N-API.
cd ts
pnpm install # one-time
pnpm -r --filter './packages/*' build # build all libraries
pnpm -r --filter './packages/*' test # smoke tests