diff --git a/.env.example b/.env.example
index 2db9c7a8bc..56e5e9c974 100644
--- a/.env.example
+++ b/.env.example
@@ -78,13 +78,6 @@ RUST_LOG=sprout_relay=debug,sprout_db=debug,sprout_auth=debug,sprout_pubsub=debu
 # OTLP tracing endpoint (optional — leave unset to disable)
 # OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
 
-# -----------------------------------------------------------------------------
-# Huddle (LiveKit integration)
-# -----------------------------------------------------------------------------
-# LIVEKIT_API_KEY=devkey
-# LIVEKIT_API_SECRET=devsecret
-# LIVEKIT_URL=ws://localhost:7880
-
 # -----------------------------------------------------------------------------
 # ACP (Agent Communication Protocol — sprout-acp harness)
 # -----------------------------------------------------------------------------
diff --git a/AGENTS.md b/AGENTS.md
index d9ac2514c2..1ff1e47d0a 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -10,25 +10,38 @@ code style, PR process, architecture), see [CONTRIBUTING.md](CONTRIBUTING.md).
 
 ```
 crates/
-  sprout-relay        # WebSocket relay server — main entry point
-  sprout-core         # Core types, event verification, filter matching
+  # Relay + core
+  sprout-relay        # WebSocket relay server — main entry point; also hosts git + huddle audio
+  sprout-core         # Core types, event verification, filter matching, kind registry
   sprout-db           # Postgres event store and data access layer
   sprout-auth         # Authentication and authorization
   sprout-pubsub       # Redis pub/sub fan-out, presence, typing indicators
-  sprout-mcp          # MCP server providing AI agent tools
-  sprout-acp          # ACP harness bridging Sprout events to AI agents
-  sprout-workflow     # YAML-as-code workflow engine (evalexpr conditions)
   sprout-search       # Typesense-backed full-text search
   sprout-audit        # Hash-chain audit log
-  sprout-huddle       # LiveKit audio/video integration
-  sprout-proxy        # Nostr client compatibility proxy
-  sprout-admin        # Operator CLI for relay administration
-  sprout-test-client  # Integration test client and E2E test suite
-  sprout-sdk          # Typed Nostr event builders (used by sprout-mcp and sprout-cli)
   sprout-media        # Blossom/S3 media storage
+  # Agent surface
+  sprout-mcp          # MCP server providing AI agent tools (being phased out in favor of the CLI)
+  sprout-acp          # ACP harness bridging Sprout events to AI agents
+  sprout-agent        # Minimal ACP-compliant agent (non-streaming, tool-calls-as-output)
+  sprout-dev-mcp      # Developer MCP server — shell + file-edit tools
+  sprout-persona      # Agent persona packs
+  sprout-workflow     # YAML-as-code workflow engine (evalexpr conditions)
+  # Clients + interop
+  sprout-proxy        # Nostr client compatibility proxy (NIP-28)
+  sprout-pair-relay   # Ephemeral sidecar relay for NIP-AB device pairing
+  sprout-pairing-cli  # CLI for NIP-AB device pairing interop testing
+  git-sign-nostr      # Sign git objects with a Nostr key
+  git-credential-nostr # Git credential helper for Nostr-authed push/fetch
+  # Tooling + shared
   sprout-cli          # Agent-first CLI
+  sprout-sdk          # Typed Nostr event builders
+  sprout-admin        # Operator CLI for relay administration
+  sprout-test-client  # Integration test client and E2E test suite
+  sprig               # All-in-one harness bundling ACP, agent, and dev MCP
 
 desktop/              # Tauri 2 + React 19 desktop app
+web/                  # Browser web client (repo browser, served by the relay)
+mobile/               # Flutter mobile app
 migrations/           # SQL migrations (auto-applied on relay startup)
 scripts/              # Dev tooling
 .env.example          # Config template — copy to .env before running
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 77c9ee2c4c..6c261fe163 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -6,7 +6,7 @@ Sprout is a self-hosted team communication platform built on the Nostr protocol
 
 The relay is the single source of truth. All reads and writes flow through it. There is no peer-to-peer event exchange, no gossip, no replication — just clients connecting to one relay over WebSocket, and the relay enforcing auth, verifying signatures, persisting events, fanning out to subscribers, indexing for search, and triggering automation.
 
-Sprout is a Rust monorepo (~72K LOC across 17 crates), licensed Apache 2.0 under Block, Inc.
+Sprout is a Rust monorepo, licensed Apache 2.0 under Block, Inc.
 
 ---
 
@@ -81,15 +81,14 @@ sprout-core  (zero I/O — types, verification, filter matching, kind registry)
 sprout-mcp          (agent API surface — stdio MCP server; depends on sprout-core and sprout-sdk)
 sprout-acp          (agent harness — bridges relay @mentions → AI agents via ACP/JSON-RPC)
 sprout-proxy        (NIP-28 compatibility proxy — translates standard Nostr clients ↔ Sprout relay)
-sprout-huddle       (LiveKit audio/video integration — standalone, not wired into relay)
 sprout-sdk          (typed Nostr event builders — used by sprout-mcp, sprout-acp, and sprout-cli)
 sprout-media        (Blossom/S3 media storage)
 sprout-cli          (agent-first CLI)
-sprout-admin        (operator CLI: mint/list API tokens)
+sprout-admin        (operator CLI: relay membership + key generation)
 sprout-test-client  (integration test harness + manual CLI)
 ```
 
-**Key architectural principle:** The relay is the single source of truth. `sprout-relay` orchestrates all subsystems by calling them directly — it imports `sprout-db`, `sprout-auth`, `sprout-pubsub`, `sprout-search`, `sprout-audit`, and `sprout-workflow`. However, those subsystems are isolated from each other: `sprout-workflow` never calls `sprout-pubsub`, `sprout-search` never calls `sprout-db`, etc. Cross-subsystem coordination happens only through the relay. `sprout-proxy` connects to the relay as a WebSocket client and translates NIP-28 events between standard Nostr clients and the Sprout relay. `sprout-huddle` is a standalone crate not yet wired into the relay.
+**Key architectural principle:** The relay is the single source of truth. `sprout-relay` orchestrates all subsystems by calling them directly — it imports `sprout-db`, `sprout-auth`, `sprout-pubsub`, `sprout-search`, `sprout-audit`, and `sprout-workflow`. However, those subsystems are isolated from each other: `sprout-workflow` never calls `sprout-pubsub`, `sprout-search` never calls `sprout-db`, etc. Cross-subsystem coordination happens only through the relay. `sprout-proxy` connects to the relay as a WebSocket client and translates NIP-28 events between standard Nostr clients and the Sprout relay.
 
 ---
 
@@ -316,7 +315,7 @@ After registering, the REQ handler queries Postgres for stored events matching t
 
 ### sprout-core — Shared Types and Verification
 
-**1,196 LOC. Zero I/O.** The foundation every other crate builds on. Explicitly prohibits tokio, sqlx, redis, and axum in its `Cargo.toml`.
+**Zero I/O.** The foundation every other crate builds on. Explicitly prohibits tokio, sqlx, redis, and axum in its `Cargo.toml`.
 
 **Key types:**
 
@@ -345,7 +344,7 @@ pub const ALL_KINDS: &[u32]  // 80 entries (KIND_AUTH excluded — never stored)
 
 ### sprout-auth — Authentication and Authorization
 
-**2,310 LOC.** Handles authentication paths, scope enforcement, and token operations.
+Handles authentication paths, scope enforcement, and token operations.
 
 **Auth paths:**
 
@@ -378,7 +377,7 @@ pub trait RateLimiter: Send + Sync { ... }
 
 ### sprout-db — Postgres Event Store
 
-**7,367 LOC.** All database access. Uses `sqlx::query()` (runtime, not compile-time macros) — no `.sqlx/` offline cache required.
+All database access. Uses `sqlx::query()` (runtime, not compile-time macros) — no `.sqlx/` offline cache required.
 
 **Key operations:**
 
@@ -416,7 +415,7 @@ pub trait RateLimiter: Send + Sync { ... }
 
 ### sprout-pubsub — Redis Pub/Sub, Presence, Typing
 
-**887 LOC.** Manages Redis pub/sub fan-out, presence tracking, and typing indicators.
+Manages Redis pub/sub fan-out, presence tracking, and typing indicators.
 
 **Architecture:**
 
@@ -448,7 +447,7 @@ EXPIRE sprout:typing:{channel_id} 60
 
 ### sprout-search — Typesense Integration
 
-**1,126 LOC.** Full-text search via Typesense. All HTTP calls use `reqwest` with `X-TYPESENSE-API-KEY`.
+Full-text search via Typesense. All HTTP calls use `reqwest` with `X-TYPESENSE-API-KEY`.
 
 **Collection schema (7 fields):** `id`, `content`, `kind` (int32), `pubkey` (facet), `channel_id` (facet, optional), `created_at` (int64, default sort), `tags_flat` (string[]).
 
@@ -466,7 +465,7 @@ EXPIRE sprout:typing:{channel_id} 60
 
 ### sprout-audit — Hash-Chain Audit Log
 
-**776 LOC.** Tamper-evident append-only log with SHA-256 hash chaining.
+Tamper-evident append-only log with SHA-256 hash chaining.
 
 **Hash chain:** each entry stores `prev_hash` (hash of the previous entry). `verify_chain()` walks entries and recomputes hashes to detect tampering. Genesis entry uses `GENESIS_HASH` (64 zeros).
 
@@ -482,7 +481,7 @@ EXPIRE sprout:typing:{channel_id} 60
 
 ### sprout-workflow — YAML-as-Code Automation Engine
 
-**4,012 LOC.** Parses, validates, and executes channel-scoped workflow definitions.
+Parses, validates, and executes channel-scoped workflow definitions.
 
 **Workflow definition structure:**
 ```yaml
@@ -533,7 +532,7 @@ Note: Both `TriggerDef` and `ActionDef` use serde internally-tagged enums. Trigg
 
 ### sprout-proxy — NIP-28 Compatibility Proxy
 
-**4,933 LOC.** Lets standard Nostr clients (Coracle, nak, Amethyst, nostr-tools, nostr-sdk) read and write Sprout channels using the NIP-28 Public Chat Channels protocol. Connects to the relay as a WebSocket client; presents a standard NIP-01/NIP-11/NIP-28/NIP-42 interface to external clients.
+Lets standard Nostr clients (Coracle, nak, Amethyst, nostr-tools, nostr-sdk) read and write Sprout channels using the NIP-28 Public Chat Channels protocol. Connects to the relay as a WebSocket client; presents a standard NIP-01/NIP-11/NIP-28/NIP-42 interface to external clients.
 
 **Key modules:** `server.rs` (Axum WebSocket server, NIP-11, NIP-42 auth, filter splitting), `translate.rs` (bidirectional kind/tag translation), `upstream.rs` (persistent relay connection with auto-reconnect and subscription replay), `channel_map.rs` (bidirectional UUID ↔ kind:40 event ID mapping), `shadow_keys.rs` (deterministic keypair derivation), `guest_store.rs` (pubkey-based guest registry), `invite_store.rs` (token-based invite system).
 
@@ -575,27 +574,23 @@ Kind 5 (deletion) is intentionally blocked inbound — the relay's deletion hand
 
 ---
 
-### sprout-huddle — LiveKit Audio/Video Integration
+### Huddle Audio — WebSocket Opus Relay
 
-**728 LOC.** Mints LiveKit JWT tokens and parses LiveKit webhook events. Defines session/participant data structures (no active registry — types only).
+Real-time voice lives inside `sprout-relay` (`src/audio/`), not a separate crate. A WebSocket endpoint (`wss://.../huddle/{channel_id}/audio`) authenticates each participant with a NIP-42 challenge, checks channel membership, admits them to an in-memory room, and forwards opaque Opus frames between peers. No external SFU.
 
-**JWT token:** HS256, 6-hour TTL (overridable). Claims: `iss` (api_key), `sub` (identity), `iat`, `exp`, `name`, `video` (VideoGrant: room, roomJoin, canPublish, canSubscribe).
+**Frame protocol (v2):** 8-byte big-endian header (sequence `u16`, 48 kHz timestamp `u32`, level dBov `i8`, flags `u8`) followed by an opaque Opus payload. Invalid `level_dbov` values are clamped rather than dropped — losing a metric beats losing audio.
 
-**Webhook verification:** HMAC-SHA256 of raw body bytes, hex-encoded. Constant-time comparison via `hmac` crate's built-in `verify_slice`.
+**Room state:** an admission guard synchronizes joins against the room's ended flag; soft cap 25 peers (hard cap 255 via `u8` peer index). Per-peer audio uses a bounded channel (drop-on-full); the control channel is separate and never drops join/leave.
 
-**5 webhook event types:** `RoomStarted`, `RoomFinished`, `ParticipantJoined`, `ParticipantLeft`, `TrackPublished`.
+**Lifecycle events:** the relay emits Nostr events for participant joined / left and huddle ended; the desktop client emits huddle started and guidelines. When the last peer leaves, the room ends and the channel archives atomically.
 
-**Session types:** `HuddleSession` with `Vec<HuddleParticipant>`. Participants have `joined_at`, `left_at`, and `Vec<TrackInfo>`. These are data structures and helpers only — no session registry or lifecycle manager exists in the crate.
-
-**Room naming:** `"sprout-{uuid}"` format via `create_room_name(channel_id)`.
-
-**Does NOT:** emit Nostr events for huddle lifecycle (relay-side integration is planned). Does NOT persist session state.
+**Not yet built:** recording and per-track publishing (the corresponding kinds are reserved, no producer exists).
 
 ---
 
 ### sprout-relay — The Server
 
-**14,327 LOC.** Axum WebSocket server. Ties all other crates together. The only crate that imports and orchestrates all subsystems.
+Axum WebSocket server. Ties all other crates together. The only crate that imports and orchestrates all subsystems.
 
 **`AppState`** (Arc-wrapped, shared across all connections — key fields shown, not exhaustive):
 
@@ -686,19 +681,9 @@ pub enum AuthState { Pending { challenge: String }, Authenticated(AuthContext),
 
 ### sprout-mcp — Agent API Surface
 
-**4,879 LOC.** stdio MCP server using the `rmcp` SDK. The interface through which AI agents interact with Sprout. Logs to stderr (stdout is the MCP JSON-RPC channel).
-
-**43 registered tools (+ 1 implemented but unregistered, + 3 deferred media/realtime toolsets):**
+stdio MCP server using the `rmcp` SDK. The interface through which AI agents interact with Sprout. Logs to stderr (stdout is the MCP JSON-RPC channel).
 
-| Category | Tools |
-|----------|-------|
-| Default | `send_message`, `send_diff_message`, `edit_message`, `delete_message`, `get_messages`, `get_thread`, `search`, `get_feed`, `add_reaction`, `remove_reaction`, `get_reactions`, `list_channels`, `get_channel`, `join_channel`, `leave_channel`, `update_channel`, `set_channel_topic`, `set_channel_purpose`, `open_dm`, `get_users`, `set_profile`, `get_presence`, `set_presence`, `trigger_workflow`, `approve_step` |
-| Channel admin | `create_channel`, `archive_channel`, `unarchive_channel`, `add_channel_member`, `remove_channel_member`, `list_channel_members`, `delete_channel` |
-| DMs | `add_dm_member`, `hide_dm`, `list_dms` |
-| Canvas | `get_canvas`, `set_canvas` |
-| Workflow admin | `list_workflows`, `create_workflow`, `update_workflow`, `delete_workflow`, `get_workflow_runs` |
-| Identity | `set_channel_add_policy` |
-| Forums | `vote_on_post` |
+The registered tool surface is grouped into toolsets, enabled per server via `SPROUT_TOOLSETS`. The authoritative list (and per-toolset grouping) is `ALL_TOOLS` in `crates/sprout-mcp/src/toolsets.rs` — the doc deliberately doesn't duplicate it, since a hand-copied list drifts. The default toolset covers messaging, threads, search, feed, reactions, channel basics, DMs, profiles/presence, and workflow triggers; opt-in toolsets add channel admin, canvas, workflow admin, forums, social, and media.
 
 **Key implementation details:**
 - Connects to relay via WebSocket (`tokio_tungstenite`). Handles NIP-42 auth automatically.
@@ -717,7 +702,7 @@ pub enum AuthState { Pending { challenge: String }, Authenticated(AuthContext),
 
 ### sprout-acp — Agent Communication Protocol Harness
 
-**14,920 LOC.** Standalone binary that bridges Sprout relay events to AI agents via the [Agent Communication Protocol](https://agentclientprotocol.com/) (ACP). The active counterpart to `sprout-mcp`'s passive tool-serving role.
+Standalone binary that bridges Sprout relay events to AI agents via the [Agent Communication Protocol](https://agentclientprotocol.com/) (ACP). The active counterpart to `sprout-mcp`'s passive tool-serving role.
 
 **Architecture:**
 
@@ -753,23 +738,19 @@ Sprout Relay ──WS──→ sprout-acp ──stdio (ACP/JSON-RPC)──→ Ag
 
 ### sprout-admin — Operator CLI
 
-**213 LOC.** Two subcommands:
+Subcommands:
 
 | Subcommand | Purpose |
 |------------|---------|
-| `mint-token` | Generate API token, store SHA-256 hash in DB, display raw token once |
-| `list-tokens` | List all active tokens (ID, name, scopes, created) |
-
-`mint-token` options: `--name`, `--scopes` (comma-separated), optional `--pubkey`. If `--pubkey` omitted, generates a new keypair and displays `nsec` (bech32) and pubkey.
-
-Raw token is shown exactly once and never stored. Only the SHA-256 hash reaches the database.
+| `add-member` | Add a pubkey to the relay membership list (`--pubkey`, `--role`) |
+| `list-members` | List all relay members |
+| `generate-key` | Generate a new Nostr keypair (for bootstrapping) |
+| `reconcile-channels` | Emit kind:39000/39002 discovery events for channels missing them (idempotent) |
 
 ---
 
 ### sprout-test-client — Integration Test Harness
 
-**9,319 LOC** (832 in `src/`, remainder in `tests/` directory).
-
 **`SproutTestClient`** wraps a WebSocket connection with a `VecDeque<RelayMessage>` buffer for message interleaving. Methods: `connect`, `connect_unauthenticated`, `authenticate`, `send_event`, `send_text_message`, `subscribe`, `close_subscription`, `recv_event`, `collect_until_eose`, `disconnect`.
 
 **Test coverage:**
@@ -841,7 +822,6 @@ Applied in: `sprout-workflow` (CallWebhook action), `sprout-core` (shared utilit
 
 ### Webhook Security
 
-- LiveKit webhooks: HMAC-SHA256 of raw body bytes, hex-encoded, constant-time comparison
 - Workflow webhooks: constant-time XOR comparison of stored UUID secret (not HMAC — compares the secret directly, not a body MAC)
 - Outbound webhooks (CallWebhook): SSRF protection + redirects disabled + 1 MiB response cap
 
@@ -898,35 +878,6 @@ These are verified gaps in the current implementation — not design aspirations
 | 1 | **No sqlx offline query cache** | Uses `sqlx::query()` (runtime) not `sqlx::query!()` (compile-time). No `.sqlx/` directory. Queries are not validated at compile time. |
 | 2 | **No rate limiting implementation** | `RateLimiter` trait exists in `sprout-auth`. Only implementation is `AlwaysAllowRateLimiter` (test stub, gated behind `#[cfg(any(test, feature = "test-utils"))]`). `RateLimitConfig` defines 4 tiers (human, agent-standard, agent-elevated, agent-platform) but none are enforced. |
 | 3 | **No dedicated typing REST endpoint** | Typing indicators (kind 20002) are delivered via both local fan-out and Redis pub/sub (cross-node). There is no REST endpoint to query current typers — `/api/presence` returns online/away status only, not typing state. |
-| 4 | **sprout-huddle is scaffolding** | `sprout-huddle` defines types, token generation, and webhook parsing, but relay-side lifecycle event emission is not implemented. Huddle state events are not wired into the relay's event pipeline. `sprout-proxy` is now functional — see its section above. |
+| 4 | **Huddle recording/tracks not built** | Voice, room lifecycle, and join/leave/end events are wired (see Huddle Audio above). Recording and per-track publishing have reserved kinds but no producer yet. |
 | 5 | **Approval gates not wired end-to-end** | The executor returns `StepResult::Suspended` and the relay has grant/deny API endpoints with DB CRUD, but the engine intercepts before creating `WaitingApproval` rows — runs that hit an approval gate are marked as Failed (🚧 WF-08). |
-| 6 | **Workflow actions partially stubbed** | `send_dm` and `set_channel_topic` actions log intent but do not emit events (🚧 WF-07). |
-
----
-
-## Appendix: LOC Summary
-
-| Crate | LOC | Layer |
-|-------|-----|-------|
-| sprout-core | 1,196 | Foundation |
-| sprout-auth | 2,310 | Foundation |
-| sprout-db | 7,367 | Foundation |
-| sprout-pubsub | 887 | Foundation |
-| sprout-search | 1,126 | Foundation |
-| sprout-audit | 776 | Foundation |
-| sprout-workflow | 4,012 | Foundation |
-| sprout-proxy | 4,933 | Client compatibility |
-| sprout-huddle | 728 | Standalone |
-| sprout-relay | 14,327 | Server |
-| sprout-mcp | 4,879 | Agent API |
-| sprout-acp | 14,920 | Agent harness |
-| sprout-sdk | 1,237 | Shared library |
-| sprout-media | 977 | Media storage |
-| sprout-cli | 2,919 | Tooling |
-| sprout-admin | 213 | Tooling |
-| sprout-test-client | 9,319 | Tooling |
-| **Total** | **~72,126** | |
-
-*LOC counted with `find crates -name '*.rs' | xargs wc -l`. Includes tests. Measured 2026-04-05.*
-
-
+| 6 | **Workflow actions partially stubbed** | The `send_dm` and `set_channel_topic` workflow actions are in the schema but return `NotImplemented` — a run that reaches one fails at execution (🚧 WF-07). |
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 76f95ef158..44ecd37cb5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -139,7 +139,7 @@ End-to-end tests live in `crates/sprout-test-client/tests/`:
 Run them with (requires running infrastructure):
 
 ```bash
-cargo test -p sprout-test-client
+cargo test -p sprout-test-client -- --ignored
 ```
 
 See `TESTING.md` for the full multi-agent E2E testing guide.
@@ -296,7 +296,6 @@ sprout-acp        ← ACP harness (bridges Sprout relay events to AI agents via
 sprout-proxy      ← Nostr client compatibility layer
 sprout-sdk        ← Typed Nostr event builders (used by sprout-mcp and sprout-cli)
 sprout-media      ← Blossom/S3 media storage
-sprout-huddle     ← LiveKit integration
 sprout-cli        ← Agent-first CLI for interacting with the relay
 sprout-admin      ← Operator CLI
 sprout-test-client← Integration test harness
diff --git a/Cargo.toml b/Cargo.toml
index 200873617b..6dd09adaae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ version = "0.1.0"
 edition = "2021"
 rust-version = "1.88.0"
 license = "Apache-2.0"
-repository = "https://github.com/sprout-rs/sprout"
+repository = "https://github.com/block/sprout"
 
 [workspace.dependencies]
 # Runtime
diff --git a/GOVERNANCE.md b/GOVERNANCE.md
index 6bccf43368..4af3958eed 100644
--- a/GOVERNANCE.md
+++ b/GOVERNANCE.md
@@ -1 +1 @@
-## [Click here for Block Open Source Project governance information](https://github.com/block/.github/blob/main/GOVERNANCE.md)
\ No newline at end of file
+## [Click here for Block Open Source Project governance information](https://github.com/block/.github/blob/main/GOVERNANCE.md)
diff --git a/README.md b/README.md
index bc89abffe6..4e7ae86151 100644
--- a/README.md
+++ b/README.md
@@ -135,7 +135,7 @@ A Rust workspace of focused crates. Single source of truth: the relay. See [ARCH
 
 **Services** — `sprout-db` (Postgres) · `sprout-auth` (NIP-42/98 Schnorr auth, rate limiting) · `sprout-pubsub` (Redis, presence, typing) · `sprout-search` (Typesense) · `sprout-audit` (hash-chain log)
 
-**Agent surface** — `sprout-cli` (agent-first CLI, JSON in / JSON out) · `sprout-acp` (ACP harness for Goose/Codex/Claude Code) · `sprout-agent` (ACP agent — see [VISION_AGENT.md](VISION_AGENT.md)) · `sprout-mcp` (stdio MCP, legacy/optional) · `sprout-dev-mcp` (shell + file-edit tools) · `sprout-workflow` (YAML automation) · `sprout-persona` (agent persona packs) · `sprout-huddle` (LiveKit voice/video)
+**Agent surface** — `sprout-cli` (agent-first CLI, JSON in / JSON out) · `sprout-acp` (ACP harness for Goose/Codex/Claude Code) · `sprout-agent` (ACP agent — see [VISION_AGENT.md](VISION_AGENT.md)) · `sprout-mcp` (stdio MCP — being phased out in favor of the CLI) · `sprout-dev-mcp` (shell + file-edit tools) · `sprout-workflow` (YAML automation) · `sprout-persona` (agent persona packs)
 
 **Git & pairing** — `git-sign-nostr` / `git-credential-nostr` (nostr-signed git) · `sprout-pair-relay` / `sprout-pairing-cli` (relay pairing)
 
diff --git a/VISION.md b/VISION.md
index 0623a408a2..b1e8e32b1f 100644
--- a/VISION.md
+++ b/VISION.md
@@ -68,7 +68,7 @@ New message type? New kind integer. Zero breaking changes.
 
 ## Architecture
 
-Rust backend, TypeScript/React desktop. The server is a Cargo workspace of focused crates — relay, auth, pub/sub, search, audit, workflow engine, MCP agent interface, and more. The desktop client is a Tauri 2 app with React 19. See [README.md](README.md) for the full crate map.
+Rust backend, TypeScript/React clients. The server is a Cargo workspace of focused crates — relay, auth, pub/sub, search, audit, workflow engine, MCP agent interface, and more. The desktop client is a Tauri 2 app with React 19; the relay also serves a browser web client (the repo browser at `myproject.com`). See [README.md](README.md) for the full crate map.
 
 ---
 
@@ -93,13 +93,12 @@ One model. TLS in transit. At-rest encryption delegated to the storage layer (e.
 
 ## Huddles
 
-LiveKit SFU handles all media routing. Sprout provides rooms and tokens.
+Real-time voice runs over a WebSocket Opus relay built into `sprout-relay`. Sprout authenticates participants (NIP-42), admits them to a room, and forwards Opus frames between peers — no external SFU.
 
-- Agents join via the same WebRTC API as humans — they bring their own STT/TTS
-- Huddle state flows as Nostr events (started, joined, left, ended, recording available)
-- Workflows can trigger on huddle events
+- Agents join the same audio relay as humans — they bring their own STT/TTS
+- Huddle lifecycle flows as Nostr events: started, joined, left, ended
 
-LiveKit token minting and kind definitions are in place. Relay-side lifecycle event emission is planned.
+Voice, room lifecycle, and lifecycle events are wired. Recording and per-track publishing are planned.
 
 ---
 
@@ -142,7 +141,7 @@ See [VISION_PROJECTS.md](VISION_PROJECTS.md) for the full forge vision: the proj
 
 ## Agent CLI
 
-`sprout-cli` is a 44-command agent-first CLI covering the full MCP surface. JSON-only stdout, structured errors on stderr, two-tier auth (NIP-98 keypair → dev pubkey). Agents can script the entire platform without a GUI.
+`sprout-cli` is an agent-first CLI that mirrors and extends the MCP surface — same primitives, plus repo, upload, and canvas operations where the CLI is the canonical interface. JSON-only stdout, structured errors on stderr, two-tier auth (NIP-98 keypair → dev pubkey). Agents can script the entire platform without a GUI.
 
 ---
 
@@ -194,18 +193,19 @@ Greenfield. Agent swarms build in parallel, integrating at the event store bound
 | | Area |
 |-|------|
 | ✅ | Core relay, auth, pub/sub, search, audit |
-| ✅ | MCP server — 44 tools, full feature surface |
+| ✅ | MCP server — full feature surface |
 | ✅ | ACP agent harness — goose, codex, claude code |
 | ✅ | Desktop client (Tauri) — Stream, Home, Forum, DMs, Agents, Workflows, Search, Settings, Profiles, Presence |
 | ✅ | Channel features — messaging, threads, reactions, canvases, media uploads, editing, deletion, typing indicators, NIP-29, soft-delete |
 | ✅ | Workflow engine — YAML-as-code, execution traces, message/reaction/schedule/webhook triggers |
 | ✅ | Identity — NIP-05, public profiles, NIP-98 auth, agent protection |
 | ✅ | NIP-28 proxy — third-party Nostr clients (Coracle, nak, Amethyst) via `sprout-proxy` |
-| ✅ | Agent CLI — `sprout-cli`, 44 commands, full MCP surface |
+| ✅ | Agent CLI — `sprout-cli`, mirrors and extends the MCP surface |
 | ✅ | Agent personas and teams — desktop-managed, built-in defaults, operator-defined |
 | 🚧 | Workflow approval gates — infrastructure exists (DB, API, UI); executor doesn't persist/resume (WF-08) |
-| 🚧 | Huddles — LiveKit token minting in place; relay-side lifecycle events not yet wired |
-| 📋 | Mobile clients, developer portal, push notifications, culture features |
+| ✅ | Huddles — WebSocket Opus voice relay + lifecycle events (recording/tracks planned) |
+| 🚧 | Mobile client — Flutter app (channels, forum, search, profile, pairing); in active development |
+| 📋 | Developer portal, push notifications, culture features |
 
 ---
 
diff --git a/VISION_PROJECTS.md b/VISION_PROJECTS.md
index fb4fc73c76..f72fa06b39 100644
--- a/VISION_PROJECTS.md
+++ b/VISION_PROJECTS.md
@@ -217,16 +217,16 @@ If Sprout disappears tomorrow, your repos still work on gitworkshop.dev, your pa
 |---|---|
 | Channels, forums, DMs, canvases | ✅ Ships today |
 | Workflow engine (triggers, traces, conditional logic) | ✅ Ships today |
-| 44-tool MCP server + ACP agent harness | ✅ Ships today |
+| MCP server + ACP agent harness | ✅ Ships today |
 | Blossom media storage (SHA-256, S3) | ✅ Ships today |
 | Approval gates | 🚧 Infrastructure exists; executor wiring in progress |
 | Project binding (kind:30617 + `sprout-` tags) | 📋 Designed |
-| Git hosting (smart HTTP + NIP-34) | 📋 Designed |
+| Git hosting (smart HTTP + NIP-34) | ✅ Ships today |
 | Merge coordinator | 📋 Designed |
 | NIP-34 issues (kind:1621) | 📋 Designed |
 | Web-of-trust reputation | 📋 Designed |
 
-The collaboration platform is built. The forge is the work ahead — wiring git hosting, the merge train, and the reputation system into the surfaces that already exist. See [VISION.md](VISION.md) for the platform and [VISION_SOVEREIGN.md](VISION_SOVEREIGN.md) for the sovereign relay story.
+The collaboration platform is built, and git hosting ships today — `git clone`/`git push` over smart HTTP with NIP-34 manifests. The forge layer above it is the work ahead — the merge train, project binding, issues, and the reputation system, wired into the surfaces that already exist. See [VISION.md](VISION.md) for the platform and [VISION_SOVEREIGN.md](VISION_SOVEREIGN.md) for the sovereign relay story.
 
 ---
 
diff --git a/crates/sprout-core/src/kind.rs b/crates/sprout-core/src/kind.rs
index 9691ed253b..6df14ac548 100644
--- a/crates/sprout-core/src/kind.rs
+++ b/crates/sprout-core/src/kind.rs
@@ -1,6 +1,6 @@
 //! Sprout V2 kind number registry.
 //!
-//! Authoritative source: RESEARCH/SPROUT_KIND_REGISTRY_V2.md
+//! This module is the authoritative source for Sprout kind numbers.
 //! All constants are `u32` — NIP-01 specifies kind as an unsigned integer,
 //! and u32 covers the full range without truncation.
 
diff --git a/crates/sprout-mcp/src/lib.rs b/crates/sprout-mcp/src/lib.rs
index 2efa713a45..93ab79357a 100644
--- a/crates/sprout-mcp/src/lib.rs
+++ b/crates/sprout-mcp/src/lib.rs
@@ -61,40 +61,13 @@
 //!
 //! ## Available Tools
 //!
-//! 42 tools total, organized into toolsets. Tools are organized into toolsets. Set
-//! `SPROUT_TOOLSETS` to control which are active (default: 25 core tools).
-//!
-//! ### Messaging (default toolset)
-//! - **`send_message`** — Post a message to a channel.
-//! - **`send_diff_message`** — Post a diff-formatted message.
-//! - **`edit_message`** — Edit an existing message.
-//! - **`delete_message`** — Delete a message.
-//! - **`get_messages`** — Fetch recent messages from a channel (default 50, max 200).
-//! - **`get_thread`** — Fetch replies in a message thread.
-//! - **`search`** — Full-text search across channels.
-//! - **`get_feed`** — Retrieve the agent's personalized home feed (mentions, needs-action
-//!   items, channel activity). Replaces the former `get_feed_mentions` / `get_feed_actions`.
-//! - **`add_reaction`** / **`remove_reaction`** / **`get_reactions`** — Emoji reactions.
-//!
-//! ### Channels (default toolset)
-//! - **`list_channels`** / **`get_channel`** — List or inspect channels.
-//! - **`join_channel`** / **`leave_channel`** — Membership management.
-//! - **`update_channel`** / **`set_channel_topic`** / **`set_channel_purpose`** — Metadata.
-//! - **`open_dm`** — Open a direct-message channel.
-//! - **`list_channel_members`** — List members of a channel.
-//!
-//! ### Channel Admin (`channel_admin` toolset)
-//! - **`create_channel`** / **`archive_channel`** / **`unarchive_channel`**
-//! - **`add_channel_member`** / **`remove_channel_member`**
-//!
-//! ### Canvas (`canvas` toolset)
-//! - **`get_canvas`** — Retrieve the shared canvas document for a channel.
-//! - **`set_canvas`** — Write or replace the canvas document for a channel.
-//!
-//! ### Workflows
-//! - **`trigger_workflow`** / **`approve_step`** — Trigger and approve steps (default toolset).
-//! - **`list_workflows`** / **`create_workflow`** / **`update_workflow`** /
-//!   **`delete_workflow`** / **`get_workflow_runs`** — Workflow admin (`workflow_admin` toolset).
+//! Tools are organized into toolsets; set `SPROUT_TOOLSETS` to control which are
+//! active. The authoritative list and per-toolset grouping is `ALL_TOOLS` in
+//! [`toolsets`] — this doc deliberately doesn't duplicate it, since a hand-copied
+//! list drifts. The default toolset covers messaging, threads, search, feed,
+//! reactions, channel basics, DMs, profiles/presence, and workflow triggers;
+//! opt-in toolsets add channel admin, canvas, workflow admin, forums, social,
+//! and media.
 //!
 //! ## Example Configuration (Claude Desktop)
 //!
@@ -113,7 +86,7 @@
 //! }
 //! ```
 //!
-//! [Sprout]: https://github.com/sprout-rs/sprout
+//! [Sprout]: https://github.com/block/sprout
 //! [NIP-42]: https://github.com/nostr-protocol/nips/blob/master/42.md
 
 // NOTE: `parse_relay_message`, `OkResponse`, and `RelayMessage` from `relay_client`
diff --git a/crates/sprout-persona/Cargo.toml b/crates/sprout-persona/Cargo.toml
index 2c33c5df04..d431aa7ec3 100644
--- a/crates/sprout-persona/Cargo.toml
+++ b/crates/sprout-persona/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2021"
 description = "Parser and loader for Sprout persona pack files (.persona.md)"
 license = "Apache-2.0"
-repository = "https://github.com/sprout-rs/sprout"
+repository = "https://github.com/block/sprout"
 
 [dependencies]
 serde = { version = "1", features = ["derive"] }
diff --git a/crates/sprout-relay/src/nip11.rs b/crates/sprout-relay/src/nip11.rs
index 7cbff06d26..67e75fedb4 100644
--- a/crates/sprout-relay/src/nip11.rs
+++ b/crates/sprout-relay/src/nip11.rs
@@ -119,7 +119,7 @@ impl RelayInfo {
             pubkey: None,
             contact: None,
             supported_nips,
-            software: "https://github.com/sprout-rs/sprout".to_string(),
+            software: "https://github.com/block/sprout".to_string(),
             version: env!("CARGO_PKG_VERSION").to_string(),
             limitation: Some(relay_limitation()),
             relay_self: relay_self.map(|s| s.to_string()),
