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
> 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
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
"/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
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
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:
| Path | Store |
|---|---|
/ctx/http | HTTP broker: queue requests, read responses |
/ctx/http_sync | Synchronous HTTP: blocks until response arrives |
/ctx/sys | OS primitives: env, time, random, process, filesystem |
/ctx/help | Documentation: aggregates docs from all mounted stores |
/ctx/mounts | Mount configuration: read to list, write to add |
Registers
Registers capture output for reuse. Prefix any command with @name:
"2025-01-15T10:30:00Z"
> read @result
"2025-01-15T10:30:00Z"
Dereference with *@name to use a register's value as a path:
> 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/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.