hyperhive/CLAUDE.md

24 KiB

hyperhive — claude entry point

Hey claude. This is your starting page. The detailed docs live in docs/ and are written for humans + you both — read them when you need depth on a subsystem. This file is the index.

File map

hive-c0re/         host daemon + sibling operator CLI (lib + 2 bins)
  src/lib.rs            `pub mod` re-exports for every module; shared by
                         both binaries so they import from the same
                         tree (no per-bin module duplication).
  src/main.rs           hive-c0re binary: clap setup; serve / spawn /
                         kill / rebuild / list / pending / approve /
                         deny / destroy [--purge] / request-spawn /
                         set-parent (--parent / --root); periodic
                         vacuum tasks.
  src/bin/hivectl.rs    `hivectl` binary: operator-facing host CLI
                         for ad-hoc administration that doesn't go
                         through the broker. v0 verbs: `forge
                         create-user <name>`, `matrix create-user
                         <name>` — wrap the same idempotent
                         `forge::ensure_user_for` /
                         `matrix::ensure_user_for` flows c0re runs
                         in its boot sweeps, callable manually for
                         recovery / debug.
  src/server.rs         host admin socket (HostRequest → dispatch)
  src/client.rs         admin-socket client
  src/manager_server.rs manager-privileged socket (ManagerRequest)
  src/agent_ports.rs    writes `/var/lib/hyperhive/agent-ports.json` on
                         meta sync; gateway reads name→port map for
                         per-agent `/agent/<name>/` routing.
  src/agent_sockets.rs  writes `/var/lib/hyperhive/agent-sockets.json` on
                         meta sync; gateway reads name→socket-path
                         map for unix-domain per-agent UI binding.
                         Entries are filtered by a `hyperhive-socket-bound` marker file
                         the harness drops next to its socket after a
                         successful `bind()` — pre-bind agents stay out
                         of the map so the gateway never races a
                         missing-socket upstream. A 10s poll loop
                         (`spawn_poll`) re-fires the writer so the map
                         reconverges if a marker appears between
                         meta-sync ticks.
  src/agent_server.rs   per-sub-agent socket listener (long-poll Recv)
  src/broker.rs         sqlite Message store + intra-process broadcast
                         channel (`MessageEvent`) for `recv_blocking_batch` +
                         the dashboard forwarder; hourly vacuum of acked>30d
  src/dashboard_events.rs unified wire-facing event channel feeding
                         `/dashboard/stream`. Carries broker `Sent` /
                         `Delivered` (mirrored by the forwarder task
                         in main.rs) + mutation events
                         (`ApprovalAdded` / `ApprovalResolved`,
                         `QuestionAdded` / `QuestionResolved`,
                         `TransientSet` / `TransientCleared`,
                         `RebuildQueueChanged`). Each frame carries a
                         monotonic per-process `seq` clients use to
                         dedupe against snapshot reads.
  src/approvals.rs      sqlite Approval queue + kinds
  src/operator_questions.rs  sqlite question queue backing `ask` /
                         `answer` (both operator + agent-to-agent)
  src/questions.rs      shared dispatch for `Ask` / `Answer` —
                         used by both agent + manager surfaces
  src/reminder_scheduler.rs  5s poll loop: drains due reminders,
                         resolves file_path container→host, persists
                         payload + delivers pointer string
  src/scheduled_prompts.rs  sqlite layer for scheduled prompts —
                         schema, CRUD helpers (`cancel_all`,
                         `cancel_targets`, `reap_cancelled`), catch-up
                         clamp on resume
  src/scheduled_prompts_worker.rs  5s poll loop: fires due rows,
                         fans out one Message per active target,
                         re-arms recurring rows, deletes fired one-shots
  src/events_vacuum.rs  host-side hourly sweep of every agent's
                         /harness/hyperhive-events.sqlite
  src/stats_vacuum.rs   host-side hourly sweep of every agent's
                         /harness/hyperhive-turn-stats.sqlite —
                         90-day age-only retention
  src/bash_tasks_vacuum.rs  host-side hourly sweep of every agent's
                         harness/bash-tasks/ — deletes terminal task
                         trios (.json/.out/.err) older than 48h
  src/crash_watch.rs    poll every 10s; fire HelperEvent::ContainerCrash
                         when a previously-running container disappears
                         without an operator-initiated transient (or a
                         RECENT_TRANSIENT_GRACE tombstone within the
                         last 30s)
  src/container_view.rs ContainerView struct + build_all helper;
                         shared between dashboard.rs (cold-load via
                         /api/state) and coordinator.rs's
                         rescan_containers_and_emit
  src/coordinator.rs    shared state (broker/approvals/operator_questions/
                         transient/sockets) + tombstone enumeration +
                         kick_agent + notify_agent (helper-event push) +
                         last_containers cache + rescan_and_emit diff helper
  src/loose_ends.rs     loose-ends aggregator (pending approvals +
                         unanswered questions + pending reminders) —
                         for_agent (filtered) and hive_wide (manager
                         surface). Backs AgentRequest::GetLooseEnds +
                         ManagerRequest::GetLooseEnds (the
                         get_loose_ends MCP tool).
  src/rebuild_queue.rs  global serialised queue for long-running ops
                         (rebuild / meta_update / spawn / destroy /
                         startup_sweep).
                         Single background worker drains FIFO; dedup
                         collapses re-enqueued still-queued entries.
                         `QueueEntry` carries id, agent, kind, state,
                         source, parent_id (cascade grouping), timing,
                         reason, error, step (current phase label while
                         Running; cleared on finish). Emits
                         `RebuildQueueChanged` snapshots on every
                         mutation.
  src/actions.rs        approve/deny/destroy (transient-aware)
  src/auto_update.rs    startup rebuild scan + ensure_manager +
                         meta::lock_update_hyperhive bump
  src/lifecycle.rs      `nixos-container` shellouts; per-agent applied
                         + proposed git repo seeding; tag plumbing
  src/meta.rs           single hive-c0re-owned flake at /var/lib/
                         hyperhive/meta/ — sync_agents, two-phase
                         prepare/finalize/abort, lock_update_*
  src/migrate.rs        startup auto-migration from pre-meta layout
                         (idempotent, marker-guarded phase 4)
  src/topology.rs       agent parent/child storage at
                         /var/lib/hyperhive/meta/topology.json — sole
                         source of truth for who's the parent of whom
                         (single source the dashboard, render_flake,
                         and the eventual cap-enforcement plumbing all
                         read). Reconciled by `meta::sync_agents`;
                         operator/manager edits land via the
                         eventual write API.
  src/tool_groups.rs    per-agent tool-group config — reads/writes
                         `/var/lib/hyperhive/meta/tool-groups.json`;
                         `set_groups` + `groups_for` + `remove_agent`.
                         Wired into `render_flake` for `HIVE_TOOL_GROUPS`
                         injection; operator write via dashboard action.
  src/limits.rs         wire-protocol size limits (inline body cap,
                         reminder spill threshold) shared across agent
                         + manager sockets. Single source of truth.
  src/flake_check.rs    pre-apply `flake.lock` validation — rejects
                         proposals missing `inputs.<X>.follows` wiring
                         (duplicate `original` node check).
  src/forge.rs          optional Forgejo wiring: per-agent users +
                         tokens, the `agent-configs` org (`push_config`),
                         and meta read access; mirrors each applied repo
                         into `agent-configs/<n>` (core-only); agents are
                         read-only collaborators on `core/meta`
  src/matrix.rs         optional matrix-tuwunel wiring: generates the
                         shared registration token at
                         `/var/lib/hyperhive/matrix-register-token`,
                         provisions per-agent matrix accounts via the
                         matrix-spec UIAA two-leg registration flow,
                         persists each agent's access_token to
                         `<state>/matrix-token`. Idempotent — skips
                         registration when token file already exists.
                         No-op when `hive-matrix` container absent.
  src/dashboard.rs      axum HTTP: /api/state JSON + actions
                         + journald viewer + bind-with-retry (SO_REUSEADDR)
                         + deployed_sha chip per container +
                         /dashboard/{stream,history} subscribing to the
                         unified DashboardEvent channel. Static assets
                         (HTML/CSS/JS/favicon) served by
                         tower_http::ServeDir from $HIVE_STATIC_DIR
                         (= `${frontend}/dashboard` per the c0re module).

frontend/             npm workspaces (esbuild → static dist). Built
                       hermetically by `nix/frontend.nix`
                       (`packages.${system}.frontend`).
  packages/shared/      @hive/shared: terminal pane + Catppuccin palette
                         + base typography (was hive-fr0nt). ES module
                         exporting { create, linkify }; pure JS, no IIFE
                         globals; consumed by dashboard + agent.
  packages/dashboard/   @hive/dashboard SPA: src/{index.html, tabs.js,
                         flow.html, flow.js, common.js, dashboard.css} +
                         build.mjs → dist/{index.html, flow.html,
                         static/{tabs.js, flow.js, dashboard.css,
                         stream-worker.js}}.
  packages/agent/       @hive/agent default per-container UI: src/
                         {index, stats, screen}.html + {app, stats}.js
                         + agent.css → dist/{*.html, static/*}.

hive-ag3nt/        in-container harness crate; produces ONE `hive`
                   binary picking role from `HIVE_ROLE` env
  src/lib.rs            re-exports + DEFAULT_SOCKET, DEFAULT_WEB_PORT
  src/client.rs         generic JSON-line request/response over unix socket
  src/web_ui.rs         per-container axum HTTP page (incl /api/cancel,
                         /api/compact, /api/model, /events/history,
                         /screen, /screen/ws)
  src/turn_stats.rs     per-turn analytics sink (one sqlite row per
                         turn at /harness/hyperhive-turn-stats.sqlite);
                         schema + best-effort writer
  src/stats.rs          read-side aggregations over turn-stats.sqlite
                         backing the /stats page (bucketed Snapshot:
                         turns / duration / tokens / model mix)
  src/events.rs         LiveEvent + broadcast Bus + sqlite-backed history
                         (/harness/hyperhive-events.sqlite) + TurnState +
                         model selection (persisted at /harness/hyperhive-model)
  src/turn.rs           claude --print + stream-json pump; --compact retry;
                         proactive compaction + auto session-reset
  src/mcp.rs            embedded MCP server (rmcp): AgentServer + ManagerServer
  src/forge_notify.rs   Forgejo webhook subscriber: formats new-issue /
                         new-PR / comment / review notifications as
                         broker messages; embeds a body excerpt
                         (up to BODY_TRUNCATE bytes, ATX headings
                         escaped) and surfaces any @mention lines that
                         fell outside the truncation window in a
                         trailing `mentions (truncated from body):`
                         block.
  src/identity.rs       hive-qualified agent label: `label()` /
                         `qualified_label()` / `qualify(label)`. Reads
                         `HYPERHIVE_HIVE_DOMAIN`; falls back to short
                         name when unset. Display-name accessors:
                         `hive_name()` / `swarm_name()` read
                         `HYPERHIVE_HIVE_NAME` / `HYPERHIVE_SWARM_NAME`,
                         both `Option<String>`.
  src/login.rs          probe $HOME/.claude/ (= `/home/<agent>/.claude`)
                         for a valid session
  src/login_session.rs  drives `claude auth login` over stdio pipes
  src/prompt.rs         system prompt renderer: filters the unified
                         template through `<!-- role:agent -->` /
                         `<!-- role:manager -->` markers per
                         `mcp::Flavor`; owns `write_system_prompt`
                         (re-exported from turn.rs for callers).
  src/bin/hive.rs       unified harness main (Serve + Mcp + Wake
                         subcommands); role from `HIVE_ROLE` env, picks
                         agent or manager wire surface server-side. Static UI assets
                         served by ServeDir from $HIVE_STATIC_DIR
                         (= hyperhive.frontend.mergedDist — default agent
                         dist + per-agent extraFiles, set per the
                         harness-base module).
  prompts/              static role/tools/settings for claude (include_str!):
                          system.md — unified system prompt; shared
                            sections plus `<!-- role:agent -->` /
                            `<!-- role:manager -->` blocks filtered by
                            `prompt::render` per flavor
                          claude-settings.json — --settings JSON

hive-forge/        Forgejo CLI wrapper (`hive-forge` binary)
  src/main.rs           clap dispatch over the verbs/
  src/client.rs         blocking reqwest client (Forgejo REST API)
  src/body.rs           body input resolution (--body / --body-file / piped stdin)
  src/verbs/<verb>.rs   one module per verb (view, issue, pr, comment,
                         comments, comment-show, comment-edit, issue-create,
                         issue-edit, pr-create, pr-reviews, assign,
                         close, labels, list, milestone, branches,
                         tree-sha, diff, subscription, attach-issue,
                         attach-comment, lint). Replaces the 600-line
                         hive-forge-tools.nix bash script.

hive-matrix-mcp/   per-agent matrix-sdk integration.
  src/main.rs           `hive-matrix-daemon` binary entry — long-running
                         matrix-sdk Client + sync per agent; serves the
                         MCP bridge over /run/hive-matrix/socket; emits
                         hyperhive wake on incoming room events.
  src/bin/mcp.rs        `hive-matrix-mcp` stdio bridge claude spawns per
                         turn — connects to the daemon socket, forwards
                         each tool call (send_message, send_dm,
                         send_reaction, send_reply, mark_read, list_rooms,
                         list_room_members, read_room). No matrix-sdk dep
                         at this entrypoint (pure serde + tokio I/O).
  src/{client,handlers,socket,timeline,wake,protocol,paths}.rs
                         shared library modules (matrix-sdk session
                         restore, request dispatch, unix socket server,
                         event handler → wake bridge, wire types, env
                         resolution).

hive-sh4re/        wire types (HostRequest/Response, AgentRequest/Response,
                   ManagerRequest/Response, Message, Approval, HelperEvent)

nix/
  modules/hive-c0re.nix         systemd service + firewall + git wiring;
                                 `contextWindowTokens` attrset (per-model,
                                 injected as env vars into all containers);
                                 top-level `services.hyperhive.domain` option
                                 (nullable; required when matrix.enable);
                                 imports hive-forge.nix + hive-gateway.nix + hive-matrix.nix
  modules/hive-forge.nix        optional in-container Forgejo
                                 (`services.hyperhive.forge.enable`, default on);
                                 `forge.domain` (default `forge.<hive-domain>`) drives
                                 ROOT_URL + gateway vhost; Catppuccin Mocha theme
  modules/hive-gateway.nix      nginx nixos-container in front of all hyperhive
                                 surfaces (`services.hyperhive.gateway.enable`,
                                 default on); proxies `/` → c0re dashboard,
                                 `/agent/<name>/` → per-agent UI (driven by
                                 c0re-written JSON at `gateway.agentPortsFile`),
                                 `forge.<hive-domain>` sub-domain → forge; `/matrix/`
                                 → fluffychat-web; `.well-known/matrix/` auto-discovery
  modules/hive-matrix.nix       optional in-container matrix-tuwunel
                                 homeserver (`services.hyperhive.matrix.enable`,
                                 default off); server_name defaults to bare
                                 `services.hyperhive.domain`; gateway serves
                                 `.well-known/matrix/{client,server}` for
                                 auto-discovery; federation on, e2ee deferred
  templates/harness-base.nix    shared harness for all containers; `hyperhive.role`
                                 (`"agent"` | `"manager"`) drives service unit + forge
                                 defaults; `hyperhive.model` option (HIVE_DEFAULT_MODEL)
  templates/agent-base.nix      thin role-setter (`hyperhive.role = "agent"`)
  templates/manager.nix         thin role-setter (`hyperhive.role = "manager"`)
  templates/weston-vnc.nix      optional `hyperhive.gui.enable`
                                 — weston + VNC backend systemd unit; writes
                                 /etc/hyperhive/gui.json (vnc_port + auth) for
                                 the harness WebSocket relay (/screen/ws)
  docs/                          HTML+MD options reference (host + agent); built
    default.nix                  via `nix build .#docs` → static site
    style.css                    (`index.html`, `host.html`, `agent.html`,
                                 `host.md`, `agent.md`); rendered by cmark-gfm
  forge-theme/theme-catppuccin-vibec0re.css  Catppuccin Mocha forge theme

docs/
  conventions.md       naming, identity=socket, tool groups, async forms, commit style
  gotchas.md           NixOS / nspawn quirks and lessons learned
  web-ui.md            index → web-ui/shape.md (shared skeleton, SSE,
                       terminal, listener bind, relative paths, atomic
                       repaint, side panel), web-ui/dashboard.md (tab
                       contents, container row, topology, selection bar,
                       approval card, endpoints + event channel),
                       web-ui/agent.md (header, terminal, composer,
                       inbox, live view, per-agent endpoints, stats)
  turn-loop.md         claude invocation, wake prompt, MCP tool surface
  approvals.md         approval flow, manager policy, helper events
  persistence.md       sqlite dbs, retention, state dir layout
  terminal-rendering.md  per-agent terminal row taxonomy (as built)
  boundary.md          operator/agent trust model rationale
  agent-hierarchy.md   tree-shape topology design + manager-privilege audit
  damocles-migration.md  future migration plan for damocles → hyperhive
  gateway.md           nginx vhost map, matrix discovery flow, firewall posture,
                       HIVE_FORGE_URL loopback rationale
  forge.md             per-agent forge accounts + agent-configs mirror;
                       forge_notify poller (gates, self-filter, body excerpt
                       pipeline, wrapper formats, reason drop-list,
                       auto-unsubscribe)
  matrix.md            matrix container shape, serverName/gatewayHost split,
                       firewall + federation, provisioning flow, fluffychat-web build
  network.md           host-side bridge + dnsmasq resolver, v1/v2 roadmap,
                       foundation for netns isolation
  swarm.md             multi-hive swarm config: peer declaration, TLS trust
                       (CA vs certFingerprint), bilateral setup, identity
                       env vars, matrix federation pointer
  ci.md                hive-ci Forgejo Actions runner: options, container
                       shape, auto-registration flow, nix sandbox note
  coordinator.md       rebuild queue: queue kinds (Rebuild, MetaUpdate, Spawn),
                       dedup logic, sources, cascade tracking, step labels;
                       serialisation rationale

Reading paths

Pick the doc that matches your task. None depend on the others — read them à la carte.

  • "What does the dashboard look like?"docs/web-ui.md (index; sub-pages: shape, dashboard, agent).
  • "How does the per-agent terminal classify + colour events?"docs/terminal-rendering.md.
  • "How does claude get its prompt and what tools does it have?"docs/turn-loop.md.
  • "How do config changes flow from manager to operator to container?"docs/approvals.md.
  • "What state survives destroy / purge / restart?"docs/persistence.md.
  • "Naming, commit style, wire protocol, the data-async pattern."docs/conventions.md.
  • "Why does the nspawn flag look like that?"docs/gotchas.md.
  • "What nginx vhosts does the gateway serve? How does matrix discovery work?"docs/gateway.md.
  • "How do per-agent forge accounts work? What does forge_notify poll + how does it format wake messages?"docs/forge.md.
  • "How does the matrix-tuwunel container work? What about fluffychat-web and per-agent matrix accounts?"docs/matrix.md.
  • "How does DNS resolution work in agent containers? What's the bridge network for?"docs/network.md.
  • "How do I connect two hives into a swarm? How do I declare peer hives and configure TLS trust?"docs/swarm.md.
  • "How does the rebuild queue work? What are queue kinds and sources?"docs/coordinator.md.
  • "How does the CI runner work? What's the auto-registration flow?"docs/ci.md.

Conventions & process

The docs below own the details — this section just points at them.