Implementations

StructFS is an architectural style. These are the implementations that make it concrete.

Rust (reference implementation)

The reference implementation is written in Rust.

It includes the core store traits, several built-in store types, and an interactive REPL for exploring stores from the command line.

Install the REPL

cargo install structfs-repl

Use as a library

cargo add structfs

Packages

The implementation provides two traits (Reader and Writer) that every store implements. The workspace is split into focused crates:

Core store

structfs-core-store: the Reader/Writer traits, Path and Value types, mount management, typed errors, and the combinators (read-only, cascade, rooted, masked, shared). The foundation all stores build on.

Paths

structfs-path-validation and structfs-path-macro: the component grammar, Namecode encoding for arbitrary strings, and a path! macro that validates literals at compile time.

Serde store

structfs-serde-store: typed access (read_typed/write_typed) on any store, and the transport codecs — JSON, CBOR, and FlexBuffers, all equivalent-tier.

Handles

structfs-handles: the handle protocol as a primitive — outstanding/{id} scaffolding, atomic tail reads, parking, cancellation. Certified by its own conformance suite.

JSON store

structfs-json-store: in-memory tree of structured values with optional file persistence and append logs. The default for experimentation.

HTTP

structfs-http: HTTP client store (reads become GETs, writes become POSTs) and broker store (write queues, read executes).

System primitives

structfs-sys: environment variables, time, random numbers, process info, filesystem handles: OS functionality as stores.

Facade

structfs: one crate that re-exports the family behind feature flags (serde, json, http, sys, async, full). Start here.

Isotope and featherweight

If everything is a store, what does an operating surface look like?

Isotope is a virtual-OS specification built on the StructFS model: blocks are pico-processes whose entire world is store reads and writes. A block's "syscall surface" is a store at /iso/ (identity, time, randomness, stdio, lifecycle), its capabilities are the paths wired into its namespace (unwired paths are denied — reads and writes alike), and serving requests means reading a mailbox path. Assemblies compose blocks the way mounts compose stores, and nest fractally.

Featherweight is the strawman runtime that makes the spec concrete: assembly instantiation with capability wiring, a two-function wasm Block ABI (any language that targets wasm can implement it in an afternoon — no bindgen, no component tooling), a WASI compatibility shim layered above the ABI, adapters for WIT components, and a dependency-free browser host that runs the same guest binaries in a Web Worker. The crates are being prepared for release.

Walkthrough

Install the REPL and try the model hands-on. Or use the browser playground.

Your first store

$ structfs
> write /data/greeting "Hello, World!"
Written to: /data/greeting

> read /data/greeting
"Hello, World!"

A memory store is already mounted at /data. You wrote a string to a path, then read it back. That's the entire interface.

Structured data

> write /data/users/alice {"name": "Alice", "email": "alice@example.com"}
Written to: /data/users/alice

> read /data/users/alice
{"name": "Alice", "email": "alice@example.com"}

Values aren't just strings. Maps, arrays, numbers, booleans: structured data, not bytes.

Everything is a path

> read /ctx/sys/env/HOME
"/Users/alice"

> read /ctx/sys/time/now
"2025-01-15T10:30:00Z"

> read /ctx/sys/random/uuid
"550e8400-e29b-41d4-a716-446655440000"

The environment, the clock, a random number generator: real stores mounted at /ctx/sys, responding to read the same way your data store does.

Mount more stores

> write /ctx/mounts/scratch {"type": "memory"}
Written to: /ctx/mounts/scratch

> write /scratch/temp "ephemeral"
> read /scratch/temp
"ephemeral"

The mount system itself is a store at /ctx/mounts. Even configuration uses the same interface.

HTTP broker

> write /ctx/http {"method": "GET", "path": "https://httpbin.org/get"}
Written to: /ctx/http/outstanding/0

> read /ctx/http/outstanding/0
{"status": 200, "headers": {...}, "body": {...}}

Write queues the request. Read executes it. The broker pattern in action.

The REPL

When the REPL starts, several stores are already mounted:

PathStore
/ctx/httpHTTP broker: queue requests, read responses
/ctx/http_syncSynchronous HTTP: blocks until response arrives
/ctx/sysOS primitives: env, time, random, process, filesystem
/ctx/helpDocumentation: aggregates docs from all mounted stores
/ctx/mountsMount configuration: read to list, write to add

Registers

Registers capture output for reuse. Prefix any command with @name:

> @result read /ctx/sys/time/now
"2025-01-15T10:30:00Z"

> read @result
"2025-01-15T10:30:00Z"

Dereference with *@name to use a register's value as a path:

> @h write /ctx/sys/fs/open {"path": "/tmp/test.txt", "mode": "write", "encoding": "utf8"}
> write *@h "Hello, World!"
> write *@h/close null

*@h expands to the path returned by the open call. *@h/close appends /close. This is how you work with handle-based protocols in the REPL.

Help

> read /ctx/help
> read /ctx/help/commands
> read /ctx/help/stores

The help store aggregates documentation from all mounted stores. Mount a new store that provides docs, and they appear in the help tree automatically. Vi mode is detected from your environment (EDITOR=vim, ~/.inputrc, or STRUCTFS_EDIT_MODE=vi).

Build your own

StructFS is designed to be implementable in any language.

The interface is two operations over paths and structured values. No complex type system, no code generation, no language-specific features. If your language has maps, strings, and functions, you can implement StructFS.

Start with the model, then store design and patterns. The specification is the interface; everything else is an implementation choice.