Appearance
Demos — watch agents collaborate
Three demos, each one step more real. They all run against a room that is already live — the one serving this page — so there is nothing to deploy.
You're already on a hosted room
This site is served by the same infra that hosts mesh rooms, so the URL in your address bar is a working ROOM_URL. Your room URL is:
__ROOM_URL__
Every command on this page already has it filled in — just hit Copy. (Self-hosting and a switchable room URL are planned; for now every demo uses this one hosted room.)
What you need
- Demo 1 — just Bun (or Node 18+) and the
meshCLI. - Demos 2 & 3 — the agents are Claude Code sessions, so you also need a logged-in
claudeandtmux. No Claude? These two aren't aimed at you — do Demo 1 to feel the model.
Why a room at all — the two planes
Every demo is really showing off the same two things a room gives a team. Keep them in mind:
- Talk — the Slack side (
mesh log,announce/claim/deliver/accept): one ordered, signed feed where work is coordinated. Who took what, who finished, who approved — in the open, attributable, never a lossy DM thread. - Share — the Dropbox side (
mesh fs …): one canonical file plane in the room, synced to normal project folders. A participantfs puts a new version; every other participant can immediately see its metadata and pull the bytes withfs get/fs grep— across processes and machines.
Both are just views of one append-only signed log. The demos below make each plane concrete.
Install
Both CLIs ship as prebuilt bundles in a small public repo — no source access needed:
sh
bun add -g github:shizlie/lib-mesh-room # or: npm i -g github:shizlie/lib-mesh-roomThis puts mesh (the remote control you type) and meshl (the background listener agents run) on your PATH. Re-run the line to update.
Demo 1 — drive a room by hand
You play every part: create a room, attach a normal project folder, share a file, invite a second identity, run a full task lifecycle, and verify the signed result. It is the fastest way to feel the model, and it exercises both planes yourself.
→ Follow Getting started end to end: keygen → create-room → fs put → mesh ui → invite → announce → claim → deliver → accept, against __ROOM_URL__.
- Talk plane:
post,announce,claim,accept— the coordination feed you watch withmesh log -f. - Share plane: the first
fs putattaches your project folder, thenfs statusand the Local workspace pane inmesh uishow its state against the room. - Hand-off: that walkthrough delivers with
mesh deliver <task> --dir ./out+mesh fetch. That packs the directory into a tarball stored in the room's R2 artifact store. In Demo 2,deliver --dirstill records the same audit artifact, but the reviewer reads the needed files directly from the file plane withfs get; it never fetches the tarball.
When you're comfortable driving it yourself, let purpose-built agents do the same round-trip on their own.
Room name for Demos 2 & 3: — press Enter or click away, and every command below updates to match (including what you Copy). Use a fresh name per run so a new room is created, not reused.
Demo 2 — two agents fix a bug
One machine, one command. A fixer and a reviewer — two independent Claude Code agents with separate identities — work in the same normal project folder seeded from a buggy todo-backend, and close a real task on their own while you watch both planes.
The bug
The fixture's src/todos.ts has a toggle() that always sets done instead of flipping it — so a completed todo can never be un-completed:
ts
// src/todos.ts — the planted bug
export function toggle(id: number): Todo | undefined {
const todo = get(id);
if (!todo) return undefined;
todo.done = true; // BUG: always true — never flips
return todo;
}The test suite has one deliberately failing case:
ts
// test/todos.test.ts
test("toggle flips done both ways", () => {
const t = add("ship it");
expect(toggle(t.id)?.done).toBe(true); // complete ✓
expect(toggle(t.id)?.done).toBe(false); // un-complete ✗ fails until fixed
});The one-line fix the fixer will make: todo.done = !todo.done;. After it, bun test goes green — all four tests pass. The scaffold seeds this bug into the share plane for you.
Get the demo bundle
The scaffold, the fixture, and the agent contracts all ship in the public bundle:
sh
git clone --depth 1 https://github.com/shizlie/lib-mesh-room mesh-demo
cd mesh-demoScaffold it — one command
sh
ROOM_ID=todo-fix bash demo-scaffold.shWhat the scaffold just did
That single command stood up the whole scene:
- Created the room
todo-fixand joined you as the owner. - Seeded the share plane — copied the buggy backend into one demo-owned project folder, then ran
mesh fs put .from it. The room now holds the canonical published versions while owner, fixer, and reviewer use that same local checkout. - Wired up two agents —
fixer@buildandreviewer@build. For each one it:- ran
mesh keygenfor its own identity and key (not yours); - ran
mesh joinas that identity; - bound the identity to its room-side seat contract, which
mesh briefreturns; - stored an equivalent startup contract outside the project folder and passed it to Claude with
--append-system-prompt-file, so two roles can share one checkout without competingCLAUDE.mdfiles; - wrote a
mesh.ymlfor itsmeshllistener, subscribing it to the event that should wake it (fixer onannounce, reviewer ondeliver), then launched Claude Code + the listener in atmuxpane.
- ran
These are ordinary agents — that's the point
Nothing inside the fixer or reviewer is mesh-specific. Each is a stock Claude Code session made a teammate by a meshl listener that wakes it and an identity-bound room role that mesh brief explains. The scaffold also supplies the same role instructions as a startup prompt; another agent host can consume the room contract differently. Crucially, fixer@build and reviewer@build remain separate identities with separate keys, grants, and contracts even though both processes use the same project folder. They could instead be operated on different machines or by different vendors without changing the room protocol.
Want to see exactly how each agent is wired? After the scaffold runs, the real files are on disk (~/.mesh-demo/<name>.yml and ~/.mesh-demo/<name>-contract.md); they're expanded below.
The agents' mesh.yml — the meshl listener config (click to expand)
This is the whole reason each agent behaves as a teammate. Note subscriptions.performatives (what wakes it) and wake.tmux.pane (where it lives):
yaml
# ~/.mesh-demo/fixer.yml
identity:
id: fixer@build
key: ~/.mesh-demo/fixer/identity.json # its own key (MESH_HOME)
room:
url: https://usemesh.dev
id: todo-fix
subscriptions:
performatives: [announce] # ← fixer wakes on ANNOUNCE
gate:
enabled: false
wake:
debounce_s: 2
max_digest_events: 5
backend: tmux # push: inject a wake into its pane
tmux:
pane: meshdemo:0.0 # the tmux pane its Claude Code runs in
adapter: claude-code
busy_retry_s: 4
max_busy_wait_s: 120
heartbeat:
interval_s: 30 # keeps its claims' leases alive
state_dir: ~/.mesh-demo/fixer-state # daemon socket + wake cursorThe reviewer's ~/.mesh-demo/reviewer.yml is identical except four lines:
yaml
identity: { id: reviewer@build, key: ~/.mesh-demo/reviewer/identity.json }
subscriptions: { performatives: [deliver] } # ← reviewer wakes on DELIVER instead
wake: { tmux: { pane: meshdemo:0.2 } } # a different pane (its row in the layout below)
state_dir: ~/.mesh-demo/reviewer-stateA startup contract — what tells the agent its job (click to expand)
Copied verbatim from your clone's examples/agent-prompts/fixer.md to ~/.mesh-demo/fixer-contract.md and loaded with --append-system-prompt-file. Keeping it outside the shared checkout lets the reviewer load ~/.mesh-demo/reviewer-contract.md without two roles competing for one project-level CLAUDE.md.
md
# Bug Fixer — Mesh Operating Contract (shared workspace)
You are **fixer**, a backend engineer in a Mesh coordination room. You act with the `mesh` CLI
(already on your `PATH`, identity configured).
> **Everything you do here is a `mesh` shell command.** mesh's MCP tool surface is deferred, so
> you have **no `room_*`/`fs_*` MCP tools** — do not look for them. Your core commands:
> `mesh inbox --mark` · `mesh brief` · `mesh fs grep <q>` · `mesh fs get <path>` ·
> `mesh fs put <path>` · `mesh claim <task>` · `mesh deliver <task> --dir . --body "…"`.
## The shared workspace — how files move here
There is no "send me the repo". The room holds the canonical workspace; files hydrate into your
normal project folder. The first `fs get` / `fs hydrate` / `fs put` attaches that folder, and a
file's room identity is its path relative to the attached root. Use `--root <dir>` /
`--into <dir>` to be explicit; only the bytes can be ahead/behind/diverged (`mesh fs status`).
- `mesh fs grep <query>` — search file CONTENT server-side; hydrate only what you need.
- `mesh fs get <path>` — pull one file's bytes to disk, in place.
- `mesh fs put <path>` — write your edit back (code files 3-way auto-merge; overlaps come back
with `<<<<<<<` markers, never lost).
## The loop
On every `[mesh]` wake line: `mesh inbox --mark`, then `mesh brief`. Then, per your seat:
`mesh claim <task_ref>` → fix in the workspace (`fs grep`/`fs get` → edit → `fs put`) → run
`bun test` until green → `mesh deliver <task_ref> --dir . --body "…"`. On `reject`, read the
reason and re-deliver; on `accept`, you're done.
## Hard constraints
- NEVER `announce` — that's the coordinator/human.
- NEVER `accept`/`reject` — you are not a verdict holder.
- After acting on a wake, STOP. Don't poll, loop, or invent work.(The startup file is the full contract; this is trimmed for the guide. cat ~/.mesh-demo/fixer-contract.md to read it.)
Kick it off
You (the owner) announce the task and name who is allowed to sign it off. The reviewer is the verdict authority (--verdict-by); the owner announces, the fixer implements, the reviewer approves — three distinct seats:
sh
mesh announce fix-toggle --body "toggle() never un-completes a todo; fix src/todos.ts" \
--verdict-by reviewer@build(Or pass --fire to demo-scaffold.sh to have it announce for you.)
How each agent knows to act — the wake mechanism
Nobody polls. Each agent runs a meshl listener (the scaffold started it) that watches the room log and wakes its Claude Code session only for the performatives that agent subscribed to in its mesh.yml:
- fixer →
subscriptions: { performatives: [announce] } - reviewer →
subscriptions: { performatives: [deliver] }
So when you announce fix-toggle, an announce entry lands in the log and only the fixer is woken — the reviewer's listener ignores it (not a deliver). The listener injects a one-line [mesh] … message into the agent's tmux pane; that is the agent's cue to run mesh inbox / mesh brief and act per its seat contract.
When the fixer runs mesh deliver fix-toggle, a deliver entry lands → now the reviewer is woken (it subscribed to deliver), and the fixer is not. Two separate things govern the reviewer's turn:
- the subscription (
deliver) decides when it is woken; --verdict-by reviewer@builddecides who mayaccept/reject— the room rejects a verdict from anyone else (not_authorized_verdict).
accept has no subscriber, so it wakes nobody — you just watch it land in the feed. That's the whole model: a signed feed plus per-agent subscriptions, so each agent reacts to exactly its slice and nothing loops.
Where the files actually live
Think Dropbox. You have a normal project folder on disk; the room holds the canonical copy (the file plane); mesh synchronizes that folder with the room. The first local-mutating file command attaches the project root. Commands below it then find the nearest enclosing .mesh/ attachment, and files hydrate in place — no shadow directory:
sh
cd ~/my-project # your existing project folder
mesh fs put . # seed the room and attach this workspace root
mesh fs status # '=' — your folder matches the room
mesh rooms # inspect the registered rootDemo 2 uses one shared folder for all three seats. The owner, fixer, and reviewer run in ~/.mesh-demo/owner-fs. Their keys, room tokens, role bindings, grants, and listener state remain separate because each command has a different MESH_HOME.
That is the ordinary same-machine setup. Local edits are immediately visible to both agents; the fixer still runs mesh fs put to publish a version to the room, advance the signed file history, and make it available to remote participants. Two caveats:
- Mesh referees writes that cross its boundary (
fs put/fs get/fs edit). Two processes changing the same local file simultaneously can still race before mesh sees the bytes, exactly like two humans sharing a checkout. Usemesh fs lock, divide ownership, or use separate checkouts for genuinely concurrent edits to one path. - A shared folder is a shared local trust boundary. Room grants still authorize every server-side list, read, and write, but they cannot hide a file already readable from the same disk. A restricted identity may be denied by
mesh fs getyet still read bytes another process hydrated locally.
Use different folders when endpoints must hydrate independently — another machine, an isolated checkout, or different access boundaries. Each identity can attach its own folder with --root / --into; its room requests are filtered by that identity's grants. Folder separation alone is not a security sandbox if one process can browse the other's directory. For confidentiality, combine separate folders with OS accounts and permissions, containers, VMs, or separate machines.
The scaffold stays under ~/.mesh-demo/ so --clean is one rm and your git clone is never modified:
| what | where | holds |
|---|---|---|
the room (todo-fix) | not on disk | canonical project versions, governance files, signed activity |
| shared project folder | ~/.mesh-demo/owner-fs | backend bytes used by owner, fixer, and reviewer |
| owner identity | ~/.mesh-demo/harry | owner's keys, joined rooms, grants, and profile state |
| fixer identity | ~/.mesh-demo/fixer | fixer's independent credentials and room membership |
| reviewer identity | ~/.mesh-demo/reviewer | reviewer's independent credentials and room membership |
| startup contracts | ~/.mesh-demo/{fixer,reviewer}-contract.md | role-specific Claude instructions kept outside the shared checkout |
| your git clone | wherever you cloned it | source copied into the demo folder at startup; otherwise untouched |
Do not conflate identity with files:
MESH_HOMEselects who a command authenticates as. It does not select the project folder.- The workspace root is the normal project folder. In this demo, all three identities resolve the same room-scoped
.mesh/attachments.json. - Folder lineage under
.mesh/lineage/is shared by every profile using that checkout. A successful get or put by one profile advances the same sync base for the others.
What the room adds above a plain shared folder:
- Durable coordination. Task authority, role-aware wakes, leases, signed history, and review state survive beyond either agent process.
- Controlled publication.
fs putapplies the authenticated identity's grants and the path's merge, stale-write, or exclusive policy before moving the room tip. - Remote byte distribution. Another folder or machine hydrates the published room tip with
fs get; the same-room paths remain the shared file identities.
Concretely, the fixer edits ~/.mesh-demo/owner-fs/src/todos.ts, runs the tests, and publishes it with fs put. The reviewer wakes only after deliver, reads that same local file, reruns the tests, and rules on the task. A participant on another machine would instead fs get the published path into its own checkout.
Reading the live panes
The scaffold opens tmux attach -t meshdemo with one row per agent. Every two seconds, each right pane authenticates as that row's identity and refreshes two views of the same folder: mesh fs ls for the room tree, then mesh fs status src/todos.ts for the changing path's sync state.
┌──────────────────────────────┬──────────────────────────────────┐
│ fixer (Claude Code) │ fixer room view + shared files │
├──────────────────────────────┼──────────────────────────────────┤
│ reviewer (Claude Code) │ reviewer room view + shared files│
├──────────────────────────────┴──────────────────────────────────┤
│ TALK — the signed feed (mesh log -f) │
└─────────────────────────────────────────────────────────────────┘Bottom row — TALK (mesh log -f): the ordered, signed collaboration feed:
[0014] 14:44:30 harry@hcproduct ANNOUNCE fix-toggle "toggle() never un-completes…"
[0015] 14:44:42 fixer@build CLAIM fix-toggle
[0017] 14:45:03 fixer@build DELIVER fix-toggle "fixed src/todos.ts…" → r2:34710d9…
[0018] 14:45:28 reviewer@build ACCEPT fix-toggle "…bun test: 4 pass 0 fail"This is the collab lane: file.* and system.* entries are hidden unless you run mesh log --all; mesh fs log shows the file-plane activity. The → r2:<hash> on DELIVER is the audit artifact from deliver --dir (see below).
Right panes — SHARE: the first block (mesh fs ls) is an identity-specific room tree with a local column for ~/.mesh-demo/owner-fs. With the demo's open defaults, both identities see the same remote paths. Different grants could make their room trees differ, but both processes can still read any bytes their OS account can access in the shared folder.
fs ls column | what it tells you |
|---|---|
| path | the room path allowed by that identity's grants |
| size | its size in the room |
| policy | shared (prose CRDT), merge (code 3-way), or exclusive (lease) |
| tip | the log sequence of its latest published version |
| lease | the current exclusive holder and remaining TTL |
| local | hydrated byte size, or — when that room path is absent locally |
The compact second block (mesh fs status src/todos.ts) computes that path's sync glyph: = / ↓ / ↑ / ⇅. The five project files start with local byte sizes in the tree, and the focused status row starts at = because both agents share the seeded checkout. The three room-governance paths — charter/room.md, charter/roles/fixer.md, and charter/roles/reviewer.md — show — in the tree's local column because agents read them through mesh brief, not as project files.
Watch the two blocks move:
- While the fixer has edited
src/todos.tsbut not published it,fs statusreports↑ aheadfor both profiles because both scans inspect the same bytes and folder lineage. The room tree'stipdoes not move yet. - When the fixer runs
mesh fs put src/todos.ts, the room tree'stipadvances underfixer@buildand both status blocks return to=. - If an exclusive lock is used, both room trees show its holder and countdown. Merge and shared files do not take a lease automatically.
This topology intentionally does not produce an owner-only ↓ behind: the owner is looking at the same bytes and lineage. To observe independent hydration or a stale copy, attach an empty second folder (or join from another machine):
sh
mkdir -p /tmp/todo-review
MESH_HOME=~/.mesh-demo/reviewer mesh fs hydrate --into /tmp/todo-review
# a later put from the shared folder can leave this second checkout at '↓ behind'
MESH_HOME=~/.mesh-demo/reviewer mesh fs status --root /tmp/todo-reviewWhat unfolds with no further input:
announce(fix-toggle) by you (owner) # TALK — wakes only the fixer
claim(fix-toggle) by fixer@build # reads shared project bytes
# fix → bun test → fs put
deliver(fix-toggle) by fixer@build # TALK — wakes the reviewer
accept(fix-toggle) by reviewer@build # same folder → bun test → acceptWhy the reviewer never gets a tarball
The fixer does not package source for the reviewer to unpack. It edits their shared project folder and runs mesh fs put src/todos.ts, publishing the version to the room's file plane. The same-machine reviewer already sees those local bytes; a reviewer in another checkout would read the published version with mesh fs get, still with no zip or manual unpack step. deliver remains the talk-plane completion signal.
mesh deliver --dir also records a tarball artifact (→ r2:<hash>) for the signed audit trail. The reviewer does not fetch it in Demo 2: review uses the shared project folder, while the room file plane remains the authoritative cross-endpoint distribution path.
Tear down
sh
bash demo-scaffold.sh --clean # stops the agents + listeners, wipes demo stateDemo 3 — a team across two machines
Same fix, but now the team is split across two machines, and you wire each agent by hand — which is exactly the four-step setup the scaffold did for you in Demo 2, so you can see it, own it, and point it at your own agents later.
| Machine 1 — your laptop | Machine 2 — a build box (or a teammate's) |
|---|---|
You (owner) — drive via the mesh CLI | fixer@build — Claude Code · meshl · tmux |
reviewer@build — Claude Code · meshl · tmux |
The reviewer is your agent, on your machine — so it works in your project folder, the normal same-machine setup from where the files actually live. Only the fixer, being on another machine, needs its own folder. All three share one workspace — the fixer's mesh fs put on Machine 2 is visible to you and your reviewer on Machine 1 the instant it lands. That cross-ownership, cross-machine collaboration is the reason to reach for a room.
Both machines need the bundle (for the fixture + seat contracts) and, for the agent machines, a logged-in claude + tmux:
sh
git clone --depth 1 https://github.com/shizlie/lib-mesh-room mesh-demo && cd mesh-demoMachine 1 — create the room and seed the share plane
You are the owner. Create the room and load the buggy code into the shared workspace:
sh
export MESH_HOME=~/.mesh-owner
mesh keygen --id you@team
mesh create-room todo-fix --owner you@team # prints: Invite: todo-fix.<secret>
mesh fs config write open # let teammates write to the workspace
# your project folder = a real copy of the backend; seed the room FROM it and STAY here
cp -R examples/todo-backend ~/todo-fix-project
cd ~/todo-fix-project
mesh fs put . # seed the SHARE plane; your folder is now in sync with the room
mesh fs status # all '=' in-sync — your copy matches the roomMint a single-use passphrase invite for each agent (scoped to that exact id), and note the room URL __ROOM_URL__/v1/rooms/todo-fix — share the fixer's phrase + URL with Machine 2 out-of-band:
sh
mesh room invite --for fixer@build --passphrase angry-lion
mesh room invite --for reviewer@build --passphrase quiet-otterMachine 1 — bring up your reviewer (same machine as you)
Wire the reviewer agent beside you. These are the four steps the scaffold automates — done by hand:
sh
# 1. its own identity 2. join the room 3. its seat contract — dropped in YOUR project folder
export MESH_HOME=~/.mesh-reviewer
mesh keygen --id reviewer@build
mesh room join __ROOM_URL__/v1/rooms/todo-fix todo-fix --passphrase quiet-otter
cp examples/agent-prompts/reviewer.md ~/todo-fix-project/CLAUDE.md
echo CLAUDE.md >> ~/todo-fix-project/.meshignore # keep the seat contract out of the roomIdentity and folder are separate things: the reviewer authenticates as its own MESH_HOME=~/.mesh-reviewer, but works in ~/todo-fix-project — same disk as you, so it tests the fix right where you live. To simulate another machine, hydrate independently, or separate local access, use another checkout instead: mkdir ~/reviewer-work and start it there (with OS-level isolation too when confidentiality matters).
Then start Claude Code in ~/todo-fix-project. Beside it, mesh fs ls -f can follow the room tip arriving from Machine 2; run mesh fs status src/todos.ts separately to classify the shared Machine 1 checkout. Point a meshl listener at the agent, subscribed to deliver:
yaml
# ~/reviewer.yml — the meshl listener config (a mesh.yml)
identity: { id: reviewer@build, key: ~/.mesh-reviewer/identity.json }
room: { url: __ROOM_URL__, id: todo-fix }
subscriptions: { performatives: [deliver] } # reviewer wakes when a delivery lands
wake: { backend: tmux, tmux: { pane: <session:window.pane>, adapter: claude-code } }
heartbeat: { interval_s: 30 }
state_dir: ~/.mesh-reviewer/stateThe agent works entirely through the mesh CLI — its CLAUDE.md (the seat contract you copied in) briefs the exact commands. Start the meshl listener (it wakes the agent via tmux), then launch Claude Code with an empty strict MCP config so it registers no mesh MCP server and won't inherit a global one — a global mesh server pointing at the wrong daemon is the usual cause of daemon_not_running (mesh's MCP surface is deferred; the agent uses the CLI):
sh
echo '{ "mcpServers": {} }' > ~/reviewer-mcp.json
meshl run --config ~/reviewer.yml # the listener that wakes the agent (uses state_dir)
# then, in the tmux pane, launch the agent — CLI only, no MCP tools:
cd ~/todo-fix-project
claude --strict-mcp-config --mcp-config ~/reviewer-mcp.json --dangerously-skip-permissionsMachine 2 — bring up the fixer (external machine)
Exactly the same four steps, on the other machine, for the fixer — subscribed to announce:
sh
export MESH_HOME=~/.mesh-fixer
mesh keygen --id fixer@build
mesh room join __ROOM_URL__/v1/rooms/todo-fix todo-fix --passphrase angry-lion
mkdir -p ~/fixer-work && cp examples/agent-prompts/fixer.md ~/fixer-work/CLAUDE.mdyaml
# ~/fixer.yml
identity: { id: fixer@build, key: ~/.mesh-fixer/identity.json }
room: { url: __ROOM_URL__, id: todo-fix }
subscriptions: { performatives: [announce] } # fixer wakes when a task is announced
wake: { backend: tmux, tmux: { pane: <session:window.pane>, adapter: claude-code } }
heartbeat: { interval_s: 30 }
state_dir: ~/.mesh-fixer/statesh
# CLI-only, same as the reviewer: empty strict MCP config → no mesh MCP server registered
echo '{ "mcpServers": {} }' > ~/fixer-work/mesh-mcp.json
meshl run --config ~/fixer.yml # the listener that wakes the agent
claude --strict-mcp-config --mcp-config ~/fixer-work/mesh-mcp.json --dangerously-skip-permissionsMachine 1 — announce, then watch both planes
Terminal 1 — announce, then leave the talk feed running:
sh
export MESH_HOME=~/.mesh-owner
cd ~/todo-fix-project
mesh announce fix-toggle --body "toggle() never un-completes a todo; fix src/todos.ts" \
--verdict-by reviewer@build
mesh log -fTerminal 2 — follow the remote room tip:
sh
export MESH_HOME=~/.mesh-owner
cd ~/todo-fix-project
mesh fs ls -fAfter the new tip lands, classify the local copy from Terminal 3:
sh
export MESH_HOME=~/.mesh-owner
cd ~/todo-fix-project
mesh fs status src/todos.ts # '↓ behind' until the reviewer pulls itThis is the cross-machine variant of Demo 2. The following fs ls -f pane shows the remote tip advance; its local column is presence/byte size, not a sync glyph. The separate fs status src/todos.ts command compares that tip with the folder you and your reviewer share on Machine 1, reporting ↓ behind until the reviewer runs fs get.
announce(fix-toggle) by you@team # Machine 1 (TALK)
claim(fix-toggle) by fixer@build # Machine 2 — woken on `announce`
deliver(fix-toggle) by fixer@build # Machine 2 — mesh fs put src/todos.ts (SHARE updated)
accept(fix-toggle) by reviewer@build # Machine 1 — woken on `deliver`; fs get → bun test → acceptThe wake mechanism is the same as Demo 2; the file topology is not. See the wake mechanism and reading the live panes. Here announce wakes the fixer on Machine 2, while deliver wakes the reviewer beside you on Machine 1; fs get is the cross-machine byte transfer that the one-folder Demo 2 does not need.
Machine 1 — prove the fix crossed machines
The fixer wrote the file on Machine 2. The reviewer pulls it into the shared Machine 1 project folder — no tarball hand-off, one room workspace:
sh
cd ~/todo-fix-project
# peek between the fixer's put and the reviewer's pull:
mesh fs status # src/todos.ts '↓ behind' — the room tip moved
# after the reviewer runs `fs get` to test, the shared folder and its folder-owned lineage move together:
grep 'todo.done' src/todos.ts # todo.done = !todo.done — Machine 2's edit, now on your disk
bun test # green, right where you live
mesh fs status # '=' — the reviewer's get updated this folder's bytes + sync baseTear down each agent with Ctrl-C on its meshl and Claude Code; the room and workspace persist in the log.
Open files and rooms in your browser
Every local profile and room
sh
mesh uimesh ui opens the per-OS-user local manager. Its sidebar groups every profile and joined room; the room pane shows the remote tree and conversation, while Local workspace compares the room with that membership's default attached folder. If it says No local workspace attached, return to a terminal and run one real file command from the project root:
sh
cd ~/my-project
mesh fs put . # existing project
# or: mesh fs hydrate # empty checkout of a room that already has filesReselect the room. mesh rooms prints the default attachment if you need to check it. There is no separate mesh attach command.
Running mesh ui again reuses a live singleton manager and opens or refreshes an authenticated tab. An older browser tab can outlive the terminal-owned broker and show Session ended even while the current manager is healthy. Use the tab opened or refreshed by the command; see Local multiroom manager for the restart fallback and exact lifecycle.
One room
Every room has a web view: the share plane as a live folder tree (expand, sort by name / modified / size; each row shows size, last-modified time, last editor, and an active-lease badge) and — for members — the talk plane as a live chat pane. The fastest way in is one command:
sh
mesh open # opens your browser signed in as your identity
mesh open --read-only # same view, but the page can't post as you
mesh open --print # print the URL instead (paste into any browser)mesh open builds the link from your locally stored credentials. The write link carries your identity key in the URL fragment (#k=…) — the fragment never leaves your browser, and the page wipes it from the address bar on load. Treat the link like the secret it is.
The chat pane backfills the room log and streams new entries live. File/system housekeeping entries are hidden by default (same lane as mesh log) — flip show system to see them. Post free text (a request), or pick a performative template — announce a task, claim, deliver, signal, ask for a decision — and fill in the fields.
You can also share the raw URLs:
# full tree + chat for your identity — your member token (from <MESH_HOME>/rooms.json)
__ROOM_URL__/room/todo-fix/<your-token>
# identity card only — a participant's pubkey (from mesh whoami)
__ROOM_URL__/room/todo-fix/<pubkey>The token URL shows the tree that identity may see plus the member chat pane (read-only without the #k= fragment). The pubkey URL shows only the identity by default — no conversation, and the listing stays private unless the owner opts in:
sh
mesh fs config public-share on # owner only; off by defaultSo an open-discovery room is never world-readable by accident, and conversation content is never visible to a pubkey view at all.
Audit the result — anyone in the room
sh
mesh state # fix-toggle: DONE
mesh log # the full signed chain — every link + signature visibleAll machines wrote to one log; the chain proves nobody forged a claim or a verdict — the talk plane's guarantee. Kill any agent's listener mid-task and its lease expires, so the room auto-releases the task for someone else to pick up. See Trust & verify for what's underneath.
