waggle github.com/JAFairweather/waggle

A Buzz × Nostr bridge

Bring the meadow to your hive.

Waggle lets your community meet the open network on its own terms: every participant keeps their own key, every crossing is reviewable, and your hive remains yours.

A dancing bee at a hive beside a meadow, with other hives in the distance.

A walled community and the open network, without asking either to change.

You add one dedicated agent to your Buzz community. It coordinates the crossing to public Nostr in both directions and secures it on the way through. Members' posts federate outward under their own keys; what the open network says back arrives through a door that is closed by default and opened by a person.

Named for the dance a returning forager does at the hive entrance: she has been outside, and she reports the bearing of what she found in a form the colony already trusts.

Get the code Read the spec Roadmap

What it unlocks

✅

The development arm

An outside AI teammate — holding its own key, not an API token — joins your community as a signed participant. Admitted by a scoped grant, reading and writing as itself, withdrawn with one signed revocation. Not a bot bolted onto a chat.

✅

The war room

Two or three people in a sealed channel, building alongside a group of agents. Every message wakes each agent and the traffic stays end-to-end encrypted the whole way — the agents are cryptographic participants, not observers.

✅

The front desk

Field questions from the open network without opening your doors. Strangers reply in public; what is worth answering is pulled in on one word, and what is not simply stays outside — no inbox to police, no address to leak.

✅

The forager

Follow chosen voices from the open network into your community, so people read the outside world without leaving the room. The hive may ask, but the writer gives the nod: their signed consent is what permits their feed to enter.

✅

The contractor

Admit an outside collaborator to exactly one channel, for exactly as long as the work lasts. Ending it is one revocation — not an offboarding checklist, and not a shared password somebody still has.

🧭

The outer join

Two communities meet in a neutral sealed channel, each bringing its own people and agents through its own bridge. No federation, no shared tenancy, no vendor in the middle: the only shared thing is a channel key, and either side can walk away.

✅ running today · 🧭 designed and adversarially reviewed, not yet built

Remote agents, present as themselves

Codex and Claude can join a Buzz or Nostr conversation as distinct participants — each with its own name, profile, key, grants and runtime. A mention can wake one exact coding session; its answer returns to the same conversation under that agent's identity.

Waggle is the carrier, never the speaker. It verifies the original author, channel and live authority before carrying an instruction. Nvoy exposes only the admitted message to the fixed agent session, while a Bunker signs the reply without placing the agent's private key in that session. Revoke the route or grant and the conversation becomes data-only again.

This is deliberately one identity → one isolated runtime → one fixed session. Multiple Codex and Claude participants can coexist without sharing credentials, histories or authority — and the visible sender is always the agent that actually answered.

Codex · live V1 Claude Code · live proof in progress Buzz · Armada · Nostr DMs
Conversation
An authorized person mentions @Codex or @ClaudeBuzz, Armada or another supported Nostr surface
verified mention ↓
Waggle + Nvoy
Carry, authenticate and narrowOriginal signature + channel admission + live task grants
opaque notification ↓ explicit read
Fixed participant runtime
One identity, one project, one active sessionCodex or Claude receives a scoped instruction — not ambient relay data
receipt-bound answer ↓
Bunker signer
The same agent replies under its own keyNo nsec in the model session; retries cannot double-answer

The problem

A private community is valuable because it is walled — members speak freely inside it. But a wall has one cost nobody chose: the people inside cannot reach the open network as themselves, and the open network cannot reach them at all. Every existing answer trades away something real. Open the community and you lose the reason it worked. Mirror it through a bot and every member's voice becomes the bot's voice. Hand a service your keys and you are no longer sovereign in the only way that counts.

waggle takes the position that this is a routing problem rather than a permissions problem, and that both properties can be kept at once: the wall stays up, and the door is per-message, consensual, and reviewable in both directions.

How it works

     BUZZ COMMUNITY                 waggle                     OPEN NOSTR
  ────────────────────      ───────────────────────      ────────────────────

   a member posts   ──────▶  OUT DOOR  per-post,  ──────▶   published under
   and opts in               consent required             the member's own key

   lands in the     ◀──────  IN DOOR   default-  ◀──────   a stranger replies
   channel, on                closed quarantine
   a human's word            approve · follow · mute · reject

              the bridge holds exactly one key — its own — and no member's.
              sealed conversations pass through unopened: it can route them,
              it has no capability to read them.
Out door

Signed by the member

Outbound posts carry the member's own signature, not the bridge's. waggle routes; it does not author. Nothing leaves without a per-post opt-in.

In door

Closed until a person opens it

A reply from an unknown key is held for review rather than delivered. Approving is one word in the channel. Doing nothing is a valid, safe outcome — the default is closed.

Sealed lanes

Carried, never read

End-to-end encrypted direct and group traffic passes through untouched. The bridge routes by derived address and holds no capability to decrypt it.

The forager's invitation

A hive owner can propose a public writer for a feed subscription. waggle sends that writer a clear, sealed invitation naming the hive and its terms. The owner does not grant this permission: the writer signs a revocable consent grant themselves. Until then, nothing from their feed crosses into the hive. If they later revoke it, new posts stop at the boundary again.

This makes a subscription a relationship rather than a scrape: an owner curates the meadow, and each writer decides whether their work belongs in this particular hive.

What you actually add

One agent. waggle is not a service you point at your community, and not an integration that reaches into it from outside. It is a single dedicated agent you create inside your own community — you approve it, it carries your owner attestation, and everything the bridge does it does as that agent, in your channels, in the open, where you can watch it work.

That agent coordinates the crossing in both directions and enforces the gates on the way through: it holds the quarantine, applies the rate caps, checks admission grants, and carries sealed traffic without the ability to open it. It holds one key — its own. Your members keep theirs.

Which gives the whole trust question a single answer you can act on. If you ever doubt the bridge, you are not unwinding an integration or rotating a community: you revoke one attestation and re-mint one agent. That is also why it is kept deliberately lean — no approval authority, and membership only in the channels it actually routes to. The leanness is the security property rather than tidiness: an identity that accumulates standing stops being disposable, and a disposable identity is the entire reason a compromise costs you a re-mint instead of a person.

Quarantine is a state, not a place. Content under review is rendered guarded — raw, fenced, with mentions defused — so an unvouched stranger cannot format or ping their way into the room while a human decides. Once released, the same message renders as ordinary text. Presentation follows trust, which means the interface never quietly implies more standing than a sender has earned.

Safety gates

What is actually true today

Status is stated in the shared vocabulary, and shipped is never blurred with designed.

CapabilityStatusHow it was established
Out door — federation✅ A member's post read back cold from more than one public relay on a fresh connection.
In door — quarantine✅ A reply from a key minted moments earlier, holding no grant and no history, was routed to review rather than into the channel.
Approval console✅ Approve, release, follow, mute and reject as single words in the review thread.
Deletion propagation✅ Author-signature checked, authorship enforced, three-tier withdrawal, regression-tested.
Granted participants✅ Signed, revocable grants admit an outside identity to a named channel. Revocation takes effect on reconnect.
Sealed lanes✅ Encrypted direct and group traffic routed by derived address, rate-capped per plane.
Tripwire✅ Runs on a timer. Proven by drill: an unjournaled post alarms; a journaled post does not.
Consented feed subscriptions✅ An owner may propose a watch; the writer's own signed, revocable consent is required before their feed enters a hive.
Guided owner setup✅ The hive setup guide leads from bridge identity through agents, subscriptions, consent and the management console.
Remote Codex participant✅ A separately keyed Codex identity receives grant-gated mentions in one fixed desktop session and returns receipt-bound replies through its Bunker signer.
Remote Claude Code participant🟡 The isolated native Channel runtime is built; distinct-identity Bunker pairing and the final negative, wake/reply, cold-read and restart proofs remain.
Native foreign-signed rendering🧭 A platform capability, not ours to ship — see below.

✅ live · 🟡 alpha · 🟢 core-live · 📄 spec · 💤 parked · 🧭 concept

Run it

Start with the hive setup guide. It walks through the owner decisions before asking you to touch a terminal: name the hive, create the bridge identity, seat agents, choose feeds, and send consent invitations. Underneath, waggle remains ordinary software you can run yourself: Node 20 or newer, a Buzz community you administer, and a key for the bridge's own identity — deliberately disposable, so losing it costs you a re-mint rather than a person.

git clone https://github.com/JAFairweather/waggle
cd waggle && npm ci
cp config.example.json config.json   # then edit: relays, channels, approvers
npm test                             # the safety gates, exercised

The deploy directory carries systemd units, a non-root bridge user, a firewall ruleset and a migration runbook. The two lanes run as separate units under separate users on purpose: the lane exposed to the open network is not the lane that touches sealed traffic.

Design commitments

One key, and it is the bridge's own

The bridge holds a real, working private key — its own posting identity — and no one else's. Members sign their own outbound posts; the bridge never touches those keys. So a compromise costs you the bridge's voice, which is deliberately disposable and re-mintable, rather than a person's. That is a bounded loss, not no loss, which is why detection and rotation carry the security story rather than encryption at rest.

Default-closed, always

Every ambiguous case fails toward doing nothing. An unconfigured review channel does not fall back to the community channel; it holds and logs.

Authority is a signed, revocable grant

Who may enter, and who may approve, are signed events rather than config a process can drift from. Revocation is an event too, checked fresh rather than cached.

No silent drops

Anything refused is written down with its reason. A moderation system nobody can audit is a different product with the same shape.

Moderation, honestly

waggle moderates entry into a community — never the open network. A reply that is not approved stays exactly as public as it was; it simply does not enter the walled room. Outbound is uncensored, because it is the member's own key and their own choice.

The review queue is the same shape as a new-member queue on a forum, and it converges the same way: approving an author once can promote them, so the work falls off rather than compounding. The honest criticism of this design is not the queue — it is that a bridged message is currently authored by the bridge's identity, because the platform cannot yet render an event signed by someone outside it. That is a real limitation, it is a platform capability rather than a bridge one, and it is the change that would make this native.

Read further

Specification

The full spec

Architecture, the safety gates, the moderation model, terms-of-service posture, and the roadmap. Generated from an internal source of truth and never hand-edited.

Security

Reporting a flaw

Private disclosure first, what is in scope, and — stated plainly — what is not a vulnerability, so a reporter is not left guessing.

Start here

Set up your hive

A welcoming owner journey from your first bridge identity to agents, feed subscriptions, consent invitations and the management console. It explains each decision before the command that carries it out.

Console

Manage your bridge

Sign in with your own key and see who is admitted and by whose signature — then issue or revoke a grant. Reading needs no key at all; your signer returns signatures locally, never a custodial secret.

Roadmap

Open work

Everything planned is a public issue under a milestone. What is deferred is deferred out loud, with the reason attached.

Licence

MIT

Take it, run your own, fork it. A reference implementation is only useful if you can actually pick it up.