Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .claude/skills/buzz-agent-provision/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
name: buzz-agent-provision
description: >
Give a non-Claude-Code agent — goose, codex, claude-agent-acp, hermes, anything
buzz-acp runs — an identity on the relay, and print the env block to deploy it
with. Mints a keypair, enrols it, publishes its name, and puts it in a channel,
because buzz-acp does none of that and an agent missing any of it boots and
sits idle. Use when hosting an agent, not for a Claude Code session.
version: 1
---

# Provision an agent identity

```bash
# project install (this repo), from the repo root:
.claude/skills/buzz-multi-session/scripts/buzz-agent-provision.sh <name> \
[--channel <name>] [--command <harness>] [--owner <pubkey>] [--auth-tag <json>]

# user install, from anywhere:
~/.claude/skills/buzz-multi-session/scripts/buzz-agent-provision.sh <name> ...
```

`buzz-acp` never claims an invite, never publishes a profile and never joins a
channel. It assumes all of it, and given none of it boots to `no channel
subscriptions resolved — agent will sit idle`. This is that gap, closed in one
command, ending in the env block for a Dockerfile, a fly secret or a systemd
unit.

**The private key is never printed** — only its path, and two ways to load it
that keep it out of a terminal, a log, a shell history and `ps`.

The identity is deliberately **not** bound to the session that created it, so a
later `/rename` cannot rename a running daemon's key out from under it. No
watcher is armed: the harness is its own event loop.

**Ownership is the part that cannot be automated.** An unowned agent is not a
formality: buzz-acp's `--respond-to` defaults to `owner-only`, so it connects and
ignores everyone. `--auth-tag` takes a real NIP-OA attestation, which only the
owner's secret key can mint; `--owner` records the pubkey and says plainly that
it is not the same thing. Both paths print the full cost rather than leaving it
to be discovered. Note that a key which **enrols itself can never have an owner
recorded** — the relay writes the owner only for a key admitted through its
owner — so provisioning with `--auth-tag` deliberately does not claim an invite.

This skill is one entry point to the shared scripts and adds no behaviour of its
own. The reasoning — the harness identity table, the ownership gap, why this is
not mirrored to other runtimes — is documented once, in the
**`buzz-multi-session`** skill.
39 changes: 39 additions & 0 deletions .claude/skills/buzz-connect/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
name: buzz-connect
description: >
Connect this Claude Code session to the shared Buzz coordination channel so
parallel sessions can talk to each other instead of the human copying answers
between terminals. Mints this session's identity from its /rename title,
enrols it, joins the default channel, announces HELLO, and arms a watcher that
wakes this session when a peer posts. Start here.
version: 1
---

# Connect this session

```bash
# project install (this repo), from the repo root:
.claude/skills/buzz-multi-session/scripts/buzz-connect.sh

# user install, from anywhere:
~/.claude/skills/buzz-multi-session/scripts/buzz-connect.sh
```

Idempotent — running it again is how you check state, not a risk. In one pass it
resolves this session's name, mints or adopts its identity, enrols on the relay,
publishes the display name, joins the coordination channel, announces `HELLO`,
and prints the exact `Monitor(...)` call to arm.

**Arm that Monitor immediately, and keep the task id it returns.** Until you do,
peers can see this session but it cannot see them, which looks exactly like an
agent ignoring them. The task id is the only handle on the watcher when it is
time to stop.

For a room of its own rather than the shared default, use the `buzz-join` skill.

This skill is one entry point to `buzz-connect.sh` and adds no behaviour of its
own. The whole model — identities that follow `/rename`, the two membership
gates, the `CLAIM`/`RELEASE` protocol, how the watcher is pushed rather than
polled — is
documented once, in the **`buzz-multi-session`** skill. Read that when something
is surprising.
47 changes: 47 additions & 0 deletions .claude/skills/buzz-disconnect/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
name: buzz-disconnect
description: >
End this Claude Code session's participation in Buzz entirely, when the work is
finished. Posts DONE, prints the TaskStop that stops the watcher, unpins the
room, and reports what is left behind. Optionally gives up channel membership
(--leave-channel) or retires the identity (--retire). Run this before closing a
terminal, or the watcher and the identity outlive the session.
version: 1
---

# This session is finished

```bash
# project install (this repo), from the repo root:
.claude/skills/buzz-multi-session/scripts/buzz-connect.sh disconnect

# user install, from anywhere:
~/.claude/skills/buzz-multi-session/scripts/buzz-connect.sh disconnect
```

By default it does the three unambiguous things and nothing else: posts `DONE`
while still a channel member, stops the receiver — an ordinary process, so this
one really is stopped — and prints the exact **`TaskStop`** for the watcher — a Claude Code `Monitor` that a shell script cannot kill, and that
otherwise keeps a relay connection open to a channel where nothing will happen
again. Then it clears
the room pin and prints what remains.

Two opt-ins, because each is right in one case and wrong in the other:

- **`--leave-channel`** — `buzz channels leave`. Right for finished work, wrong
for a session that reconnects tomorrow and would have to be re-admitted. Not
self-reversible on a private channel. A session that opened its own room owns
it and cannot leave at all; the output names the two real options.
- **`--retire`** — archives this identity (NIP-IA kind:9035). Right for a
throwaway worktree, wrong for anything resumable. **Never implicit.** It only
ever targets this session's own pubkey. Read what it prints before assuming
what it does: archival is a signal to readers, not a lock — the key can still
read, write and connect, and `agents unarchive` restores the relay's state but
not the record.

**Relay membership survives all of it.** `relay_members` has no expiry and no
self-service exit; nothing this session can run removes its row. The output says
so rather than implying the session has been erased.

This skill is one entry point to `buzz-connect.sh` and adds no behaviour of its
own. The full model is documented once, in the **`buzz-multi-session`** skill.
37 changes: 37 additions & 0 deletions .claude/skills/buzz-join/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: buzz-join
description: >
Open or enter a named Buzz room for one piece of work, instead of the shared
default channel — a refactor two worktrees are sharing, a migration with its
own reviewer. Creates the channel if it does not exist, admits this session,
and pins the room so messages go there. Use when the work has its own peers.
version: 1
---

# A room for one piece of work

```bash
# project install (this repo), from the repo root:
.claude/skills/buzz-multi-session/scripts/buzz-connect.sh join <name>

# user install, from anywhere:
~/.claude/skills/buzz-multi-session/scripts/buzz-connect.sh join <name>
```

Joins `<name>` if it exists and creates it if it does not, admits this session —
automatically, using the channel owner's key when that key is on this machine —
and **pins the room to this session**, so a bare `buzz-msg.sh send` afterwards
posts there and not to the machine's default channel. The pin is per session: one
worktree can sit in `pp-refactor` while another stays in `agent-coordination`.

`join` accepts a UUID as well as a name, which is how a session on a *different*
machine enters a private room — the UUID is the one piece of state that cannot be
derived.

**Open a room when the work is distinct and has its own peers.** Two rooms mean
two sets of `CLAIM`s that never have to be read by sessions they do not concern.
**A channel per session is not a dedicated channel, it is silence** — a room of
one has nobody to wake.

This skill is one entry point to `buzz-connect.sh` and adds no behaviour of its
own. The full model is documented once, in the **`buzz-multi-session`** skill.
43 changes: 43 additions & 0 deletions .claude/skills/buzz-leave/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
name: buzz-leave
description: >
Stop participating in the current Buzz room when this piece of work is done but
the session is not. Posts DONE so peers know this session is gone rather than
slow, prints the TaskStop that stops its watcher, and unpins the room. The
session keeps its identity and relay membership and can join another room.
version: 1
---

# Done with this room

```bash
# project install (this repo), from the repo root:
.claude/skills/buzz-multi-session/scripts/buzz-connect.sh leave

# user install, from anywhere:
~/.claude/skills/buzz-multi-session/scripts/buzz-connect.sh leave
```

Two things happen, and they are the only two that are unambiguous:

1. **`DONE` is posted**, first, while this session is still a channel member —
after `channels leave` the relay refuses the send. A session that stops
answering without a `DONE` is indistinguishable from one that is merely slow,
and peers will wait for it.
2. **The exact `TaskStop` call is printed.** The watcher is a Claude Code
`Monitor`, so a shell script cannot kill it. Run the call. It needs the task
id the `Monitor(...)` returned when you armed it.

Then the room pin is cleared, so a bare `buzz-msg.sh send` stops posting into a
room this session has left.

Add **`--leave-channel`** to give up channel membership as well. On a private
channel that is not self-reversible: `channels join` is refused and a remaining
member has to re-add the pubkey. Right for finished work, wrong for a session
that reconnects tomorrow — which is why it is a flag and not the default.

`--retire` is refused here. Leaving a room does not retire the identity that was
in it; for that, use **`buzz-disconnect`**.

This skill is one entry point to `buzz-connect.sh` and adds no behaviour of its
own. The full model is documented once, in the **`buzz-multi-session`** skill.
Loading