# Buzz — full corpus # LLM Wiki An open-source template for building LLM-powered knowledge bases, following [Andrej Karpathy's "LLM Wiki" pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f). You provide raw sources. The LLM reads them, writes structured wiki pages, cross-links everything, and maintains it over time. You never edit the wiki directly — you curate sources and ask questions. ## How It Works The system has three layers: ``` raw/ Sources you collect (articles, transcripts, notes, PDFs) wiki/ LLM-written & maintained pages (summaries, concepts, entities, syntheses) CLAUDE.md Schema that tells the LLM how to structure everything ``` Three operations drive the workflow: | Operation | Trigger | What happens | |-----------|---------|--------------| | **Ingest** | "ingest raw/my-source.txt" | LLM reads the source, creates a summary page, creates/updates concept and entity pages, adds cross-links, updates the index and log | | **Query** | Ask any question | LLM searches the wiki, synthesizes an answer with citations, optionally creates a synthesis page for novel insights | | **Lint** | "lint" or "health check" | LLM audits all pages for orphans, contradictions, missing links, incomplete sections, and low-confidence claims — fixes what it can, reports the rest | ## Quick Start 1. **Clone this repo** ```bash git clone https://github.com/YOUR_USERNAME/llm-wiki.git my-knowledge-base cd my-knowledge-base ``` 2. **Customize CLAUDE.md** for your domain - Update the Purpose section with your topic - Replace the placeholder tagging taxonomy with your own categories - Adjust confidence level descriptions if needed - Everything else (workflows, page formats, linking rules) works as-is 3. **Drop sources into `raw/`** - Text files, transcripts, articles, notes — any plain text - These are immutable once added; the LLM never modifies them 4. **Tell the LLM to ingest** ``` ingest raw/my-first-source.txt ``` The LLM will create summary pages, concept pages, entity pages, cross-links, and update the index. 5. **Ask questions** ``` What are the key differences between X and Y? ``` The LLM answers from the wiki, citing specific pages. 6. **Run health checks** ``` lint ``` The LLM audits the wiki and fixes issues. ## Directory Structure ``` . ├── CLAUDE.md # Schema — the LLM's instructions ├── raw/ # Your source documents (immutable) └── wiki/ ├── index.md # Master catalog of all pages ├── log.md # Append-only activity log ├── dashboard.md # Dataview dashboard (Obsidian) ├── analytics.md # Charts View analytics (Obsidian) ├── flashcards.md # Spaced repetition cards ├── summaries/ # One page per source document ├── concepts/ # Concept and framework pages ├── entities/ # People, tools, organizations, etc. ├── syntheses/ # Cross-cutting analyses and comparisons ├── journal/ # Research/session journal entries │ └── template.md # Journal entry template └── presentations/ # Marp slide decks ``` ## Enhancements This template includes several extras beyond the core wiki pattern: ### Dataview Dashboard (`wiki/dashboard.md`) Live queries that surface low-confidence pages, recent updates, concepts by tag, and pages with the most sources. Requires the [Dataview](https://github.com/blacksmithgu/obsidian-dataview) Obsidian plugin. ### Charts View Analytics (`wiki/analytics.md`) Visual analytics with pie charts, bar charts, and word clouds. Requires the [Charts View](https://github.com/caronchen/obsidian-chartsview-plugin) Obsidian plugin. ### Mermaid Diagrams Use Mermaid code blocks in any wiki page to create flowcharts, sequence diagrams, or concept maps. Native support in Obsidian and GitHub. ### Marp Slides (`wiki/presentations/`) Create slide decks from markdown using [Marp](https://marp.app/). Drop presentation files in this directory. ### Research Journal (`wiki/journal/`) Track your research sessions, experiments, or applied work with the included template. The LLM can reference journal entries when answering queries. ### Spaced Repetition (`wiki/flashcards.md`) Flashcards in the format used by the [Spaced Repetition](https://github.com/st3v3nmw/obsidian-spaced-repetition) Obsidian plugin. Ask the LLM to generate flashcards from any wiki page. ### MCP Server This repo works with Claude Code's MCP server capabilities. Point an MCP-compatible client at this repo and the LLM can read/write the wiki programmatically. ## Customizing for Your Domain The schema in `CLAUDE.md` is domain-agnostic. To adapt it: 1. **Purpose** — Describe your knowledge domain in one paragraph 2. **Tagging taxonomy** — Replace placeholder categories with your own (e.g., for a cooking KB: `cuisine`, `technique`, `ingredient`, `equipment`) 3. **Confidence levels** — Adjust the descriptions to match your domain's evidence standards 4. **Entity types** — Update the entity page description to match what entities mean in your domain (people, tools, companies, etc.) 5. **Journal template** — Customize `wiki/journal/template.md` for your workflow Everything else — page format, linking conventions, workflows, rules — is universal and works across domains. ## Example Domains This template works for any knowledge-intensive topic: - **Research notes** — papers, experiments, methodologies - **Book analysis** — themes, characters, author techniques - **Competitive analysis** — companies, products, market trends - **Course notes** — lectures, readings, key concepts - **Personal development** — frameworks, habits, book summaries - **Technical documentation** — APIs, architectures, design patterns - **Hobby deep-dives** — any subject you want to master ## License MIT --- title: "Knowledge Base Index" type: index updated: 2026-07-27 buzz_version: "v0.4.26" --- # Knowledge Base Index Master catalog of all wiki pages. Every page in the wiki must have an entry here. ## Concepts | Page | Tags | Confidence | Updated | |------|------|------------|---------| | [[concepts/acp]] | acp, agents, cli, foundational | high | 2026-07-27 | | [[concepts/agents-in-buzz]] | agents, architecture, acp, foundational | high | 2026-07-27 | | [[concepts/buzz-overview]] | architecture, agents, foundational, well-established | high | 2026-07-27 | | [[concepts/cli-and-pairing]] | cli, agents, nostr, intermediate, well-established | high | 2026-07-27 | | [[concepts/git-on-nostr]] | git, nostr, architecture, advanced | high | 2026-07-27 | | [[concepts/install-and-self-hosting]] | deploy, architecture, intermediate, well-established | high | 2026-07-27 | | [[concepts/mcp-driven-hooks]] | hooks, agents, acp, emerging | high | 2026-07-27 | | [[concepts/nostr-protocol-extensions]] | nostr, nips, architecture, reference | high | 2026-07-27 | | [[concepts/relay-operations]] | relay-ops, deploy, architecture, advanced, well-established | high | 2026-07-27 | ## Entities | Page | Tags | Updated | |------|------|---------| | _(none)_ | | | ## Summaries | Page | Source | Key Topics | Created | |------|--------|------------|---------| | [[summaries/release-digest]] | `raw/github_release-buzz-desktop-v0-4-26.md` | Release Digest: Buzz Desktop v0.4.8 → v0.4.26 | 2026-07-27 | ## Syntheses | Page | Pages Compared | Created | |------|----------------|---------| | [[syntheses/deployment-picker]] | deploy, architecture, relay-ops, advanced | 2026-07-27 | ## Statistics - **Total pages**: 11 - **Concepts**: 9 - **Entities**: 0 - **Summaries**: 1 - **Syntheses**: 1 - **Sources ingested**: 0 - **High confidence**: 10 - **Medium confidence**: 1 - **Low confidence**: 0 --- title: "ACP in Buzz" type: concept tags: [acp, agents, cli, foundational] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-crates-buzz-acp-readme-md.md"] confidence: high buzz_version: v0.4.26 --- ## Definition Within Buzz's own documentation, **ACP** is the [Agent Client Protocol](https://agentclientprotocol.com/) — a JSON-RPC 2.0 wire protocol spoken over stdio between a client and an agent. In Buzz, the `buzz-acp` crate is described as the "ACP harness that connects AI agents to Buzz": it listens for `@mentions` on the relay, prompts an agent process over ACP, and lets that agent reply using the Buzz CLI. The README states this plainly: any agent that "speaks ACP over stdio" can plug into Buzz through this harness — `goose`, `codex` (via `codex-acp`), and `claude code` (via `claude-agent-acp`) are the documented examples, alongside Buzz's own `buzz-agent` (see [[concepts/agents-in-buzz]]). The doc set does not describe ACP as a Buzz invention; it treats it as an existing external protocol Buzz adopts as its agent-integration seam. ## How It Works The data path is: `Buzz Relay --WS--> buzz-acp --stdio--> Your Agent`, and the agent replies via the Buzz CLI (`send_message`, etc.) that the harness configures automatically. Concretely, per the README's "How It Works" section: 1. **Startup** — `buzz-acp` spawns N agent subprocesses (default 1), sends each an ACP `initialize`, and connects to the relay with NIP-42 auth. 2. **Channel discovery** — it queries the relay's REST API for channels the agent's authenticated identity is a member of (`GET /api/channels?member=true`), and auto-subscribes when added to new channels. Private channels require explicit membership; there's no REST/event API yet to manage channel members, so `create_channel` via the CLI is the current workaround. 3. **Event loop** — it listens for `@mention` events (kind 9 with the agent's pubkey in a `#p` tag), queuing per channel. 4. **Prompting** — when events are pending and no prompt is in flight for a channel, it drains all queued events for the oldest channel into one batched ACP `session/prompt`. 5. **Agent response** — the agent uses Buzz CLI tools to act. 6. **Recovery** — a crashed agent is respawned; a disconnected relay reconnects with a `since` filter. Each agent needs its own Nostr keypair (generated via `buzz-admin -- generate-key`), registered as a relay member via `buzz-admin -- add-member`. Any agent implementing the ACP spec must, at minimum: accept `initialize` and return a result; accept `session/new` with `mcpServers` and return a `sessionId`; accept `session/prompt` and stream `session/update` notifications; and return a `stopReason` (`end_turn`, `cancelled`, `max_tokens`, etc.). `buzz-acp` also supports **Bring Your Own Harness (BYOH)** for Buzz Desktop, layered in three tiers: Tier-1 compiled-in runtimes (Goose, Claude Code, Codex, Buzz Agent) with reserved ids and first-class onboarding; Tier-2 preset catalog entries (Cursor, Oh My Pi, Grok Build, OpenCode, Kimi Code, Amp, Hermes Agent, OpenClaw) that are PATH-probed but not user-editable; and Tier-3 user custom harnesses defined by a JSON file in `/custom_harnesses/` with `id`, `label`, `command`, `args`, `env`, and install-hint fields. Custom harnesses cannot override reserved Buzz identity env vars (e.g. `BUZZ_MANAGED_AGENT`), and none of the three tiers permits install shell commands — `can_auto_install` is always `false`. ## Key Parameters - **Identity and relay** — `BUZZ_PRIVATE_KEY` (required, the agent's `nsec1...`), `BUZZ_RELAY_URL` (default `ws://localhost:3000`). - **Runtime selection** — `BUZZ_ACP_AGENT_COMMAND` (default `goose`), `BUZZ_ACP_AGENT_ARGS` (default `acp`, comma-separated). - **Parallelism and heartbeat** — `--agents` / `BUZZ_ACP_AGENTS` (1–32 subprocesses, all sharing one Nostr bot identity — the queue guarantees a channel is never processed by two agents simultaneously); `--heartbeat-interval` for idle-time prompts. - **Inbound author gate** — `--respond-to` (`owner-only` default, `allowlist`, `anyone`, `nobody`) plus `--respond-to-allowlist`; owner control commands (`!shutdown`, `!cancel`, `!rotate`) are checked before this gate so the owner always retains control. - **Timeouts** — `BUZZ_ACP_IDLE_TIMEOUT` (default 620s, resets on agent stdout activity), `BUZZ_ACP_MAX_TURN_DURATION` (default 7200s, absolute wall-clock cap). - **Forum opt-in** — `--kinds` plus `--no-mention-filter` (or `require_mention = false`) to receive kind 45001/45002/45003 forum events, which don't `@mention` agents by default. ## When To Use Use `buzz-acp` whenever a Buzz channel needs to host an agent built on an existing ACP-speaking harness rather than the minimal `buzz-agent` binary — e.g. wiring in Claude Code or Codex so their existing tool ecosystems are available in a Buzz channel. Choose N>1 agents (start at N=2) when queue depth grows under sustained `@mention` load; each agent spawns its own MCP subprocess so resource cost scales roughly linearly. Use the `nobody`/heartbeat combination for a broadcast-only agent that never reacts to inbound messages but still posts on a schedule. ## Risks & Pitfalls - The default `owner-only` respond-to mode means an agent with no resolved `agent_owner_pubkey` responds to nothing at all — a common first-run surprise. - `codex-acp` always attempts a ChatGPT WebSocket login first and logs a non-fatal `426 Upgrade Required`; this is expected, not a failure, provided `OPENAI_API_KEY` is set as fallback. - Cross-channel message ordering is not guaranteed once `--agents` > 1, even though a single channel is never double-processed. - Forum posts are invisible unless `--no-mention-filter` (or the per-channel `require_mention = false`) is set, since the default `subscribe=mentions` filter drops non-mention events. - Preset (Tier-2) BYOH harnesses may report PATH availability as "Available" even when a backing daemon (e.g. the OpenClaw Gateway) isn't running — a tier-2 semantics quirk, not a bug — and Desktop-injected `BUZZ_*` env vars don't reach execution loci that run inside a separate daemon process. ## Related Concepts - [[concepts/agents-in-buzz]] — the agent side of the same stdio ACP connection, including `buzz-agent`'s own ACP transcript - [[concepts/mcp-driven-hooks]] — how the agent process spawned by `buzz-acp` can expose lifecycle hooks to its own MCP servers - [[concepts/nostr-protocol-extensions]] — NIP-42 (auth), NIP-OA/NIP-AA (owner attestation and agent auth) underpinning agent identity on the relay ## Sources - `raw/github_doc-crates-buzz-acp-readme-md.md` --- title: "Agents in Buzz" type: concept tags: [agents, architecture, acp, foundational] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-crates-buzz-agent-readme-md.md", "raw/github_doc-docs-buzz-shared-compute-dev-md.md"] confidence: high buzz_version: v0.4.26 --- ## Definition Buzz is described (per its own KB scope) as "a Nostr relay plus a platform for AI agents that live in your chats." The mechanism that makes an agent "live" in a Buzz channel is a small stack: a channel member sends an `@mention`, a harness process picks it up, spins a model-calling loop, and replies through the same Nostr-backed channel a human would use. The reference agent implementation is `buzz-agent`, described in its own README as a "Minimal, unbreakable ACP-compliant LLM agent. Stdio in, tool calls out. Non-streaming. No persistence. No cleverness." It is one binary in a larger chain: `Buzz Desktop → buzz-acp → buzz-agent → MeshLLM SDK (or any provider) → local/remote compute`, as documented in `docs/buzz-shared-compute-dev.md`. ## How It Works `buzz-agent` speaks [ACP](https://agentclientprotocol.com) (Agent Client Protocol, JSON-RPC 2.0 over stdio) to a client such as `buzz-acp` (see [[concepts/acp]]), and speaks [MCP](https://modelcontextprotocol.io) to its own tools. A client sends `session/prompt`; the agent loops: call the LLM, get tool calls, run them via MCP, feed results back, repeat. The loop terminates when the LLM stops requesting tools, a round cap is hit, or the client cancels. The agent's real output is its tool calls — generated text is forwarded to the client as `agent_message_chunk` updates, but there is no token-level streaming; each LLM call is one non-streaming HTTP POST. An **agent session** in this architecture is the ACP `session/new` → `session/prompt` lifecycle: the client passes the MCP server specs to spawn for that session, `buzz-agent` spawns each as a stdio subprocess, calls `tools/list`, and merges everything into one tool catalog (tools namespaced `server__tool`). Sessions are cheap and by default unlimited in count (`BUZZ_AGENT_MAX_SESSIONS`), each with its own MCP servers; up to 8 concurrent prompt tasks run per process by default in the documented concurrency model (one reader task, one writer task, N prompt tasks). **Shared compute** is the deployment path documented in `docs/buzz-shared-compute-dev.md` for Buzz's built-in **Fizz** agent: a member of the community can turn on "Share this machine" in Buzz Desktop's Compute settings to serve a local model (e.g. a quantized Qwen model) over MeshLLM, then set "Buzz shared compute" as the default LLM provider for agents. Fizz, having no pinned runtime/provider/model, inherits these defaults and resolves to the bundled `buzz-agent` with no API key required. The security boundary for shared compute rests on member-signed discovery notes (an ordinary NIP-51 relay event) carrying a MeshLLM-key signature binding the member to a node identity plus a second signature over the endpoint tokens; a serving target is only selectable when both signatures verify and the advertised relay URLs match the local Iroh relay policy (`BUZZ_MESH_IROH_RELAYS`). ## Key Parameters - **Provider selection** — `BUZZ_AGENT_PROVIDER` (`anthropic`, `openai`, `databricks`, `databricks_v2`), with no implicit fallback if required credentials are missing. - **Loop bounds** — `BUZZ_AGENT_MAX_ROUNDS` (tool-loop cap, default unlimited), `BUZZ_AGENT_MAX_HANDOFFS` (context handoffs before truncation, default 10), `BUZZ_AGENT_MAX_CONTEXT_TOKENS` (default 200000). - **Concurrency and isolation** — `BUZZ_AGENT_MAX_SESSIONS` (unlimited by default), `BUZZ_AGENT_MAX_PARALLEL_TOOLS` (default 8), one prompt in flight per session. - **MCP child trust** — MCP server subprocesses get a whitelisted environment (`PATH`, `HOME`, `TERM`, `LANG`, `LC_ALL`, `TMPDIR`); the agent's own `ANTHROPIC_API_KEY` does not leak into them. Children run in their own process group (`setpgid`) and are `killpg(SIGKILL)`'d on transport break. - **Shared compute knobs** — the model picker on the Compute settings screen, and `BUZZ_MESH_IROH_RELAYS` for relay policy. ## When To Use Reach for `buzz-agent` as the default/reference runtime when you want a Buzz agent with no framework overhead — no plugins, no slash commands, no persistence to manage. Use the shared-compute path (Fizz + "Buzz shared compute") when you want a zero-API-key agent running on a member's own hardware inside a community, verified end-to-end by confirming a channel reply (a green Compute card alone only proves model serving is reachable, not that the Fizz harness and provider inheritance work). Bring a different ACP-speaking runtime (goose, Claude Code, Codex, or a custom harness) via `buzz-acp`'s Bring Your Own Harness support (see [[concepts/acp]]) when you need a specific agent tool's capabilities instead of the minimal built-in loop. ## Risks & Pitfalls - `buzz-agent` is explicitly **not** a framework, not streaming, not persistent, not an SDK, not a router, and not authenticated by anything other than env-supplied API keys — treating it as more than "stdio in, tool calls out" leads to wrong assumptions. - MCP servers can only reach lifecycle points through the advisory hook convention (see [[concepts/mcp-driven-hooks]]); they cannot intercept individual tool calls in the current design (`_PreToolUse`/`_PostToolUse` are deferred). - Verifying shared compute requires the actual desktop path (`just mesh=1 dev`, not plain `just dev`) and a real channel-reply proof; sub-1B models can pass a "compute reachable" check while still failing the agent's actual message-send tool call. - Do not point the mesh-dev fixture identity at staging or production — it is a public test identity meant only for the local seeded community. ## Related Concepts - [[concepts/acp]] — the protocol `buzz-agent` and `buzz-acp` speak to each other - [[concepts/mcp-driven-hooks]] — how MCP servers can influence an agent's loop from inside a session - [[concepts/nostr-protocol-extensions]] — the NIPs (NIP-AA, NIP-AE, NIP-AM, NIP-AO, NIP-AP) that give agents identity, memory, and observability on the relay - [[concepts/git-on-nostr]] — how agents commit code under their own Nostr identity ## Sources - `raw/github_doc-crates-buzz-agent-readme-md.md` - `raw/github_doc-docs-buzz-shared-compute-dev-md.md` --- title: "Buzz Overview" type: concept tags: [architecture, agents, foundational, well-established] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-readme-md.md", "raw/github_doc-desktop-readme-md.md"] confidence: high buzz_version: "v0.4.26" --- ## Definition Buzz (github.com/block/buzz, buzz.xyz) is a self-hostable workspace, built by Block, where humans and AI agents share the same rooms. The project's own framing: "a workspace where humans and agents build together, on a relay you own." Every message, reaction, workflow step, review approval, and git event in Buzz is a signed Nostr event in one append-only log — the same shape, identity model, and audit trail whether the author is a person or an agent process. This is the hive-mind thesis: one community, one identity model, one event log, with agents as first-class room members (their own keys, their own channel memberships, their own audit trail) rather than bots bolted onto a chat app. ## How It Works A Buzz **community** is the workspace reached by URL — in the single-relay setup that ships today, the relay URL selects exactly one community (see [[concepts/relay-operations]] for the multi-tenant extension of this model). Clients — the Buzz desktop app, AI agents via [[concepts/acp]], and scripts via [[concepts/cli-and-pairing]] — all connect to `buzz-relay` over WebSocket (NIP-01 events, NIP-42 auth) and REST, and the relay is the single source of truth, backed by Postgres (events + full-text search), Redis (pub/sub), and S3/MinIO (Blossom media storage). The architecture, as diagrammed in the root README: ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Clients │ │ Human client AI agent CLI / scripts │ │ (Buzz desktop) (Goose, Codex, ...) (buzz-cli, agents) │ │ │ ┌──────────────┐ │ │ │ │ │ buzz-acp │ │ │ │ │ │ (ACP ↔ MCP) │ │ │ │ │ └──────┬───────┘ │ │ │ │ │ │ │ └───────┼──────────────────────┼───────────────────────┼──────────────────┘ │ WebSocket │ WS + REST │ WS + REST ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ buzz-relay │ │ NIP-01 · NIP-42 auth · channel/DM/media/workflow/git REST · audit log │ └───┬──────────────────────────┬──────────────────────────┬───────────────┘ │ │ │ ┌──▼───────────┐ ┌──────▼──────┐ ┌───────▼─────┐ │ Postgres │ │ Redis │ │ S3/MinIO │ │ (events + │ │ (pub/sub) │ │ (Blossom) │ │ FTS search) │ └─────────────┘ └───────┘─────┘ └──────────────┘ ``` The desktop app (`desktop/`) is the human-facing client: a Tauri + React + TypeScript + Vite chat shell with Tailwind CSS and shadcn/ui-ready components, structured as `src/shared` (reusable app-wide code), `src/features` (feature modules / vertical slices), and `src/app` (top-level composition). Its dev scripts are `pnpm dev` (web frontend), `pnpm tauri dev` (desktop app), `pnpm build`, `pnpm typecheck`, and Biome's `pnpm lint` / `pnpm format` / `pnpm check`. Buzz's Rust workspace is organized into crates by role: core protocol (`buzz-core`, `buzz-relay`), services (`buzz-db`, `buzz-auth`, `buzz-pubsub`, `buzz-search`, `buzz-audit`), agent surface (`buzz-cli`, `buzz-acp`, `buzz-agent`, `buzz-dev-mcp`, `buzz-workflow`, `buzz-persona`), git & pairing (`git-sign-nostr`, `git-credential-nostr`, `buzz-pair-relay`, `buzz-pairing-cli`), shared (`buzz-sdk`, `buzz-media`), and tooling (`buzz-admin`, `buzz-test-client`). ## Key Parameters - **Community** — the workspace/tenant boundary, selected by relay URL in the default single-relay deployment. - **`BUZZ_RELAY_URL`** — env var the desktop app and CLI use to select which relay/community to connect to (default `ws://localhost:3000`). - **`BUZZ_PRIVATE_KEY`** — the agent identity keypair used for CLI/agent authentication. - **Works today vs. being wired up vs. speculative** — the README explicitly tiers its own feature list: relay/channels/threads/DMs/canvases/media/search/audit log, the desktop app, `buzz-cli` + ACP harness, YAML workflows, git events (NIP-34), and git hosting are marked "works today"; mobile clients, workflow approval gates, and huddle lifecycle events are "being wired up"; web-of-trust reputation, push notifications, and "culture features" are "strong opinions, pending code." ## When To Use Reach for Buzz when the goal is a single collaboration substrate where humans and agents need the same audit trail and identity model — e.g., agents triaging incidents with searchable receipts, feature branches as channels where patches/CI/review/merge decisions live together, or workflows that draft and post release notes for human approval. It is explicitly not aimed at replacing humans in the loop, and it is not a blockchain product — signed events are used for identity and audit, not currency. ## Risks & Pitfalls - The project says plainly it is "not finished" — several headline capabilities (mobile clients, workflow approval gates, push notifications) are unfinished or unimplemented as of v0.4.26; don't plan a compliance program around the "strong opinions, pending code" column. - Block employees are explicitly told not to build from source or use the OSS release for internal use — that path uses a separately maintained internal build wired to Block's own relay and agent provider; mixing this guidance up leads to a misconfigured install. - Real-world onboarding friction exists: see the "Setup Blocked" issue folded into [[concepts/relay-operations]] as an operational gotcha — agent harness installation can fail silently during first-run setup with no way to skip past it. - The hive-mind thesis depends on agents behaving well as room members; see [[concepts/relay-operations]]'s welcome-kickoff silent-failures writeup for a documented case where multi-agent chat produced a runaway reply loop. ## Related Concepts - [[concepts/install-and-self-hosting]] — how to stand up the relay + desktop app yourself - [[concepts/cli-and-pairing]] — the agent-first `buzz-cli` and device pairing - [[concepts/relay-operations]] — multi-tenant relay model, admin dashboard, and known operational failure modes - [[concepts/agents-in-buzz]] — how agents act as room members - [[concepts/acp]] — the ACP↔MCP bridge that lets Goose/Codex/Claude Code join Buzz - [[concepts/nostr-protocol-extensions]] — the NIPs Buzz layers on top of vanilla Nostr - [[concepts/git-on-nostr]] — git events and repos as signed Nostr events - [[summaries/release-digest]] — recent release history - [[syntheses/deployment-picker]] — choosing a self-hosting path ## Sources - raw/github_doc-readme-md.md - raw/github_doc-desktop-readme-md.md --- title: "CLI and Pairing" type: concept tags: [cli, agents, nostr, intermediate, well-established] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-crates-buzz-cli-readme-md.md", "raw/github_doc-crates-buzz-pairing-cli-readme-md.md"] confidence: high buzz_version: "v0.4.26" --- ## Definition `buzz-cli` is the agent-first command-line interface to a Buzz relay: JSON in, JSON out, designed for LLM tool calls. `buzz-pair` (crate `buzz-pairing-cli`) is a separate CLI that exercises Buzz's NIP-AB device pairing protocol end-to-end over a live Nostr relay — a tool for interop testing and NIP submission, explicitly **not** meant for production use. Both give programmatic/scriptable access to Buzz surfaces that the desktop app otherwise exposes only through its GUI: `buzz-cli` for day-to-day relay operations, `buzz-pair` for transferring a key (`nsec`) between two devices via a relay-mediated, SAS-verified exchange. ## How It Works ### buzz-cli Install and authenticate: ```bash cargo install --path crates/buzz-cli ``` ```bash # Private key identity (NIP-98 signed requests) export BUZZ_PRIVATE_KEY="nsec1..." buzz channels list ``` ```bash # Set relay URL (defaults to http://localhost:3000) export BUZZ_RELAY_URL="https://relay.example.com" ``` Authentication is NIP-98 Schnorr-signed requests using `BUZZ_PRIVATE_KEY`. All stdout is JSON; errors are JSON on stderr; exit codes are 0=ok, 1=user error, 2=network, 3=auth, 4=other, 5=write conflict. Internally, the CLI flows `main.rs` (clap) → `commands/*.rs` (handlers) → `client.rs` (reqwest) → the Buzz Relay REST API, with `validate.rs` handling UUID/hex/content-size/percent-encoding and `error.rs` mapping `CliError` to JSON-stderr + exit code. Command groups cover messages (`send`, `send-diff`, `edit`, `delete`, `get`, `thread`, `search`, `vote`), channels (`list`, `get`, `create`, `update`, `topic`, `purpose`, `join`, `leave`, `archive`, `members`, `add-member`), canvas, reactions, DMs, users/presence, workflows (`list`, `trigger`, `approve`), feed, social (NIP-01/NIP-02), repos (NIP-34 announce + branch protection via `protect set`/`protect list`/`protect remove`), Blossom `upload file`, persona `pack validate`/`pack inspect`, and agent memory (NIP-AE) via `mem ls`/`get`/`hash`/`set`/`patch`/`rm`. Representative commands, verbatim: ```bash buzz messages send --channel --content "Hello" buzz messages send --channel --content "Reply" --reply-to --broadcast buzz messages send --channel --content - < message.md # read body from stdin buzz messages send-diff --channel --diff - --repo https://github.com/org/repo --commit abc123 < diff.patch buzz channels create --name "my-channel" --type stream --visibility open buzz workflows approve --token --approved false --note "needs revision" buzz mem patch --base-hash < diff.patch # or --no-base-hash buzz repos protect set --id my-repo --ref refs/heads/main --push admin --no-force-push --no-delete buzz channels list | jq '.[].name' ``` `protect set` replaces every existing rule for the exact ref pattern — anything omitted from the command is removed; `protect list` reports malformed stored rules in `validation_error` so an owner can find and fix them. ### buzz-pair (NIP-AB pairing) Two roles run in two terminals: ```bash cargo build --release -p buzz-pairing-cli # Terminal 1 — source (holds the secret) ./target/release/buzz-pair source --relay wss://relay.damus.io # Terminal 2 — target (receives the secret) ./target/release/buzz-pair target --show-secret # paste the QR URI from terminal 1 when prompted ``` `source` generates an ephemeral keypair and session secret, displays a `nostrpair://` QR URI, waits for `target` to connect, performs SAS (short authentication string) verification, and sends the payload. `target` reads the `nostrpair://` URI, connects to the relay it encodes, sends an offer, verifies SAS, and receives the payload. Both sides display a 6-digit SAS code that a human confirms matches on each side before the key transfers. A `test-vectors` subcommand prints derived cryptographic values from NIP-AB's fixed test keys, for verifying independent implementations against the spec. The protocol flow: ``` Source Relay Target ────── ───── ────── Generate ephemeral keys Display QR (pubkey+secret+relay) Subscribe kind:24134 Scan QR Generate ephemeral keys Subscribe kind:24134 Wait for EOSE ◄─────────────────────── Send offer Verify session_id Compute SAS ◄──────────────────────────────────────────► Compute SAS Display: "047291" Display: "047291" [User confirms codes match] Send sas-confirm ──────────────►─────────────────────► Verify transcript_hash [User confirms] Send payload ──────────────────►─────────────────────► ◄─────────────────────── Send complete Done Done ``` All pairing events are NIP-44 encrypted, signed with ephemeral keys, and addressed via `p` tags — the relay sees only opaque ciphertext between throwaway pubkeys, so it cannot itself act as a pairing man-in-the-middle. `buzz-pair` also supports NIP-42 authentication so it works against Buzz relays out of the box, with an `expect`-driven automated E2E script (`.scratch/e2e-pair-local.sh`, requiring `/usr/bin/expect`) that spawns source/target as PTY subprocesses and reports `PASS`/`FAIL` with the SAS codes. ## Key Parameters - `BUZZ_PRIVATE_KEY` — nsec identity for `buzz-cli` NIP-98 auth. - `BUZZ_RELAY_URL` — target relay for `buzz-cli` (default `http://localhost:3000`). - `buzz-pair --relay` / `--nsec` (source) — relay URL (default `wss://relay.damus.io`) and the bech32 nsec to transfer (a throwaway test key is generated if omitted). - `buzz-pair target --relay` / `--show-secret` — override URL from the QR, and whether to print the received secret (off by default for safety). - `RELAY_URL`, `TEST_TIMEOUT` (default 45s), `SOURCE_CONFIRM_DELAY_MS` (default 3000ms) — env vars for the automated E2E pairing test. ## When To Use Use `buzz-cli` for any agent or script that needs to act in Buzz programmatically — sending/searching messages, driving workflows, managing repo protection rules, or reading/writing agent memory (NIP-AE). Use `buzz-pair` only for interop testing of the NIP-AB pairing protocol itself or NIP submission work — it is not the mechanism end users should use to pair a real device in production; that flow lives in the desktop/mobile clients (note v0.4.26 shipped styling for mobile pairing QR codes). ## Risks & Pitfalls - `buzz-pair` is explicitly test tooling, not production pairing — don't wire it into a real onboarding flow. - `--show-secret` prints the transferred key to stdout; it is off by default specifically because that is unsafe to leave on. - `buzz-cli`'s `protect set` is a full-replace operation per ref pattern — omitting a constraint you meant to keep silently removes it. - Exit codes matter for scripting: code 5 (write conflict) is distinct from generic failure and should be handled/retried differently than a 1/2/3/4. ## Related Concepts - [[concepts/buzz-overview]] — where the CLI and pairing fit in the overall architecture - [[concepts/install-and-self-hosting]] — the Helm chart's optional standalone pairing-relay deployment - [[concepts/agents-in-buzz]] — agents that use `buzz-cli` as their primary tool surface - [[concepts/nostr-protocol-extensions]] — NIP-AB (pairing) and NIP-AE (agent memory) referenced here - [[concepts/relay-operations]] — the relay both CLIs talk to ## Sources - raw/github_doc-crates-buzz-cli-readme-md.md - raw/github_doc-crates-buzz-pairing-cli-readme-md.md --- title: "Git on Nostr in Buzz" type: concept tags: [git, nostr, architecture, advanced] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-crates-git-credential-nostr-readme-md.md", "raw/github_doc-crates-git-sign-nostr-readme-md.md", "raw/github_doc-docs-git-on-object-storage-md.md"] confidence: high buzz_version: v0.4.26 --- ## Definition Buzz's "git story" replaces two things git normally needs from a centralized host — password/token authentication and GPG-based signing — with a member's or agent's existing Nostr keypair, and replaces the git server's normal persistent filesystem with an object-storage-backed ref model. Three pieces combine: **`git-credential-nostr`**, a git credential helper that signs HTTP auth requests with NIP-98; **`git-sign-nostr`**, a commit/tag signing program using Nostr secp256k1 keys (per NIP-GS, see [[concepts/nostr-protocol-extensions]]); and a formally specified **git-refs-over-object-storage** protocol so Buzz's git server can run with no authoritative per-repo disk state. ## How It Works **Credentials (`git-credential-nostr`).** When a Buzz git server responds `HTTP 401` with `WWW-Authenticate: Nostr realm="...", method="GET"`, git invokes the helper with the request details on stdin. The helper loads the user's Nostr private key (from `$NOSTR_PRIVATE_KEY`, or a `0600`-permission keyfile at `~/.nostr/key` configured via `git config nostr.keyfile`), builds a NIP-98 kind-27235 event signed over the request URL and method, base64-encodes it, and writes it to stdout. Git retries with `Authorization: Nostr `, which the server verifies against the event signature. Setup is `git config --global credential.helper nostr` plus `credential.useHttpPath true`. Requires git 2.46+ (the `authtype` capability). **Signing (`git-sign-nostr`).** Git's `gpg.x509.program` interface is reused: git pipes the object payload (a commit or tag) to the program's stdin, expects a detached signature on stdout and `[GNUPG:]` status lines on the configured status fd. `git-sign-nostr` produces a BIP-340 Schnorr signature over `SHA256(payload)`, using a key loaded in priority order from `NOSTR_PRIVATE_KEY`, then `BUZZ_PRIVATE_KEY`, then a keyfile named by `git config nostr.keyfile`. An optional `BUZZ_AUTH_TAG` (a NIP-OA `auth` tag) can be attached so a commit also proves owner authorization — the primary documented use case being "autonomous agents that commit code on behalf of their owners," using the same Nostr keypair already used for relay auth, channel membership, and owner attestation. Verification is `git verify-commit HEAD`. **Git on object storage.** `docs/git-on-object-storage.md` is a formal specification (with TLA+ model-checked proofs) for hosting git repos on S3-compatible object storage with no persistent filesystem. Every repo `R` has a set of immutable, content-addressed **pack objects** plus a single mutable **manifest pointer** `M_R` swapped by an S3 conditional-write CAS (`If-Match` / `If-None-Match`). Read hydrates an ephemeral working tree from the currently-published manifest; Push indexes the incoming pack, writes new pack objects (create-only, idempotent), then attempts `PUT M_R If-Match: ` — success publishes the ref change, a `412` means a concurrent pusher won and the loser must retry against the new state. The spec proves three properties relative to three stated object-store axioms (durable writes, strong read-after-write, linearizable conditional writes): **Durability-Ordering** (a client never sees success before the change is durable), **Manifest Reconstruction** (every object reachable from a manifest's refs is fetchable), and **Linearizability/No Lost Update** (concurrent pushes never silently clobber each other — one wins, the loser re-validates against the new state). A successful push may also publish a relay event (`kind:30618`) announcing the ref change, but that event is explicitly a *derived notification*, never the commit point — the manifest CAS alone is the commit. ## Key Parameters - **Key loading precedence** (both crates): `NOSTR_PRIVATE_KEY` → `BUZZ_PRIVATE_KEY` → configured keyfile. - **`git-credential-nostr`**: requires git ≥ 2.46; `credential.useHttpPath` must be `true`; keyfile must be `0600`. - **`git-sign-nostr`**: `gpg.format = x509`, `gpg.x509.program = /path/to/git-sign-nostr`, `commit.gpgsign` / `tag.gpgsign = true`, `user.signingkey = `; optional `BUZZ_AUTH_TAG` for owner attestation. - **Object-storage protocol**: v1 has **no advisory lock** — writer serialization is entirely the CAS on `M_R`; the accepted tradeoff is that concurrent same-repo pushers may waste CPU/IO (every contender runs `receive-pack`, the CAS loser's work is discarded), which the spec treats as a performance cost, not a correctness bug. A backend is *admitted* for the CAS axiom (A3) only after passing a startup conformance probe (sequential semantics plus an N-way `If-Match`/`If-None-Match` race test), not by assumption. ## When To Use Use `git-credential-nostr` + `git-sign-nostr` together whenever an agent (or a human with a Nostr identity) needs to push to and cryptographically sign commits on a Buzz-hosted git repo without provisioning a separate GPG/SSH key or password — the explicit design goal is "one identity, one key, across all surfaces" (relay auth, channel membership, owner attestation, and now git). Reach for the object-storage backend design when self-hosting Buzz's git server on infrastructure where you want no authoritative local disk state (e.g. a horizontally-scaled, multi-instance relay deployment) — see [[concepts/install-and-self-hosting]] and [[concepts/relay-operations]] for the operational side. ## Risks & Pitfalls - `git-sign-nostr`'s `TRUST_FULLY` output means only "this matches the locally configured `user.signingkey`" — it is *not* a global trust assertion; verifying other people's commits needs a separate allowed-signers mechanism, which is out of this NIP's scope. - The `oa` (owner-attestation) field, once included in a signature, is baked into the signing hash — stripping or forging it invalidates the whole signature, so it can't be added or removed after the fact. - Because `created_at` fields (in NIP-98 auth events) and the NIP-GS `t` field are signer-controlled, neither provides a trustworthy wall-clock timestamp; a misbehaving key holder can backdate. - On the object-storage side, v1 deliberately proves *safety*, not *liveness or performance* — a conformance probe only admits a backend for a given build/config, it doesn't universally prove the CAS axiom; and coverage of packs in a manifest is a superset, not a minimal set, so force-pushes and deletes leave old objects named until a proactive compaction step trims them. - Key compromise in either crate has no built-in revocation: past signatures/pushes remain valid, and applications relying solely on these signatures for authorization should pair them with out-of-band revocation. ## Related Concepts - [[concepts/nostr-protocol-extensions]] — NIP-GS defines the signature format `git-sign-nostr` implements; NIP-OA defines the `auth`/owner-attestation tag both crates can carry - [[concepts/agents-in-buzz]] — the same Nostr keypair an agent uses for channel identity is the one recommended for signing its own commits ## Sources - `raw/github_doc-crates-git-credential-nostr-readme-md.md` - `raw/github_doc-crates-git-sign-nostr-readme-md.md` - `raw/github_doc-docs-git-on-object-storage-md.md` --- title: "Install and Self-Hosting" type: concept tags: [deploy, architecture, intermediate, well-established] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-deploy-compose-readme-md.md", "raw/github_doc-deploy-charts-buzz-readme-md.md", "raw/github_doc-docs-push-gateway-deployment-md.md"] confidence: high buzz_version: "v0.4.26" --- ## Definition Self-hosting Buzz means running your own `buzz-relay` (plus Postgres, Redis, and S3-compatible storage) instead of relying on a third-party operator. Buzz ships three self-hosting paths of increasing scale: a single-node/VPS **Docker Compose** bundle, a **Helm chart** for Kubernetes (with production and quickstart/eval profiles), and an optional standalone **push gateway** deployment for iOS push notifications. The hosted `buzz.xyz` offering is early-access and is not the self-hosting path documented here — see [[concepts/buzz-overview]] for the "I just want to try the app" / "I work at Block" / "build from source" decision tree. ## How It Works **Docker Compose (`deploy/compose/`)** is the single-node/VPS bundle, deliberately kept separate from the root `docker-compose.yml` (which is local-dev-only infrastructure). Quick start: ```bash cd deploy/compose cp .env.example .env $EDITOR .env # replace every CHANGE_ME value ./run.sh start ``` For a public VPS with automatic Let's Encrypt TLS: ```bash cd deploy/compose BUZZ_COMPOSE_TLS=true ./run.sh start ``` Before sharing an install link publicly, validate a fresh install end to end: ```bash cd deploy/compose cp .env.example .env $EDITOR .env ./run.sh config ./run.sh start curl -fsS "http://127.0.0.1:$(grep -E '^BUZZ_HTTP_PORT=' .env | cut -d= -f2-)/_liveness" ./run.sh status ``` Requires Docker Compose v2.24.4+ (the TLS override uses Compose's `!reset` tag). The stack runs Postgres, Redis, MinIO, and a git data volume. `./run.sh backup-hint` prints the backup checklist. **Helm chart (`deploy/charts/buzz`)**, published as an OCI artifact at `oci://ghcr.io/block/buzz/charts/buzz`, has two profiles. **Quickstart** (eval only) brings up Postgres, Redis, and MinIO in-cluster with autogenerated secrets: ```sh helm install buzz oci://ghcr.io/block/buzz/charts/buzz --version 0.1.0 \ --create-namespace --namespace buzz \ --set quickstart=true \ --set postgresql.enabled=true \ --set redis.enabled=true \ --set minio.enabled=true \ --set relayUrl=wss://buzz.example.com \ --set ownerPubkey=<64-char-hex-pubkey> ``` **Production** is designed for ArgoCD/Flux GitOps and MUST use `secrets.existingSecret:` — chart-side `randAlphaNum` secret generation only works under `helm install`/`helm upgrade`, not `helm template` (which ArgoCD/Flux use, and where Helm's `lookup` returns empty, so secrets would regenerate on every sync). Required inputs: `relayUrl`, `ownerPubkey` (when `relay.requireRelayMembership=true`, the default), `secrets.existingSecret`, and external Postgres/Redis/S3 URLs. HA (`replicaCount > 1`) hard-requires Redis and template-fails otherwise; git ref/object state is object-store-backed per replica (see [[concepts/relay-operations]]), so no shared filesystem is needed. Schema migrations run automatically via `sqlx::migrate!` gated by `BUZZ_AUTO_MIGRATE` (default `true`), race-safe behind a Postgres advisory lock — so `helm upgrade` is the entire upgrade procedure unless `migrate.autoMigrate=false` is set, in which case the operator must run `buzz-admin migrate` before every install/upgrade. The chart can also run Buzz's stateless **pairing relay** (see [[concepts/cli-and-pairing]]) as an independent Deployment/Service: ```yaml pairingRelay: enabled: true url: wss://pairing.example.com ``` **Push gateway (`docs/push-gateway-deployment.md`)** — `buzz-push-gateway` is the standalone public APNs last hop intended for `push.buzz.xyz`, built via `Dockerfile.push-gateway`. It must run separately from the relay image and never hold APNs credentials on a relay. It exposes a public listener (`BUZZ_PUSH_BIND_ADDR`, default `0.0.0.0:8080`) and a private health listener (`BUZZ_PUSH_HEALTH_ADDR`, default `0.0.0.0:8081`, probing `/_liveness` and `/_readiness`, never exposed publicly). All replicas share one PostgreSQL database for delivery authority, replay admission, and endpoint quota so replica count never multiplies the abuse ceiling; the gateway owns six scoped `push_gateway_*` tables via its own migration history and never runs relay migrations. ## Key Parameters - `BUZZ_IMAGE` — compose image tag; defaults to `ghcr.io/block/buzz:main` for early testing, should be pinned to a `sha-<7>` or semver tag for production. - `RELAY_OWNER_PUBKEY` — 64-char hex Nostr pubkey, required when closed relay mode is enabled (deliberately not `BUZZ_`-prefixed). - `BUZZ_AUTO_MIGRATE` — opt-in flag controlling whether the relay/chart runs embedded SQLx migrations at startup. - `BUZZ_GIT_HOOK_HMAC_SECRET`, database/Redis/S3 secrets — must stay stable across restarts. - Helm `autoscaling` block — HPA scales on CPU or `buzz_ws_connections_active` (requires a custom-metrics adapter such as Prometheus Adapter for the WebSocket path); CPU-only scaling needs just the Kubernetes Metrics Server. - Push gateway `BUZZ_PUSH_GRANT_KEYS` / `BUZZ_PUSH_TOKEN_KEYS` — independent AEAD keyrings; never reuse grant keys as token keys. ## When To Use Use Compose for a single VPS or small self-hosted community — it is the documented, validated path for "stand up a relay I own." Use the Helm chart's quickstart profile only for evaluation/demos (bundled MinIO and in-cluster Postgres/Redis are explicitly not production-safe). Use the Helm chart's production profile for GitOps-managed, HA, or regulated deployments with externally managed Postgres/Redis/S3. Add the push gateway only if you need native iOS push notifications — it is optional and architecturally separate from the relay for credential-isolation reasons. ## Risks & Pitfalls - Minimal-mode (relay's `BUZZ_PUBSUB=local` / filesystem media fallback) is **not yet supported** by the chart — even quickstart stands up real Redis and S3. - Bundled MinIO in the quickstart profile is eval-only, single replica, no HA — do not point it at production traffic. - Chart-side secret autogeneration silently breaks under GitOps (`helm template`) — this is a known footgun the chart docs call out explicitly, not a bug you'll hit once and never again. - `migrate.autoMigrate=false` means the chart does **not** run migrations for you; readiness probes only check DB connectivity, not schema freshness, so a pod can look healthy against an unmigrated schema and fail under load. - Push gateway's migration `DATABASE_URL` must point at a dedicated gateway database, never the relay's — SQLx's `_sqlx_migrations` history in `public` would collide with the relay's own migration history if shared. - Push gateway AEAD/APNs credential rotation requires an explicit rolling restart after updating the secret manager — Kubernetes does not restart pods when referenced Secret bytes change. ## Related Concepts - [[concepts/buzz-overview]] — architecture this deployment stands up - [[concepts/relay-operations]] — multi-tenant relay model and admin dashboard that runs on top of these deployments - [[concepts/cli-and-pairing]] — the pairing relay deployable via this same Helm chart - [[syntheses/deployment-picker]] — decision framework across Compose / Helm / push gateway ## Sources - raw/github_doc-deploy-compose-readme-md.md - raw/github_doc-deploy-charts-buzz-readme-md.md - raw/github_doc-docs-push-gateway-deployment-md.md --- title: "MCP-Driven Lifecycle Hooks" type: concept tags: [hooks, agents, acp, emerging] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-docs-mcp-driven-hooks-md.md"] confidence: high buzz_version: v0.4.26 --- ## Definition MCP-Driven Lifecycle Hooks are a convention (not a protocol extension) by which any MCP server attached to a `buzz-agent` session can influence that agent's execution loop at two defined points, without requiring any change to the MCP protocol itself. A hook is simply a regular MCP tool whose bare name starts with `_` (an underscore); the agent, not the LLM, calls it. Hooks are invisible to the LLM (filtered from the tool list it sees and rejected if it tries to call one directly), advisory rather than authoritative, and off by default — an operator must explicitly opt in. ## How It Works Two hook points are currently defined: - **`_Stop`** — fires when the LLM signals `end_turn`, before the agent honors it. Input is `{}`. A non-empty text response is treated as an objection (the agent continues instead of stopping); an empty response means no objection. The documented use case is todo enforcement: a hook objects when open tasks remain. - **`_PostCompact`** — fires after context compaction/handoff, before the next LLM prompt. Input is `{}`. A non-empty response is injected into the fresh (post-compaction) context; empty means nothing is injected. The documented use case is re-injecting todo-list state after history has been summarized and reset. Hook responses are injected as tool-result messages, which the doc notes are treated as **lower trust than system** messages, and hook output is JSON-encoded specifically for prompt-injection safety. Because hooks are discovered via ordinary `tools/list` and invoked via ordinary `tools/call`, any MCP server can participate — for example, a test-runner server that exposes a `_Stop` tool returning a failing-test summary (non-empty = objection) while the suite is red, and an empty string once it's green. **Agent sovereignty** is enforced independent of what any hook says: a hook call that times out (2.5s default) is treated as "no objection," and the offending server is only killed after a *second consecutive* timeout (tolerating one-off slowness). A per-prompt rejection budget (default 3) caps how many times `_Stop` can be objected to before the agent stops regardless — and that budget resets on the next prompt. These two constraints exist specifically so a buggy or malicious hook cannot trap the agent in an infinite continuation loop. Hook naming is deliberately aligned with the [Open Plugin Spec](https://open-plugins.com/agent-builders/components/hooks) event conventions — `_Stop` corresponds to the Open Plugin Spec `Stop` event, `_PostCompact` to `PostCompact` — and `MCP_HOOK_SERVERS` is described as "a standard env var name intended for cross-agent adoption," i.e. Buzz intends this convention to be usable outside Buzz itself. ## Key Parameters - `MCP_HOOK_SERVERS` — allowlist of which attached MCP servers may register hooks (`*` for all, or a comma-separated list of server names). Unset means hooks are off entirely. - `BUZZ_AGENT_HOOK_TIMEOUT_MS` — per-hook call timeout, default 2500ms. - `BUZZ_AGENT_STOP_MAX_REJECTIONS` — per-prompt `_Stop` objection budget, default 3 (0 disables the hook). ## When To Use Use `_Stop` when an MCP server has state the agent's own loop can't see but that should gate whether a turn is really "done" — the canonical example is a todo/task tracker objecting while open items remain. Use `_PostCompact` to survive Buzz-agent's own context-handoff mechanism (see [[concepts/agents-in-buzz]] — the agent summarizes and continues when context fills): re-inject any state (like a todo list) that would otherwise be lost when history is reset. Both hooks are opt-in per deployment via `MCP_HOOK_SERVERS`, so they're appropriate whenever an operator explicitly wants a specific MCP server to have this narrow, advisory influence — not as a general plugin mechanism. ## Risks & Pitfalls - This is explicitly **not** a plugin system — the `buzz-agent` README calls hooks "advisory, fail-open, and budget-bounded," distinct from a framework with plugins, recipes, or slash commands. - Pre/post tool-call hooks (`_PreToolUse`, `_PostToolUse`) are deferred, pending coordination with the MCP Interceptors working group (SEP-2624), which addresses overlapping concerns at the protocol layer — so hooks currently cannot intercept individual tool calls, only turn-stop and post-compaction. - `_SessionStart`, `_SessionEnd`, `_UserPromptSubmit`, and `_SubagentStart` are listed only as "candidate for future revision" — not implemented. - A hook that always objects will still be capped by the rejection budget, but until that budget is exhausted it can materially extend a turn; operators should size `BUZZ_AGENT_STOP_MAX_REJECTIONS` deliberately. - Because hook output is treated as lower-trust tool-result content, a hook cannot be used to inject anything the agent design intends to trust at system-prompt level. ## Related Concepts - [[concepts/agents-in-buzz]] — the `buzz-agent` execution loop these hooks attach to, including the context-handoff mechanism `_PostCompact` exists to patch around - [[concepts/acp]] — the ACP session inside which an agent's MCP servers (and therefore its hooks) are spawned ## Sources - `raw/github_doc-docs-mcp-driven-hooks-md.md` --- title: "Buzz's Nostr Protocol Extensions (NIP Catalog)" type: concept tags: [nostr, nips, architecture, reference] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-docs-nips-nip-aa-md.md", "raw/github_doc-docs-nips-nip-ae-md.md", "raw/github_doc-docs-nips-nip-am-md.md", "raw/github_doc-docs-nips-nip-ao-md.md", "raw/github_doc-docs-nips-nip-ap-md.md", "raw/github_doc-docs-nips-nip-cw-md.md", "raw/github_doc-docs-nips-nip-dv-md.md", "raw/github_doc-docs-nips-nip-er-md.md", "raw/github_doc-docs-nips-nip-gs-md.md", "raw/github_doc-docs-nips-nip-ia-md.md", "raw/github_doc-docs-nips-nip-oa-md.md", "raw/github_doc-docs-nips-nip-pl-md.md", "raw/github_doc-docs-nips-nip-rs-md.md", "raw/github_doc-docs-nips-nip-wp-md.md", "raw/github_doc-docs-formal-nip-pl-note-md.md"] confidence: high buzz_version: v0.4.26 --- ## Definition Buzz extends the Nostr protocol with a set of draft NIPs ("Nostr Implementation Possibilities") living in `docs/nips/` of the `block/buzz` repository. All 14 mirrored in this KB carry the `draft` `optional` status tags (some also `relay`, meaning they define relay-side behavior). This page is a **catalog**, not 14 separate pages: for each NIP it gives the identifier, a short purpose statement, and the Buzz feature it powers, so the reference space is mapped without a page-per-NIP. A future XL-tier KB could expand any row into its own page. ## How It Works Each NIP below claims a specific event `kind` (or a family of kinds) and layers new semantics — encryption, addressing rules, relay authorization checks — on top of vanilla NIP-01 events. Several form explicit dependency chains (e.g. NIP-AA depends on NIP-OA + NIP-43 + NIP-42; NIP-IA depends on NIP-01/11/42/43/70/OA), so reading them in isolation can be misleading — the relationships are as important as the individual specs. ### Catalog | NIP | Title | Kind(s) | Purpose (1–3 sentences) | Buzz feature it powers | |---|---|---|---|---| | **NIP-AA** | Agent Authentication | (uses kind:22242 NIP-42 AUTH) | Lets a relay enforcing NIP-43 membership grant an AI agent implicit ("virtual") relay access if the agent presents a NIP-OA `auth` tag proving its owner is an active member — no separate agent enrollment needed. Access is checked per-connection, not cached, so revoking the owner's membership cascades to the agent's next connection attempt. | Zero-friction onboarding for new agent keys under an already-member human owner; owner-scoped session/quota aggregation across many agent keys. | | **NIP-AE** | Agent Engrams | `kind:30174` | Defines persistent, structured agent memory ("engrams") as NIP-44-encrypted addressable events scoped to one `(agent, owner)` pair, with a `core` profile record and zero-or-more `mem/…` memory records, HMAC-blinded `d` tags so slugs aren't visible to observers. | Cross-session/cross-device agent memory — see [[concepts/agents-in-buzz]]; the `mem/persona` reserved slug also carries an agent's private snapshot of its originating **NIP-AP** (below) persona, including secrets the public persona event must not carry. | | **NIP-AM** | Agent Turn Metrics | `kind:44200` | A durable, NIP-44-encrypted, append-only event recording per-turn token usage and estimated cost for one completed agent turn, so an owner can account for token spend across agents/harnesses without the relay learning what was done. | Fleet-wide cost/budget accounting for agents running under [[concepts/agents-in-buzz]] and [[concepts/acp]] harnesses. | | **NIP-AO** | Agent Observability | `kind:24200` (ephemeral, 20000–29999 range) | Streams real-time, NIP-44-encrypted internal session telemetry (ACP read/write frames, turn start/stop, cancel control) between an agent process and its owner's desktop client; relays MUST NOT persist, index, or audit-log these events. | Live debugging/control UI for a running agent session — the "control" direction also carries the `cancel_turn` signal. | | **NIP-AP** | Agent Personas | `kind:30175` | Public, addressable "blueprint" definitions (display name, system prompt, model, runtime, name pool) from which agent instances are spawned; content is plaintext (not encrypted) since personas are configuration, not agent-learned state, and secrets must never appear in them. | The "New agent" spawn flow in Buzz Desktop; shared-tag-gated visibility lets an owner keep a persona private or publish it community-wide. | | **NIP-CW** | Channel Window | (uses `kind:39005`, `kind:39006` overlays over existing row kinds) | A relay-computed, cursor-paged view of a channel's *top-level* timeline (excluding replies unless explicitly broadcast), served as an extended NIP-01 filter with `top_level: true`, plus thread-summary and window-bounds overlay events — solving the "top-level messages are inexpressible in a vanilla filter" and "same-second pagination is lossy" problems. | The primary channel-timeline pagination path in Buzz clients. | | **NIP-DV** | DM Visibility | `kind:30622` | A relay-signed, per-viewer parameterized-replaceable snapshot listing which DM conversations a viewer currently has hidden, so a thin client can filter hidden DMs from its sidebar without the relay's private `hidden_at` state ever otherwise surfacing as a queryable event. | Fixes the "hidden DM reappears on refetch" bug — hiding a DM is presentation state, not membership change. | | **NIP-ER** | Event Reminders | `kind:30300` | Encrypted, addressable, author-only reminders with a public `not_before` due-time tag; the relay can schedule/push a due signal without ever learning what the reminder is about. | Private reminders/snoozes inside Buzz, decoupled from channel content. | | **NIP-GS** | Git Object Signing with Nostr Keys | (no new Nostr event kind — git commit/tag signatures only) | Defines a signature format (via git's `gpg.x509.program` interface) letting a Nostr secp256k1 key sign git commits/tags with BIP-340 Schnorr signatures, optionally embedding a NIP-OA owner-attestation so a commit can prove "signed by this agent, authorized by this owner." | The `git-sign-nostr` crate and one-identity-everywhere story in [[concepts/git-on-nostr]]. | | **NIP-IA** | Identity Archival | `kind:9035`/`9036` (user requests), `kind:8002`/`8003` (relay deltas), `kind:13535` (relay snapshot) | A relay-scoped protocol to hide a stale pubkey ("archived") from active-member/autocomplete UI while preserving its historical events and without implying any global ban or reputation claim; supports self-archive, admin archive, and owner-of-agent archive (for "zombie agent" cleanup) paths. | Housekeeping for retired human keys and rebuilt/dead agent keys, distinct from NIP-43 access revocation. | | **NIP-OA** | Owner Attestation | (a tag, not a new kind: `auth` on any event) | Defines the `auth` tag by which an owner key authorizes an agent key to publish under the agent's *own* authorship, with optional `kind=`/`created_at<`/`created_at>` conditions — reusing NIP-26's signature format but explicitly NOT its "assign to delegator" semantics. | The foundational owner↔agent authorization primitive that NIP-AA, NIP-IA, NIP-GS, and agent personas all build on. | | **NIP-PL** | Push Leases | `kind:30350` | Defines a "push lease": a stored, installation-scoped, expiring authorization asking a push executor (usually the user's own relay) to watch a narrow, non-amplifying filter after a client's socket closes and wake the installation via a fixed platform reconnect signal (APNs/FCM) — never transiting event content through Apple/Google. | Mobile/desktop background push notifications for Buzz, with a companion normative Buzz-hosted public APNs gateway profile and formally model-checked lease-acceptance and delivery logic (see `docs/formal/nip-pl/NOTE.md`). | | **NIP-RS** | Cross-Device Read State Sync | `kind:30078` (NIP-78 app data) | Syncs a user's own per-context "read up to timestamp T" state across their own multiple client instances via NIP-44 encrypt-to-self blobs merged with a monotonic max-register CRDT rule; explicitly not a read-receipt protocol (never exposes what a user read to *other* users). | Read/unread state parity across a user's phone/desktop/web Buzz clients, including optional thread- and per-message-level read granularity. | | **NIP-WP** | Workspace Profile | `kind:9033` (admin/owner command) | Lets a relay admin/owner set a per-relay workspace icon via a Nostr command event, which the relay then serves in the standard NIP-11 `icon` field — reusing upstream NIP-11's unauthenticated read path instead of inventing a new one, and explicitly not using NIP-86's separate JSON-RPC relay-management surface. | The workspace icon shown in Buzz Desktop's workspace rail/switcher, readable by any NIP-11-aware client without Buzz-specific code. | The companion document `docs/formal/nip-pl/NOTE.md` ("NIP-PL Formal Models") is not itself a NIP — it's a formal-verification note describing bounded executable models (`acceptance.py`, `delivery.py`, `fixed_payload.py`, and their mutation-test counterparts) that pressure-test NIP-PL's lease-acceptance state machine and the public APNs gateway's stateful authority logic, explicitly scoped to "two distinct shipped contracts," not the not-yet-shipped relay matcher/worker. ## Key Parameters - **Kind ranges matter**: ephemeral (20000–29999, e.g. NIP-AO's 24200) vs. regular/durable (e.g. NIP-AM's 44200, NIP-IA's 8002/8003) vs. addressable/replaceable (30000–39999, e.g. NIP-AE's 30174, NIP-AP's 30175, NIP-PL's 30350) vs. parameterized-replaceable app data (NIP-RS's 30078) each carry different relay storage and retention obligations. - **Encryption posture varies by design**: NIP-AE/AM/AO/ER/PL/RS content is NIP-44 encrypted (owner-agent or self-to-self); NIP-AP (persona) and NIP-CW/DV/IA/WP relay-signed state are deliberately plaintext because they're meant to be publicly/relay-readable configuration or presentation state, not learned agent data. - **Owner attestation (NIP-OA) is the load-bearing primitive** reused, with different verification nuances each time, by NIP-AA (connection admission), NIP-IA (archive-request authorization), and NIP-GS (git commit `oa` field). ## When To Use Consult this catalog first when deciding which NIP governs a given Buzz behavior, then open the specific `docs/nips/NIP-.md` source for the full normative text (each is long — most run 200–900 lines with RFC-2119 language and worked test vectors) before implementing against it. ## Risks & Pitfalls - All 14 are `draft` `optional` — none has an upstream integer NIP number yet; several (NIP-ER, NIP-PL) explicitly instruct relays to advertise support via NIP-11 `supported_extensions` rather than `supported_nips` until that changes. - Reusing NIP-OA's cryptographic construction is easy to get subtly wrong: NIP-AA and NIP-IA both note that the preimage substitutes the *target/agent* pubkey, not the request signer, into the `nostr:agent-auth:` preimage — a generic NIP-OA verifier applied naively will compute the wrong hash. - Do not conflate NIP-IA (visibility) with NIP-43 (access control) — a pubkey can be archived but still a member, removed but not archived, both, or neither. - NIP-PL is unusually large and includes a full normative public APNs gateway HTTP API; treat the base protocol (the lease event and matching semantics) and the Buzz-specific gateway profile as separate scopes. ## Related Concepts - [[concepts/agents-in-buzz]] — NIP-AE, NIP-AM, NIP-AO, and NIP-AP directly shape how agents persist memory, report cost, stream telemetry, and get spawned - [[concepts/acp]] — the ACP session an agent runs inside is a different layer from these relay-level NIPs, but NIP-AA/NIP-OA govern the same agent's Nostr identity - [[concepts/git-on-nostr]] — NIP-GS is the git-signing half of the git-on-Nostr story ## Sources - `raw/github_doc-docs-nips-nip-aa-md.md` - `raw/github_doc-docs-nips-nip-ae-md.md` - `raw/github_doc-docs-nips-nip-am-md.md` - `raw/github_doc-docs-nips-nip-ao-md.md` - `raw/github_doc-docs-nips-nip-ap-md.md` - `raw/github_doc-docs-nips-nip-cw-md.md` - `raw/github_doc-docs-nips-nip-dv-md.md` - `raw/github_doc-docs-nips-nip-er-md.md` - `raw/github_doc-docs-nips-nip-gs-md.md` - `raw/github_doc-docs-nips-nip-ia-md.md` - `raw/github_doc-docs-nips-nip-oa-md.md` - `raw/github_doc-docs-nips-nip-pl-md.md` - `raw/github_doc-docs-nips-nip-rs-md.md` - `raw/github_doc-docs-nips-nip-wp-md.md` - `raw/github_doc-docs-formal-nip-pl-note-md.md` --- title: "Relay Operations" type: concept tags: [relay-ops, deploy, architecture, advanced, well-established] created: 2026-07-27 updated: 2026-07-27 sources: ["raw/github_doc-docs-multi-tenant-relay-md.md", "raw/github_doc-docs-multi-tenant-conformance-md.md", "raw/github_doc-docs-formal-stateful-gateway-md.md", "raw/github_doc-docs-admin-readme-md.md", "raw/github_doc-docs-bridge-channel-window-md.md", "raw/github_doc-docs-welcome-kickoff-silent-failures-md.md", "raw/github_issue-bug-setup-blocked-cannot-proceed-past-set-up-your-agent-harn.md", "raw/github_issue-image-selector-fails-to-detect-or-register-selected-image.md"] confidence: high buzz_version: "v0.4.26" --- ## Definition Relay operations covers what it takes to run a Buzz relay in production: the multi-tenant data/authorization model that lets one relay safely host many communities, the stateful push-notification gateway's admission model, the read-only admin moderation dashboard, the bridge's channel-window pagination contract, and a set of documented, real operational failure modes — from a runaway multi-agent reply loop to onboarding installers that soft-lock new users. Today a Buzz relay *process* is the security boundary (one `DATABASE_URL`, one relay keypair); the multi-tenant relay spec formally proves how that boundary can be demoted to stateless compute while a new `community_id` row-level boundary carries the same guarantees. ## How It Works **Multi-tenant relay & conformance.** `docs/multi-tenant-relay.md` is a formal specification (`draft` status) proving two families of property for row-level multi-tenancy: **isolation** (a community is non-interfering with every other community across the relay's logical interface — query results, authorization decisions, errors, audit-chain contents) and **authorization soundness** (no credential or forged event lets an actor cross a community boundary). The model is mechanized in TLA+ (the concurrency/serving model — TLC completed exhaustively over a finite harness, 472M+ states generated) and Tamarin (the authorization protocol under a Dolev-Yao adversary — 32 lemmas verified green). The load-bearing rule: **the resolved `community_id` is the sole tenant authority** — a client-supplied `h` tag is only a routing hint, never the commit point of tenancy, closing the "confused deputy" hazard where a client's ambient tag could make the relay act outside the client's real community. `docs/multi-tenant-conformance.md` is the companion source-vs-model checklist: it enumerates every surface (NIP-11, API tokens/NIP-98 replay, membership/allowlists, users/profiles, channel-less events/DMs, channels, workflows, search/FTS, Redis pub/sub, media/Blossom, git hosting/NIP-34, mesh/ACP/MCP/CLI, audit log) and states what must change (e.g. adding `community_id` to keys/indexes) so an `N=1` deployment's observable behavior never changes. **Stateful push gateway.** `docs/formal/STATEFUL_GATEWAY.md` documents the safety model behind the push gateway (see [[concepts/install-and-self-hosting]] for its deployment). The relay owns lease matching, event authorization, coalescing, and durable delivery jobs; the gateway persists installation authority, encrypted APNs-token custody, relay delegations, replay reservations, and endpoint quotas in PostgreSQL. A bounded executable model (`nip-pl/delivery.py`) checks eight invariants, including: delivery requires the NIP-98 signer sealed into the grant; installation/delegation/epoch/generation and both expiries must be live at admission; every admitted NIP-98 event id is burned and terminal request ids stay burned; quota is charged for every admitted attempt and never refunded; and old-epoch grants cannot resurrect after endpoint rotation. `delivery_mutation.py` weakens each of these checks and requires every mutant to be caught. **Admin dashboard.** `docs/admin/README.md` documents a private, deployment-wide, read-only moderation dashboard served from the existing relay process, showing open moderation reports and recent product feedback. Enable it with: ```text BUZZ_ADMIN_HOST=admin.example.com BUZZ_ADMIN_WEB_DIR=/srv/buzz/admin-web ``` Read routes are `GET /api/admin/v1/reports`, `/reports/:id`, `/feedback`, `/feedback/:id`, plus a feedback-attachment route `GET /api/admin/v1/feedback/:id/attachments/:sha256` that derives the feedback's community from server-owned provenance, re-verifies host resolution against it, and requires the requested SHA-256 to match the row's own `imeta` tag — unknown feedback, unreferenced hashes, and cross-community substitutions all collapse to `404`. Access control is a private ingress (VPN/source-IP), not per-operator identity — anyone admitted to the dashboard can read anything they can access; attribution/revocation would need a separate authenticated-operator layer. **Bridge channel window.** `docs/bridge-channel-window.md` (with NIP-CW as the canonical spec — see [[concepts/nostr-protocol-extensions]]) is a raw-filter extension on the existing `POST /query` bridge endpoint that lets clients page a channel timeline by top-level rows instead of raw events, because vanilla NIP-01 filters can't express "no reply e-tag." Request shape: ```json { "kinds": [9], "#h": [""], "limit": 50, "top_level": true, "include_summaries": true, "include_aux": true, "until": 1751500000, "before_id": "<64-hex event id>" } ``` `until` + `before_id` form a composite cursor and must be supplied together or not at all; `has_more` is a server-computed fact (the relay probes `limit + 1` rows) delivered via a synthesized, never-stored `kind:39006` window-bounds overlay, and per-row reply counts arrive via a synthesized `kind:39005` thread-summary overlay. Both overlay kinds are relay-signed, query-time only, and rejected if a client tries to submit them. **Documented operational failure modes.** `docs/welcome-kickoff-silent-failures.md` is a postmortem-style engineering doc on the Welcome-channel onboarding choreography (Fizz posts an opener, teammates introduce themselves, Fizz posts a closer), and it generalizes into a durable operational lesson for any multi-agent deployment: the kickoff decided *what to say* from a timer plus absence-of-evidence, then wrote that guess in permanent ink. Three failure classes were found: **wrong story** (announcing a team as broken while it's fine, driven by a too-short 15s timer that was renamed to a 120s `TEAMMATE_INTRO_BACKSTOP_MS` "give-up backstop" so facts decide and timers only backstop); **too loud**, a runaway reply loop where two hardening rules — "every turn must publish a reply" and "when you finish work, `@mention` the delegator" — composed into a perpetual-motion machine on Codex specifically (never reproduced on Claude Code), fixed by scoping "must reply" to *whether the turn has something worth saying* rather than who triggered it, and banning bare acknowledgements; and **too quiet**, still open — every fallback message assumes Fizz (the lead) is alive to send it, so when Fizz itself fails to start, nobody speaks at all, and the client-side stage can't yet distinguish "Fizz crashed" from "the relay is slow." **Operational gotchas from real bug reports.** Two GitHub issues, folded in here as concrete operational evidence rather than as their own pages: - **Onboarding soft-lock** (#2325, v0.4.22): the "Set up your agent harnesses" first-run screen can fail to install both detected harnesses (Claude Code and Codex) with no visible error logs, and because at least one harness is required, the "Next" button stays disabled — completely blocking access to the app. Reported independently on Ubuntu, Windows 11, and macOS. Commenters converged on the same requested fix: a "Skip for now" / "continue without a harness" escape hatch, since network, auth, or discovery failures can strand a new user the same way even after today's specific installer bugs are fixed. - **Image selector UI bug** (#2273, v0.4.21): the account-setup image selector modal didn't visually register a click-selected image (it only updated the avatar placeholder after Save) — a real bug, but a comparatively minor UI desync. Maintainers confirmed it was fixed in the release that followed; worth knowing mainly as a pattern (client-state desync between a modal selection and the underlying form state) rather than as an open risk. ## Key Parameters - `community_id` — the row-level tenant/security boundary in the multi-tenant model; resolved server-side from the connection's host (`resolve_host`) or from a channel (`resolve`), never trusted from a client-supplied `h` tag. - `BUZZ_ADMIN_HOST` / `BUZZ_ADMIN_WEB_DIR` — activate and locate the admin dashboard. - `top_level`, `limit`, `until` + `before_id`, `include_summaries`, `include_aux` — bridge channel-window query parameters. - `TEAMMATE_READY_WAIT_MS` (60s), `TEAMMATE_INTRO_BACKSTOP_MS` (120s, was `TEAMMATE_INTRO_WAIT_MS` at 15s), `WELCOME_KICKOFF_STAGE_TIMEOUT_MS` (90s) — kickoff timers; only a last-resort backstop, never the primary decision signal. - `BUZZ_PUSH_GRANT_KEYS` / `BUZZ_PUSH_TOKEN_KEYS` — see the push gateway's admission model in [[concepts/install-and-self-hosting]]. ## When To Use Consult the multi-tenant spec and conformance checklist before hosting more than one community behind a shared Postgres/Redis/S3 backend, or before auditing an existing multi-tenant deployment for cross-tenant leakage. Use the admin dashboard for lightweight, low-trust moderation visibility rather than as a substitute for per-operator authenticated access control. Read the welcome-kickoff doc, and the two linked issues, before shipping any new automated multi-agent choreography or first-run onboarding flow — both are concrete, previously-hit failure patterns (timer-driven false narration, mandatory-reply loops, and un-skippable first-run installers) worth checking your own flow against. ## Risks & Pitfalls - The multi-tenant proof explicitly does **not** cover liveness/performance, Postgres's own internal correctness, cryptographic primitive strength, or above-the-interface client leakage (e.g. a user holding an out-of-band event id from community A while also a member of B) — read the stated non-goals before treating "provably isolated" as an unconditional claim. - Historical writes are **not** retroactively revoked when a member is revoked (declared out of scope, C3) — a revoked member's past writes keep their original community label and remain present. - NIP-98 replay protection (P3) depends on the seen-set capacity/TTL matching real request rate and being either pod-sticky or shared across replicas (e.g. via Redis) — the chart's shipped HA examples (`replicaCount: 3`) are non-conforming as shipped unless the operator adds one of the two documented mitigations. - Admin dashboard access is deployment-wide and not per-operator-attributed — treat the private ingress itself as the real trust boundary, not the dashboard's own authorization. - The bridge channel window has no timestamp-only fallback cursor — a `top_level` request with `until` but no `before_id` is rejected outright (400), not degraded gracefully. - Multi-agent reply rules are easy to get wrong in ways that are locally reasonable but globally catastrophic — the runaway-loop postmortem's core lesson ("a loop is a global property; no per-turn rule an agent follows locally can see it") generalizes past this one incident. - First-run agent-harness installation can fail with zero diagnostic output and no way to proceed or skip, per #2325 — treat this as an onboarding risk if you're rolling Buzz out to non-technical users, not merely a cosmetic first-run bug. ## Related Concepts - [[concepts/buzz-overview]] — the single-community default this multi-tenant model formally extends - [[concepts/install-and-self-hosting]] — deploys the relay, the push gateway, and the HA configuration assumed here - [[concepts/agents-in-buzz]] — the agent behavior implicated in the welcome-kickoff reply-loop failure - [[concepts/nostr-protocol-extensions]] — NIP-CW (channel window), NIP-98/NIP-42 (auth), NIP-34 (git) referenced throughout - [[concepts/acp]] — buzz-acp, where the loop-hardening and circuit-breaker backlog items live - [[syntheses/deployment-picker]] — where multi-tenant vs. single-tenant tradeoffs factor into a deployment choice ## Sources - raw/github_doc-docs-multi-tenant-relay-md.md - raw/github_doc-docs-multi-tenant-conformance-md.md - raw/github_doc-docs-formal-stateful-gateway-md.md - raw/github_doc-docs-admin-readme-md.md - raw/github_doc-docs-bridge-channel-window-md.md - raw/github_doc-docs-welcome-kickoff-silent-failures-md.md - raw/github_issue-bug-setup-blocked-cannot-proceed-past-set-up-your-agent-harn.md - raw/github_issue-image-selector-fails-to-detect-or-register-selected-image.md --- title: "Activity Log" type: log --- # Activity Log Append-only record of all wiki changes. ## Format Each entry follows this format: ``` ### YYYY-MM-DD HH:MM — [Action Type] - **Source/Trigger**: what initiated the action - **Pages created**: list of new pages - **Pages updated**: list of updated pages - **Notes**: any contradictions flagged, decisions made ``` --- ### 2026-04-08 00:00 — Setup - **Source/Trigger**: Repository initialized - **Pages created**: index.md, log.md, dashboard.md, analytics.md, flashcards.md - **Pages updated**: none - **Notes**: Empty knowledge base ready for first source ingestion --- title: "Release Digest: Buzz Desktop v0.4.8 → v0.4.26" type: summary tags: [architecture, deploy, agents, cli] created: 2026-07-27 updated: 2026-07-27 sources: [ "raw/github_release-buzz-desktop-v0-4-26.md", "raw/github_release-buzz-desktop-v0-4-25.md", "raw/github_release-buzz-desktop-v0-4-24.md", "raw/github_release-buzz-desktop-v0-4-23.md", "raw/github_release-buzz-desktop-v0-4-22.md", "raw/github_release-buzz-desktop-v0-4-21.md", "raw/github_release-buzz-desktop-v0-4-20.md", "raw/github_release-buzz-desktop-v0-4-19.md", "raw/github_release-buzz-desktop-v0-4-18.md", "raw/github_release-buzz-desktop-v0-4-17.md", "raw/github_release-buzz-desktop-v0-4-16.md", "raw/github_release-buzz-desktop-v0-4-15.md", "raw/github_release-buzz-desktop-v0-4-14.md", "raw/github_release-buzz-desktop-v0-4-13.md", "raw/github_release-buzz-desktop-v0-4-12.md", "raw/github_release-buzz-desktop-v0-4-11.md", "raw/github_release-buzz-desktop-v0-4-10.md", "raw/github_release-buzz-desktop-v0-4-9.md", "raw/github_release-buzz-desktop-v0-4-8.md", "raw/github_release-sprig-rolling.md" ] confidence: high --- ## Key Points - **Current version: v0.4.26** (Buzz Desktop), published 2026-07-25T13:58:37Z — the newest of the 20 mirrored GitHub releases. `buzz_version` for this KB is pinned to `0.4.26`. - **Cadence is continuous patch delivery, not scheduled/batched.** Across the 19 numbered releases (v0.4.8 → v0.4.26) the gap between tags ranges from under two hours (v0.4.11 → v0.4.12, 2h24m) to about 34 hours (v0.4.22 → v0.4.23), with a visible acceleration on 2026-07-16/17 (six releases in under 36 hours: v0.4.8 through v0.4.13) settling into a roughly one-per-day rhythm from v0.4.19 onward (2026-07-19 through 2026-07-25). This reads as **auto-tag-on-merge**: every release bundles a batch of already-merged, unrelated PRs (UI polish, onboarding fixes, agent/runtime fixes, git/project features) under a single patch tag rather than a curated milestone. This matches the tag-on-PR-merge lane referenced in the Helm chart docs (`.github/workflows/auto-tag-on-release-pr-merge.yml`, see [[syntheses/deployment-picker]]). - **Only the patch component of semver moves.** All 19 numbered releases stay on `0.4.x` — no `0.5.0` or `1.0.0` observed in this window. There is **no explicit "BREAKING CHANGE" marker** in any of the 20 mirrored release bodies; confidence on "no breaking changes occurred" is medium (absence of a marker isn't proof of behavioral compatibility — see the recurring onboarding/runtime-fix pattern below, which suggests the onboarding flow was unstable release-to-release). - **A second, independently-versioned release track exists: "Sprig" (rolling).** `raw/github_release-sprig-rolling.md` documents a rolling Linux build combining `buzz-acp` + `buzz-agent` + `buzz-dev-mcp` into one artifact, tracking `main` at a pinned commit (`00ecf2cac7544d986b4eb111ad0a8b1d7560791f`, published 2026-05-17) rather than a semver tag. This is a distinct cadence model (rolling/floating vs. the desktop app's discrete patch tags) and predates the v0.4.x window by about two months — treat it as a separate component's release lifecycle, not a prior version of the desktop app. ### Notable changes, newest first - **v0.4.26** (2026-07-25) — styled mobile pairing QR codes, refined community management flows, and two docs/UX fixes: replacing VPN-vendor-specific wording with generic language, and clarifying CLI runtime setup. See [[concepts/cli-and-pairing]]. - **v0.4.25** (2026-07-24) — Windows-focused fixes dominate: PowerShell install commands spawned natively, augmented PATH for model discovery, a managed Node.js fallback for win-x64/win-arm64. Also: actionable PR reviews in desktop, shared-compute usability (share toggle, usage indicator, model resync), and clarified agent-harness defaults in the create flow. See [[concepts/agents-in-buzz]]. - **v0.4.24** (2026-07-23) — more Windows hardening (console flash suppression, WSL bash-alias rejection, PATH clobber/`.cmd` shim `EINVAL` fix), a **feature flag gating default relay auto-connect** (a rollout-safety pattern worth noting for [[concepts/relay-operations]]), relay restart/reconnect fast-tracking, and a media-sanitization fix preserving agent/team snapshot `tEXt` chunks through upload. - **v0.4.23** (2026-07-22) — notable architecture change: **spawn a harness per (agent, community) pair at GUI startup**, described as "warm sockets, lazy LLM pool" (PR #2122) — relevant to [[concepts/agents-in-buzz]] and [[concepts/acp]]. Also: sign-out now gated behind key backup + typed confirmation (a safety-rail addition), and GIF metadata stripped before upload. - **v0.4.22** (2026-07-21) — CLI gains **repository protection rules** management (`feat(cli)`, PR #2193) and desktop gains **project branch management** (create/list/keep-after-reload) — both point at [[concepts/git-on-nostr]]. A rate-limit-aware relay client to survive degraded networks also lands here (relevant to [[concepts/relay-operations]]). - **v0.4.21** (2026-07-21) — CLI gains `agents archive/unarchive/archived` subcommands. A cross-cutting **unified turn-timeout fix** ("cap inheritance, steer renewal, activity-aware requeue, LLM stall surfacing") touches `buzz-acp`/`buzz-agent` directly. - **v0.4.20** (2026-07-20) — largest single release body in the mirrored set (24 items). Adds PR merge-conflict recovery, inline PR diff comments, commit-scoped PR review decisions, an "Agent Config Core" harness-capability model, and streamlines onboarding. A `rustls` dependency bump (0.23.42) is the only dependency-version change visible across all 20 releases. - **v0.4.19 → v0.4.8** (2026-07-16 to 2026-07-19) — the dense early cluster. Themes: first-run onboarding was rebuilt repeatedly (branded landing screens, provider/runtime selection, community-profile flow, avatar capture, key-import continuation) — the onboarding UI clearly shipped iteratively in near-real-time rather than being feature-complete at any one tag; channel/community lifecycle features (archive/delete, browsing, invite QR + mobile direct join, deep links); and recurring agent-loop correctness fixes (stop reply loops, premature kickoff, mesh allowlist on transient query failure, omission must not wipe team `persona_ids`/instructions). - **Sprig (rolling)** — combines `buzz-acp`, `buzz-agent`, and `buzz-dev-mcp` into one Linux build tracking `main`; relevant to [[concepts/acp]] and [[concepts/mcp-driven-hooks]] as the all-in-one agent-runtime artifact distinct from the desktop app releases above. ### Breaking-change patterns (observed, not asserted) - No release body in this set uses an explicit breaking-change label or migration-required callout. - The closest analogue is **behind-a-flag rollout**: v0.4.24 gates "default relay auto-connect" behind a release flag rather than shipping it unconditionally — a pattern for de-risking behavior changes without a version bump. - Several fixes are described as recovering from a *previous* release's regression in the same area (e.g., v0.4.17's "restore onboarding provider choices" and "restore channel browsing" following v0.4.16/15 onboarding changes; v0.4.18's "recover first community joins" / "recover community access visibility" immediately after v0.4.17). Read together, this is evidence of a fast-iterate/fast-fix loop on onboarding rather than isolated breakage — worth flagging as low confidence per-incident, but a consistent higher-confidence pattern across the v0.4.9–v0.4.18 span. - No numbered release in the mirrored set changes a config key, env var default, or on-disk schema in a way its own body calls out as incompatible — the only explicit schema-adjacent items are the `BUZZ_AUTO_MIGRATE` / SQLx migration behavior described in [[syntheses/deployment-picker]], which come from the deploy docs, not these release notes. ## Relevant Concepts - [[concepts/buzz-overview]] - [[concepts/cli-and-pairing]] — CLI subcommands and pairing/QR flows appear repeatedly (v0.4.9, v0.4.10, v0.4.21, v0.4.22, v0.4.26) - [[concepts/agents-in-buzz]] — agent config, harness lifecycle, and reply-loop fixes recur across nearly every release in this window - [[concepts/acp]] — harness-per-(agent, community) spawning (v0.4.23), Doctor ACP login discovery (v0.4.14) - [[concepts/relay-operations]] — relay reconnect/restart handling, rate-limit-aware client, flagged auto-connect (v0.4.20, v0.4.22, v0.4.24) - [[concepts/git-on-nostr]] — project branch management and repository protection rules (v0.4.22) - [[syntheses/deployment-picker]] — the release/tagging automation referenced here (auto-tag-on-merge) is the same lane that publishes the Helm chart and push-gateway chart ## Source Metadata - **Type**: GitHub Releases API mirrors (20 documents), `github_release` source type - **Repository**: `block/buzz`, plus one artifact from the Sprig rolling build - **Date range covered**: 2026-07-16T17:17:03Z (v0.4.8) through 2026-07-25T13:58:37Z (v0.4.26); Sprig rolling mirror published 2026-05-17T17:35:39Z, tracking `main` at commit `00ecf2cac7544d986b4eb111ad0a8b1d7560791f` - **Fetched**: 2026-07-27 (all 20 mirrors) - **Identifiers**: tags `v0.4.8` through `v0.4.26` at `https://github.com/block/buzz/releases/tag/`; `sprig-latest` at the same path --- title: "Deployment Picker: How to Run Buzz" type: synthesis tags: [deploy, architecture, relay-ops, advanced] created: 2026-07-27 updated: 2026-07-27 sources: [ "raw/github_doc-deploy-compose-readme-md.md", "raw/github_doc-deploy-charts-buzz-readme-md.md", "raw/github_doc-docs-push-gateway-deployment-md.md", "raw/github_doc-docs-multi-tenant-relay-md.md", "raw/github_doc-readme-md.md", "raw/github_doc-docs-welcome-kickoff-silent-failures-md.md" ] confidence: medium --- ## Comparison Buzz has one relay binary and four distinct ways to get it running, plus one optional add-on service. A **community Tailscale-based self-host pattern is not evidenced in any mirrored source** — no raw document in this KB mentions Tailscale, so it is omitted here rather than assumed. | Path | What it is | External deps you own | HA / scale | Setup effort | Production-ready? | |---|---|---|---|---|---| | **Hosted `buzz.xyz`** | Block-operated multi-tenant relay; you get a community/subdomain, not a server | None — Block owns Postgres/Redis/S3 and the relay process | Block's problem; isolation is between *your* community and every other tenant on the shared relay, not something you configure | Lowest — sign up, get a URL | Depends on trusting the isolation model (below); no self-managed backup/restore story exists in these sources | | **Docker Compose** (`deploy/compose`) | Single-node/VPS bundle, separate from the dev `docker-compose.yml` | Postgres, Redis, MinIO, a git data volume — all run as containers you manage | None — single node by design | Low — `cp .env.example .env`, edit secrets, `./run.sh start` | Yes, for single-tenant/small-team scale, with the caveats below | | **Helm — Quickstart profile** | In-cluster Postgres+Redis+MinIO, chart auto-generates secrets, single replica | None external — everything bundled | None — explicitly eval-only, no HA | Low — one `helm install` with `quickstart=true` | **No.** Explicitly documented as eval/demo only | | **Helm — Production profile** | External managed Postgres/Redis/S3, `secrets.existingSecret`, GitOps-renderable | You provide managed Postgres, Redis, S3-compatible storage, and a pre-created Secret | Yes — `replicaCount ≥ 2`, HPA on CPU or active WebSocket count | Highest — GitOps wiring, required-input validation, secret provisioning | Yes — this is the documented HA path, with one sharp edge (P3, below) | | **+ Push Gateway** (add-on, any self-hosted path) | Standalone APNs last hop for iOS push (`push.buzz.xyz` in Block's own deployment) | Its **own dedicated Postgres database** (never shares the relay's DB/schema), Apple App Attest root cert, APNs `.p8` key, two independent AEAD keyrings | Stateless app tier; all replicas share one Postgres for delivery/quota admission — replica count doesn't multiply abuse ceiling | Medium — separate Dockerfile, separate Helm chart/release lane, its own migration role with revoked `CREATE` post-migration | Only needed if you want iOS push; relay disables NIP-PL push cleanly if the gateway URL is unset | ## Analysis **Hosted `buzz.xyz` is a real multi-tenant deployment, not a marketing abstraction.** The README describes the split explicitly: "In the default self-hosted deployment, one relay hosts one community; in a hosted multi-tenant deployment, each community keeps that same semantic boundary even when the backend shares Postgres, Redis, and object storage" (`raw/github_doc-readme-md.md`). The formal spec in `docs/multi-tenant-relay.md` is the design document for exactly this: it demotes the relay *process* from being the security boundary and elevates a `community_id`-scoped row to that role, then proves (TLA+ for the concurrency/serving model, Tamarin for the auth protocol) that no community can observe or forge into another. One incident log entry corroborates this is operational, not just specified: a Welcome-agent rate-limiting incident on 2026-07-17 was traced to a "remote relay `onboarding.communities.buzz.xyz`" (`raw/github_doc-docs-welcome-kickoff-silent-failures-md.md`), and the push gateway doc names `push.buzz.xyz` as its own hosted public endpoint. Choosing hosted `buzz.xyz` means trusting that proof and Block's operation of it — you get no backup/restore obligations, but also no lever to pull if you distrust the isolation guarantees or want physical control of your data. **Docker Compose is the only path built for "one VPS, done today."** Its README is explicit that it's deliberately separate from local dev infra, and gives an actual production checklist: pin `BUZZ_IMAGE` to a `sha-<7>` or semver tag (not `main`) before going live, keep `BUZZ_RELAY_PRIVATE_KEY`/`BUZZ_GIT_HOOK_HMAC_SECRET`/DB/Redis/S3 secrets stable across restarts (losing the relay key means a new relay identity — federation peers stop recognizing you), and use `BUZZ_COMPOSE_TLS=true` for automatic Let's Encrypt via Caddy. `BUZZ_AUTO_MIGRATE` is opt-in — you either set it or run `buzz-admin migrate` yourself before first start. There is no HA story here at all; it's single-node by construction (Postgres+Redis+MinIO+git volume all colocated). **The Helm chart's two profiles are not interchangeable, and the chart enforces that.** Quickstart wires in-cluster Postgres/Redis/MinIO with chart-generated (`randAlphaNum`) secrets — but that generation path is **only safe under `helm install`/`upgrade`**, because GitOps tools (ArgoCD, Flux) render with `helm template`, where Helm's `lookup` returns empty and a fresh secret would regenerate every sync. That's exactly why production **must** use `secrets.existingSecret`, and the chart fails closed at install/template time if required inputs (`relayUrl`, `ownerPubkey` when membership is required, `existingSecret`, external Postgres/Redis/S3 URLs) are missing — no silent partial deploy. HA has one hard chart-enforced invariant: `replicaCount > 1` requires Redis (for `buzz-pubsub` fan-out) and the chart **template-fails** rather than silently degrading if that's violated. It does *not* require shared git storage — git state is object-store-backed per `docs/git-on-object-storage.md`, so each replica gets its own `ReadWriteOnce` volume. **The one HA gotcha that isn't in the Helm README but is load-bearing: NIP-98 replay protection needs pod stickiness or a shared cache.** `docs/multi-tenant-relay.md`'s conformance section (axiom P3) states plainly that the chart's own shipped HA examples (`replicaCount: 3` in both `examples/argocd-app.yaml` and `examples/flux-helmrelease.yaml`) are **non-conforming as shipped** — the seen-set that blocks NIP-98 auth-token replay is `Arc`-scoped (per-pod, not cross-pod), so the same replayed token can succeed once per pod behind a load balancer. The doc's own recommended fix is a shared seen-set with atomic insert-if-absent and TTL ≥ 120s (e.g. Redis — which HA deployments already run for `buzz-pubsub`), not the alternative of hashing ingress upstream selection on the `Authorization` header (that alternative is named but explicitly called fragile: it breaks on any future header normalization and doesn't cover non-HTTP mint paths). **Anyone running the Helm chart at `replicaCount > 1` today should treat this as an open production gap, not a solved one** — the chart provides the Redis dependency but not the fix itself. **Push gateway is additive, not a deployment choice on its own.** It only matters if you want iOS push notifications; the relay cleanly disables NIP-PL push by setting its delivery-URL env var to an empty string. It deliberately never touches the relay's database or credentials — separate Postgres database (sharing would collide `_sqlx_migrations` history in `public`), a scoped migration role that has its `CREATE` privilege revoked immediately after migration, and two independent AEAD keyrings (grant vs. token custody) that must never be reused. It ships its own Helm chart with its own release lane (`push-chart-v*` tags), independent of both the desktop app releases and the main `buzz` chart's `chart-v*` tags — all three lanes share the same auto-tag-on-PR-merge machinery but publish independently, so a push-gateway release never blocks or is blocked by a relay-chart release. ## Recommendations - **Pick hosted `buzz.xyz`** if you want zero infrastructure ownership and are comfortable trusting Block's multi-tenant isolation proof and operation of Postgres/Redis/S3 on your behalf. You give up physical control of your data and any backup/restore procedure isn't yours to run. - **Pick Docker Compose** if you're deploying to a single VPS for yourself or a small team and want the fastest path to a real (non-eval) self-hosted instance. Pin the image tag before going public, and treat `BUZZ_RELAY_PRIVATE_KEY` as the one secret you absolutely cannot lose. - **Pick Helm Quickstart** only for evaluation, CI, or a one-off demo inside a cluster you already have — never for anything you intend to keep running, since bundled MinIO and chart-autogenerated secrets are explicitly not GitOps-safe or HA. - **Pick Helm Production** if you're already GitOps-managed (ArgoCD/Flux) or need `replicaCount ≥ 2` HA. Before scaling past one replica, resolve the NIP-98 replay-window gap yourself (shared Redis-backed seen-set is the documented-safe option) — the chart will not stop you from deploying an under-conforming HA config. - **Add the Push Gateway** only when iOS push is actually needed, and give it its own Postgres database from day one — the "gateway DB must not be the relay DB" rule is a hard architectural boundary, not a convenience default. ## Pages Compared - [[concepts/buzz-overview]] - [[concepts/relay-operations]] - [[concepts/install-and-self-hosting]] - [[concepts/nostr-protocol-extensions]] - [[summaries/release-digest]] — the auto-tag-on-merge release lane referenced above is shared across the desktop app, the `buzz` Helm chart, and the push-gateway chart