Filesystem

The virtual filesystem — an in-memory tree with pluggable providers, blob-backed large files, persistence, and tar.gz snapshots.

Every box has a VFS — a virtual filesystem that behaves like a POSIX tree (files, directories, symlinks, permissions, mtimes) but lives in memory as plain JavaScript objects. It's the single source of truth that the shell, commands, and the Node fs shim all read and write.

The tree and its API

The VFS exposes the operations you'd expect, synchronously at the core level:

kernel.vfs.writeFile("/home/user/a.txt", "hello");
kernel.vfs.readFileString("/home/user/a.txt"); // "hello"
kernel.vfs.readdir("/home/user"); // Dirent[]
kernel.vfs.stat("/home/user/a.txt"); // Stat
kernel.vfs.mkdir("/tmp/x", { recursive: true });

The Sandbox fs helper wraps these in a promise-based, node:fs-shaped API (readFile, writeFile, readdir, stat, mkdir, rm, exists, rename, cp), and the Node runtime maps node:fs / node:fs/promises onto the same tree.

The VFS also emits watch events (vfs.watch(listener)), which power fs.watch in the Node layer, HMR file watching for dev servers, and the kernel's own save-on-change persistence.

Providers: synthetic and mounted paths

Not every path is a plain in-memory file. The VFS supports providers mounted at a path prefix:

  • /proc — synthetic process/system info generated on read.
  • /dev — device-like files.
  • NativeFsProvider — backs a subtree with a real host directory. In Node, the mounts option uses this so a box reads and writes files on your machine; it can also take a custom NativeFsModule.

Large files: blob & content store

Small files live inline in the tree. Large or binary files are chunked and stored in a content store backed by a blob store — MemoryBlobStore by default, or IndexedDBBlobStore in the browser. Content is addressed by hash (hashBytes), so identical data is stored once. CHUNK_THRESHOLD and CHUNK_SIZE control when and how a file is chunked.

Persistence

The kernel drives persistence through a PersistenceManager and a pluggable PersistenceBackend:

  • IndexedDBPersistenceBackend — the browser default; the VFS is serialized and saved to IndexedDB, debounced on change, so a box survives a reload.
  • MemoryPersistenceBackend — volatile; nothing is written out.

Serialization is exposed directly too (serialize / deserialize, SerializedNode) if you want to manage box images yourself.

Snapshots

Beyond incremental persistence, a box's whole disk can be exported as a tar.gz and restored elsewhere — the basis for saving, cloning, and moving boxes between environments.

const image = await sandbox.fs.exportSnapshot(); // Uint8Array (tar.gz)
await otherSandbox.fs.importSnapshot(image);

Note

Snapshots are whole-disk, point-in-time images. A write-ahead log for crash-consistent, incremental durability is on the roadmap, alongside choosing the backing store per environment (IndexedDB/OPFS in the browser, the host filesystem via the CLI, or purely volatile).