# hyperhive — claude entry point Hey claude. This is your starting page. The detailed docs live in [`docs/`](docs/) and are written for humans + you both — read them when you need depth on a subsystem. This file is the index. - High-level project intro: **[README.md](README.md)**. - Open work + backlog: the forge issue tracker at **`$HIVE_FORGE_URL/hyperhive/hyperhive/issues`**. Read the host out of the env var — inside an agent container `localhost` is the *agent*, not the forge, so a hardcoded loopback address fails to connect. - Operator/agent trust-boundary design: **[docs/boundary.md](docs/boundary.md)** (`area/ops` issues for the deployment/gateway/privsep work — the separator is a **slash**; `--label area:ops` matches nothing and silently returns *unfiltered* results, which reads like a backlog rather than like an error). - Agent trust model (trust boundary, prompt-injection threat model, capability = accepted risk), credential isolation + sandbox threat model: **[docs/security.md](docs/security.md)**. ## Repo map One line per crate / top-level dir. **Each module's authoritative, always-current description lives in its own `//!` doc-comment** — `grep`/read the module when you need detail. This index is kept deliberately lean: it auto-loads into every turn's context, and a hand-maintained per-file tree drifts out of sync with the code. ### Rust workspace (`Cargo.toml` members) - **`hive-c0re/`** — host daemon (runs as the unprivileged `hive-core` user). `src/main.rs` is the `hive-c0re` binary — **daemon-only** (`serve` + the periodic vacuum/sweep loops); the operator CLI lives in the separate `hivectl` crate, which talks to the daemon over the host admin socket. Owns the sqlite broker, approval + question + reminder + schedule queues, the meta flake, lifecycle (`nixos-container` shellouts), gateway / forge / matrix provisioning, per-container stats, and the axum operator dashboard (`dashboard.rs`). Largest crate. - **`hivectl/`** — standalone operator CLI (`hivectl` binary). Talks to the `hive-c0re` daemon over the host admin socket (`hive-host-sock` wire types) — does NOT link `hive-c0re`. Full, always-current verb reference (CI-enforced against the clap tree, see `docs/conventions.md`): [`docs/tools/hivectl-cli.md`](docs/tools/hivectl-cli.md). - **`hive-agent/`**, **`hive-agent-mcp/`** — in-container harness, two sibling crates for every agent (not a single `hive-ag3nt/` dir — that's the runtime/binary-family nickname, not a directory). - **`hive-agent/`** — the serve-loop binary: turn-loop *policy* layer (`turn.rs`) over the `hive-claude` driver, per-agent web UI (`web_ui/` module dir), event + turn-stats sqlite sinks, login flow, system-prompt renderer. - **`hive-agent-mcp/`** — the embedded MCP server (long-lived streamable-http listener, `hive-mcp-http` systemd unit) + its claude launch-config layer (tool-group/capability → `--allowedTools`, `--mcp-config` render). - **`hive-jobq/`** — job-DAG scheduler, extracted from hive-c0re's in-tree `job_queue` as a domain-agnostic library. **Runtime-only — nothing writes the graph to disk**; hive-c0re starts empty each boot and re-derives desired state via the reconcile sweep, so node ids and timestamps are stable within a run, not across restarts. One shared graph for the whole system (not a DAG per job); enqueuing inserts a self-contained sub-DAG and returns the ids of the nodes the job asked for, in the order it named them. Generic over the node payload `N` and the resource name `R`; resource deps are named counting semaphores acquired all-or-nothing at node start. `hive-c0re`'s remaining `job_queue/` module is the c0re-specific layer *over* this crate, and is being removed in favour of it — new scheduler-shaped code belongs here, not there. - **`hive-jobq-wire/`** — wire types for serving a `hive-jobq` graph to a viewer, plus the `WireNode` / `WireResource` traits a host implements to say how its `N` and `R` render. Deliberately *not* part of `hive-jobq`: that crate is logic, this is presentation, and folded together they remix. `GraphWire::wire_snapshot` is blanket-implemented for any `Graph` whose parameters implement both — so a payload that has never said how it displays cannot reach a viewer at all. - **`hive-screen-mcp/`** — stdio MCP bridge for GUI agents (`hyperhive.gui.enable`): `screenshot` via `grim`, `type_text` / `key_press` via `wtype` (Wayland virtual-keyboard protocol), and `mouse_move` / `mouse_click` as RFB pointer events to the local neatvnc server. All userspace, no daemon of its own. - **`hive-priv/`** — minimal root privileged-helper, socket-activated at `/run/hive/priv.sock`; performs the few root operations (bind-mount edits, nsenter) the unprivileged `hive-c0re` delegates to it. See `docs/boundary.md`. - **`hive-forge/`** — `hive-forge` Forgejo CLI wrapper; one module per verb under `src/verbs/`. - **`hive-forge-notify/`** — per-agent notification poller daemons; turns unread notification threads into todos on the harness's in-agent socket. Two binaries from one crate: `hive-forge-notify` (the hive's Forgejo) and `hive-github-notify` (github.com, installed by `nix/agent-modules/github.nix`). Was a task inside the `hive-agent` serve loop; own process since it needs nothing else from the harness. - **`hive-matrix-mcp/`** — per-agent matrix-sdk daemon (`hive-matrix-daemon`); serves its MCP tools (`send_message`, `read_room`, …) directly over streamable-http (no stdio bridge), same shape as `hive-bash-mcp`. - **`hive-bash-mcp/`** — per-agent bash-task runner daemon (`hive-bash-daemon`); serves its MCP tools (`run`/`status`/`kill`) directly over streamable-http (no stdio bridge), writes task files under `/harness/bash-tasks/`, and records the favorite-tools `bash_commands` stat into turn-stats.sqlite. - **`hive-sh4re/`** — shared wire types (Agent / Manager request + response, `Message`, `Approval`, `HelperEvent`) used across the unix sockets. Host-admin-socket and hive-priv-socket wire types have been split out into their own crates (below) so `hivectl` and `hive-priv` don't need to pull in the rest of `hive-sh4re`. - **`hive-host-sock/`** — wire types for the host admin socket (`/run/hyperhive/host.sock`), the protocol `hivectl` speaks to `hive-c0re`. Split out of `hive-sh4re` so a standalone `hivectl` only depends on this protocol crate, not the whole daemon crate. - **`hive-priv-sock/`** — wire types for the `hive-priv` privileged-helper socket (`/run/hive/priv.sock`), shared by `hive-priv` (server) and `hive-c0re` (client). Also split out of `hive-sh4re`. - **`hive-core-agent-sock/`** — wire types for the *host*-served per-agent + manager socket (`/run/hive/mcp.sock`), the protocol an agent's harness speaks to `hive-c0re`. Same split rationale as the two above; the shared payload types it references stay in `hive-sh4re`. - **`hive-agent-sock/`** — wire types for the *in-agent* socket, served by the harness to in-container producers — matrix / bash MCP daemons and `forge_notify` are the built-in ones, but any user-configured MCP server can push todos here too, nothing restricts the `subsystem` set. Carries the loose-ends-v2 **todo** ops plus harness-local reminders + questions. ⚠️ Distinct from `hive-core-agent-sock` above: **this socket never leaves the container** and `hive-c0re` is not in the path at all — no broker round-trip, no long-poll, no marker files. - **`hive-types/`** — zero-dependency (bar serde) leaf crate holding the foundational newtypes, chiefly `Ident` (1–63 chars of `[a-z0-9-]`, constructed only via the validating parser). Lets every wire-type crate and both binaries type their agent-name fields as a validated ident and get serde-checked parsing at the socket boundary, without coupling to `hive-sh4re`. - **`hive-sock-client/`** — the shared JSON-line-over-unix-socket client every daemon uses to talk to a hyperhive socket. Generic over the request/response types, so the host-served control socket and the harness's in-agent socket both use it with their own wire-type crates. Retry is a policy value (`Retry::None` for callers already inside a poll loop, `Retry::RideOutRestart` for callers with no natural retry), and the response is either decoded (`request`) or drained (`notify`). Deliberately separate from the `*-sock` crates — those stay dependency-free wire types. - **`hive-metric/`** — small CLI to push a single labeled metric to the OTEL collector via the OpenTelemetry Rust SDK / OTLP HTTP exporter. - **`swarm-controller/`** — swarm-level daemon, opt-in per host (`services.hyperhive.swarm.controller.enable`). Where `hive-c0re` owns the agents on **one** host, this owns what is true **across** hives; a swarm runs one of them, so most hives leave it off. Serves HTTP over a unix socket the gateway's nginx proxies to — ⚠️ **the socket's directory is its access control**; the constraint that governs it is in the crate's README, and a unit test pins the path. - **`swarmctl/`** — swarm-level operator CLI, installed by the swarm-controller module on the host that runs the daemon. Runs as **root and acts directly** — no socket, no HTTP route, no priv helper; the crate's README records why the rootless shape was examined and rejected. Does not link `swarm-controller`, mirroring `hivectl` ÷ `hive-c0re`. ⚠️ Its user store is **two files, one authoritative**: `users.json` is canonical, authelia's `users.yml` is a *rendered artifact* that is written and never read back. Full, always-current verb reference (CI-enforced against the clap tree, same pattern as `hivectl`'s — see `docs/conventions.md`): [`docs/tools/swarmctl-cli.md`](docs/tools/swarmctl-cli.md). ### External dependencies with no directory here - **`hive-claude`** — reusable, app-agnostic driver for headless `claude --print`: spawns the CLI, streams + classifies stream-json, parses per-turn `Telemetry`, and drives a durable self-compacting `InfiniteSession` (name + `SessionStore` + `CompactionPolicy`). Uses `thiserror` (it's a library); the `hive-*` binaries consume it with `anyhow`. ⚠️ **Its own repo, not a workspace member** — consumed as a dependency in the root `Cargo.toml`, so there is no `hive-claude/` directory to read and `grep` here will not find it. ### Other top-level dirs - **`frontend/`** — npm workspaces → static dashboard + per-agent UI dist, built hermetically by `nix/packages/frontend.nix`. Packages: `shared` (terminal pane + Catppuccin palette), `dashboard` (the operator SPA), `agent` (the default per-container UI), `swarm-ui` (swarm-level UI shell — Preact + wouter + TypeScript + JSX, project- bootstrap scope; packaged separately by `nix/packages/swarm-ui.nix`, not bundled into `packages.default`'s closure — see that file). - **`nix/`** — `host-modules/` (the host stack: hyperhive core options, `hive-{c0re,priv,forge,gateway,matrix,network,tls,ci}`, otel, swarm), `agent-modules/` (the per-agent harness feature modules), `templates/{agent,ruth}.nix` (container entry points), `packages/` (flake package outputs), `docs/` (the options-doc derivation), plus `sources.nix` / `rust.nix` / `checks.nix` / `devshell.nix` / `treefmt.nix` behind the thin `flake.nix`. - **`docs/`** — subsystem reference docs (see *Reading paths* below). - **`branding/`**, **`scripts/`** — static assets + helper scripts. ## Reading paths Pick the doc that matches your task. None depend on the others — read them à la carte. - **"How do I bring a fresh hive online (first-run hivectl bootstrap)?"** → [`docs/setup.md`](docs/setup.md). - **"What does the dashboard look like?"** → [`docs/web-ui.md`](docs/web-ui.md) (index; sub-pages: [`shape`](docs/web-ui/shape.md), [`dashboard`](docs/web-ui/dashboard.md), [`agent`](docs/web-ui/agent.md)). - **"How does the per-agent terminal classify + colour events?"** → [`docs/terminal-rendering.md`](docs/terminal-rendering.md). - **"How does claude get its prompt and what tools does it have?"** → [`docs/turn-loop/`](docs/turn-loop/README.md) (index: the loop, binary shape, turn outcomes; sub-pages: [`claude-invocation`](docs/turn-loop/claude-invocation.md), [`config`](docs/turn-loop/config.md), [`mcp`](docs/turn-loop/mcp.md)). - **"How do config changes flow from manager to operator to container?"** → [`docs/approvals.md`](docs/approvals.md). - **"What state survives destroy / purge / restart?"** → [`docs/persistence.md`](docs/persistence.md). - **"Naming, commit style, wire protocol, the `data-async` pattern."** → [`docs/conventions.md`](docs/conventions.md). - **"Why does the nspawn flag look like that?"** → [`docs/gotchas.md`](docs/gotchas.md). - **"What nginx vhosts does the gateway serve? How does matrix discovery work?"** → [`docs/gateway.md`](docs/gateway.md). - **"How do per-agent forge accounts work? What does forge_notify poll + how does it format wake messages?"** → [`docs/forge.md`](docs/forge.md). - **"What verbs does `hive-forge` support? How do I post a comment, upload an attachment, manage subscriptions?"** → [`docs/tools/forge.md`](docs/tools/forge.md). - **"What does `hivectl` do? How do I provision a forge/matrix account, manage gateway users, restart containers, or drop into an agent shell?"** → [`docs/tools/hivectl.md`](docs/tools/hivectl.md). - **"How does the matrix-tuwunel container work? What about fluffychat-web and per-agent matrix accounts?"** → [`docs/matrix.md`](docs/matrix.md). - **"How do I give an agent a GitHub account (`gh` + `git push`)? How is the PAT injected?"** → [`docs/github.md`](docs/github.md). - **"How does DNS resolution work in agent containers? What's the bridge network for?"** → [`docs/network.md`](docs/network.md). - **"How do I connect two hives into a swarm? How do I declare peer hives and configure TLS trust?"** → [`docs/swarm/`](docs/swarm/README.md). - **"Where do agent snapshots go? How does the swarm's `btrfs receive` endpoint authenticate a pushing hive, and what does a snapshot actually contain?"** → [`docs/snapshot-store.md`](docs/snapshot-store.md). - **"How does the rebuild queue work? What are queue kinds and sources?"** → [`docs/coordinator.md`](docs/coordinator.md). - **"How does the CI runner work? What's the auto-registration flow?"** → [`docs/ci.md`](docs/ci.md). - **"What is `/knowledge`? How does the hive-wide knowledge repo sync, and how do I contribute a document?"** → [`docs/knowledge.md`](docs/knowledge.md). - **"How do I export Claude Code metrics (tokens, cost, tool calls) to a Prometheus/Grafana collector? What OTEL options are available?"** → [`docs/observability.md`](docs/observability.md). - **"What does a PR review verdict actually gate? Should a reviewer wait for CI before approving? What does arming auto-merge commit an operator to?"** → [`docs/pr-review-gate.md`](docs/pr-review-gate.md). ## Conventions & process The docs below own the details — this section just points at them. - **Commit style, naming, identity, reconcile verb:** → [`docs/conventions.md`](docs/conventions.md). - **Never add `#[allow(clippy::…)]`** — fix the lint instead (extract a helper, add backticks, etc.). Details + worked examples: → [`docs/conventions.md`](docs/conventions.md#building--local-checks). - **NixOS / nspawn quirks** (bind mounts, conf flags, etc.): → [`docs/gotchas.md`](docs/gotchas.md). - **Turn loop, sentinels (rate-limit, auth-failed), context window:** → [`docs/turn-loop/`](docs/turn-loop/README.md). - **Two-step spawn, approval flow, flake.lock validation:** → [`docs/approvals.md`](docs/approvals.md). - **Pre-push lint hook** (catches tracker-tag and comment-block failures before CI does — install once per clone): `ln -sf ../../scripts/pre-push .git/hooks/pre-push`