func New
New returns an empty file server owned by uid, with its root created at block height now.
Package memfs is a RAM file server: Plan 9's ramfs, in a realm's heap.
gno.land/p/moul/x/plan9/memfs/v0A RAM file server: Plan 9's ramfs, in a realm's heap. The reference
implementation of ninep.File and ninep.Mutable.
1import memfs "gno.land/p/moul/x/plan9/memfs/v0"
2
3fs := memfs.New("g1...", runtime.ChainHeight())
4fs.MkdirAll("/usr/glenda/bin", height)
5fs.WriteFile("/tmp/greeting", "hello\n", height)
6root := fs.Root() // a ninep.File, mountable into any namespace
Children live in an avl.Tree, so a directory listing is ordered by name and
therefore identical on every validating node. A map would make Render a
consensus bug.
Mutable is in-realm only. A non-crossing method runs in the caller's
frame, so a foreign realm calling Create or Write here would be mutating
objects it does not own. The read half is safe from anywhere, which is exactly
what makes a memfs tree mountable into somebody else's namespace: they get
reads, and only its owner gets writes.
The clock is a parameter, not an import. Every mutation takes the block height from the caller rather than reading chain state itself, so the same tree runs in a plain unit test.
9P behaviours reproduced rather than approximated:
Length 0, as 9P does.Qid.Version increments on every write, so a client holding a qid can tell
"same file, changed" from "different file" without reading it.DMAPPEND pins every write to the end, whatever offset was asked for.Design and analysis: moul/gno-contracts#136.
Not affiliated with Plan 9. Plan 9 from Bell Labs is the work of the Computing Science Research Center at Bell Labs; the name and the marks are theirs, and the copyright is held by the Plan 9 Foundation. This package borrows the vocabulary and none of the code: it is an independent homage, asking what that ecosystem's spirit looks like on a chain. Full attribution: NOTICE.
Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
Dependency graph:

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.
Package memfs is a RAM file server: Plan 9's ramfs, in a realm's heap.
It is the reference implementation of gno.land/p/moul/x/plan9/ninep's File and Mutable, and the tree a namespace server hands out as a user's private root. Children live in an avl.Tree, so a directory listing is ordered by name and therefore identical on every validating node; a map would make Render a consensus bug.
Mutable is IN-REALM ONLY. A non-crossing method runs in the caller's frame, so a foreign realm calling Create or Write here would be mutating objects it does not own. Reads (the ninep.File half) are safe from anywhere, which is what makes a memfs tree mountable into somebody else's namespace.
The caller supplies the clock (a block height) on every mutation rather than the tree reading chain state itself, so the same tree is exercisable in a plain unit test.
NOTICE. Plan 9 from Bell Labs is the work of the Computing Science Research Center at Bell Labs; the name and the marks are theirs, and the copyright is held by the Plan 9 Foundation (https://p9f.org). This package is not affiliated with, endorsed by, or sponsored by them, and contains no Plan 9 code: it borrows the vocabulary so that the design reads without a glossary, and it is an homage, asking what that ecosystem's spirit looks like on a chain. Full attribution: NOTICE.md at the root of moul/gno-contracts.
FS is a mutable in-memory file tree.
MkdirAll creates p and every missing parent, and returns the leaf. An existing directory is not an error; an existing plain file on the path is.
Root returns the server's root directory.
RootMutable returns the root as a Mutable. Only call it from the realm that owns this FS.
Uid returns the owner this server stamps on new files.
WriteFile creates or replaces the file at p, creating parent directories as needed. It is the seeding helper a realm wants at init.