Bead Namespace API — Plan-9 command surface for bead composition (Plan9 Beads)

**Artifact** from Bead: Plan9 Beads · [canonical source](https://redfish.acequia.io/guerin/.agents/975f5db5-905e-42c4-8ec6-f3911a691374/2026-06-11/artifacts/bead-namespace-api.md) · session 2026-06-11 · discussion: Talk: Plan9 Beads

**Bead:** `975f5db5-905e-42c4-8ec6-f3911a691374` (plan9-beads) · **Date:** 2026-06-11 · **Status:** proposed (design artifact; not yet implemented or ratified into [`beads.md`](https://redfish.acequia.io/guerin/.agents/beads.md)) A five-command surface for composing a live chat into one or more beads, modeled on Plan-9 namespace operations. Reads delegate across mounted beads (fused concepts); writes route to a declared create target. Design rationale: [start-vs-mount](https://redfish.acequia.io/guerin/.agents/975f5db5-905e-42c4-8ec6-f3911a691374/2026-06-11/notes/00-start-vs-mount.md), [multiple-prototypes-and-self](https://redfish.acequia.io/guerin/.agents/975f5db5-905e-42c4-8ec6-f3911a691374/2026-06-11/notes/01-multiple-prototypes-and-self.md), [plan9-union-semantics](https://redfish.acequia.io/guerin/.agents/975f5db5-905e-42c4-8ec6-f3911a691374/2026-06-11/notes/02-plan9-union-semantics.md).

## Conventions - **Argument order is Plan-9: `verb new old`** — the mount point (`old`) is **last**; the thing attached (`new`) is first. - A **bead** is named by its absolute URI or by a short name resolved through the session namespace-file / a bead's `names.json`. - A **mount point** is a path in the chat's working namespace (e.g. `/ctx`), distinct from any real WebDAV path. - The `.agents/` directory is the **registry** (the Plan-9 `/srv` analog): every bead is a postable, mountable served tree.

## Command summary | Command | Plan-9 kin | Lifecycle | Effect | |---|---|---|---| | `bead-start [slug]` | `srv` / create | birth | Construct a bead (new GUID + folder) if none open; post it to the registry. The initializer. | | `bead-mount [-b\|-a] [-c] <bead> <point>` | `mount` | composition | Attach a bead's served tree into the chat's namespace at `<point>` (union). Repeatable, plural. | | `bead-unmount [<bead>] <point>` | `unmount` | composition | Remove one member from the union at `<point>`, or clear `<point>` entirely. | | `bead-ns` | `ns` | inspection | Print the current mount table (this session's namespace). | | `bead-rfork` | `rfork`/`newns` | isolation | Fork the namespace so this chat's mounts don't leak to sibling chats. |

## `bead-start [slug]` Constructor. Births a bead if no bead session is open: generates a GUID, creates `.agents/<GUID>/` with the standard root files and a dated kind-folder set, and posts it to the registry. If a bead is already open, this is a no-op (or attaches the optional `slug` as the human name). **Does not** compose anything — composition is `bead-mount`. ``` bead-start plan9-beads ``` - **slug** *(optional)* — human name recorded in `about.md` / `agent.json`. - **Returns** — the new bead URI. - See: [start-vs-mount](https://redfish.acequia.io/guerin/.agents/975f5db5-905e-42c4-8ec6-f3911a691374/2026-06-11/notes/00-start-vs-mount.md).

## `bead-mount [-b | -a] [-c] <bead> <point>` Binder. Attaches `<bead>`'s served tree at `<point>` as a **union member**. Repeatable: mount many beads at the same point to form a union directory. **Flags** | Flag | Plan-9 | Meaning | |---|---|---| | `-b` | `MNT_BEFORE` | Union member searched **first** on reads (highest read priority). | | `-a` | `MNT_AFTER` | Union member searched **after** existing members. | | *(neither)* | replace | Replace whatever is bound at `<point>`. | | `-c` | `MNT_CREATE` | This member is the **create target**: new files created under `<point>` land here. | Flags combine: `-ac` = union-after **and** create target. ``` bead-mount -b https://…/.agents/A/ /ctx # A: read first, read-only bead-mount -a B /ctx # B: read after, read-only (short name) bead-mount -ac C /ctx # C: read after, AND write target ``` **Resolution rules** - **Read** `/ctx/<x>` → search members in `-b`/`-a` order; **first hit wins**. The chat's own emissions shadow all mounted members. - **Write/create** `/ctx/notes/<x>.md` → lands in the **`-c` member**, in the matching kind-subdir (`notes/`/`skills/`/`artifacts/`, per beads.md Impl Detail #3). No `-c` pinned → **shadow locally** until one is. **Constraints** - Keep **at most one `-c` per point** (legible default; two create targets = ambiguous write). - A bead may only be a `-c` target if the caller holds write authority over it (owner, or a delegated chain-token whose `writePaths` cover it). Otherwise mount read-only.

## `bead-unmount [<bead>] <point>` Removes `<bead>` from the union at `<point>`. Omit `<bead>` to clear the whole point. ``` bead-unmount B /ctx # drop just B from the union bead-unmount /ctx # unmount everything at /ctx ```

## `bead-ns` Prints the current mount table: each point, its members in search order, and which member carries the create bit. Use before a write when unsure where it will land. ``` bead-ns # /ctx (union) # [1] A https://…/.agents/A/ read # [2] B https://…/.agents/B/ read # [3] C https://…/.agents/C/ read,create* ```

## `bead-rfork` Forks the session namespace. After `bead-rfork`, mounts made by this chat are private to it and do not affect sibling chats sharing the same beads. Mirrors Plan-9's per-process copy-on-fork namespace. Conservative default: **fork on session open** (isolation by default); shared namespaces are opt-in.

## The session namespace-file The durable form of the mount table — `names.json` lifted from per-bead to **per-session**, the bead analog of Plan-9's `/lib/namespace`. Replaying its `mounts` re-binds the chat's view. ```json { "profile": "acequia/session-namespace", "session": "<chat-or-session-id>", "mounts": [ { "bead": "https://…/.agents/A/", "point": "/ctx", "order": "before", "create": false, "name": "A" }, { "bead": "https://…/.agents/B/", "point": "/ctx", "order": "after", "create": false, "name": "B" }, { "bead": "https://…/.agents/C/", "point": "/ctx", "order": "after", "create": true, "name": "C" } ] } ``` `order` ∈ `before | after | replace` (→ `-b`/`-a`/neither); `create: true` ↔ `-c` (one per point); `name` is the local alias for `wiki-links` while mounted.

## Worked example A chat fusing the **doorbell** acoustic work with the **storm-event** viewer, writing new shared concepts into a fresh design bead: ``` bead-start sensor-fusion-notes # construct the write target bead-mount -b 883c513f-…/ /ctx # doorbell: read first bead-mount -a 1c0f5851-…/ /ctx # storm-event: read after bead-mount -ac sensor-fusion-notes /ctx # new bead: read last, IS the write target # → reads union across doorbell + storm-event + new bead (fused concepts) # → every emitted note persists into sensor-fusion-notes/notes/ bead-ns # confirm the create target ```

## Mapping back to the three lenses | Concept | Self | Plan-9 | this API | |---|---|---|---| | read across parents | prioritized parent slots | union search order | `-b`/`-a` | | tie-break on same name | slot priority | mount order | mount order | | where a new thing is stored | (n/a — write stays own) | create bit | `-c` | | isolate one actor's view | (n/a) | per-process namespace | `bead-rfork` | | persisted view | (n/a) | `/lib/namespace` | session namespace-file | The one piece with no JS/Self equivalent is **write-through** (`-c`), because files persist and object properties don't — see [multiple-prototypes-and-self](https://redfish.acequia.io/guerin/.agents/975f5db5-905e-42c4-8ec6-f3911a691374/2026-06-11/notes/01-multiple-prototypes-and-self.md).