hyperhive/CLAUDE.md
iris 2080fd3866 feat: live SSE updates for P3RM1SS10NS tab (capabilities + tool groups)
Add CapabilitiesChanged and ToolGroupsChanged DashboardEvent variants
so the P3RM1SS10NS tab reflects perm changes without the operator
navigating away and back.

Backend:
- DashboardEvent::CapabilitiesChanged { seq, caps, descriptions,
  assignments } — same payload shape as GET /api/capabilities
- DashboardEvent::ToolGroupsChanged { seq, groups, descriptions,
  assignments } — same payload shape as GET /api/tool-groups
- Coordinator::emit_capabilities_snapshot() and
  emit_tool_groups_snapshot() — read from the JSON files and broadcast
- rebuild_queue.rs PermChange worker: emit after each successful
  commit_capabilities / commit_tool_groups call

Frontend:
- applyCapabilitiesChanged(ev): calls renderCapabilities(root, ev)
- applyToolGroupsChanged(ev): calls renderToolGroups(root, ev)
- Both registered in MUTATION_HANDLERS
- activateTab comment updated (SSE now covers perm changes)

Docs: dashboard.md and CLAUDE.md updated.

This completes SSE coverage for all dashboard sections: SW4RM,
Y3R C4LL, SYST3M, SCH3DUL3S/reminders, and P3RM1SS10NS all
derive live updates from /dashboard/stream.
2026-06-05 12:06:32 +02:00

28 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. Verbs: `forge
                         create-user <name>` / `matrix create-user
                         <name>` — manual entry points to the same
                         idempotent provisioning flows c0re runs at
                         boot; `gateway create-user|delete-user|
                         list-users` — BCrypt htpasswd management for
                         gateway HTTP Basic auth; `agents list|kill|
                         restart|restart-all` — container management
                         without the broker; `choom <name> [--fresh]`
                         — exec into `machinectl shell h-<name>`
                         running `claude --continue` (or fresh) so
                         the operator can drop into the agent's live
                         Claude session interactively.
  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/gateway_nginx.rs  runtime nginx include-file generator. Writes
                         `/var/lib/hyperhive/gateway/agents.conf` (one
                         `location /agent/<n>/` block per agent, UDS or
                         TCP upstream) on every topology change; calls
                         `systemctl -M hive-gateway reload nginx` to reload
                         nginx. Idempotent — skips write + reload when
                         the file content would not change.
  src/priv_client.rs    async client for the `hive-priv` privileged-
                         helper socket at `/run/hive/priv.sock`.
                         One-shot connection-per-call: open socket,
                         send one JSON line, read response, close.
                         Exposes one async fn per operation; called by
                         `lifecycle` for bind-mount manipulation during
                         spawn / rebuild.
  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`, `SchedulesChanged`,
                         `RemindersChanged`, `CapabilitiesChanged`,
                         `ToolGroupsChanged`).
                         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/build_logs.rs     sqlite-backed full build-log capture (stdout +
                         stderr per `nixos-container` / `nix build`
                         invocation). Process singleton opened by
                         `Coordinator`; `lifecycle` appends lines live.
                         Dashboard surfaces the log on expand. Backed by
                         `/var/lib/hyperhive/build_logs.sqlite`; hourly
                         retention sweep via the existing vacuum.
  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/capabilities.rs   per-agent capability grants — reads/writes
                         `/var/lib/hyperhive/meta/capabilities.json`;
                         `set_caps` + `caps_for` + `has_cap` +
                         `remove_agent`. Wired into `render_flake` for
                         `HIVE_CAPABILITIES` injection; operator write
                         via dashboard P3RM1SS10NS tab.
  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, logs.html, logs.js,
                         common.js, stream-worker.js, common.css,
                         dashboard.css, flow.css, logs.css} +
                         build.mjs → dist/{index.html, flow.html,
                         logs.html, static/{tabs.js, flow.js, logs.js,
                         stream-worker.js, common.css, dashboard.css,
                         flow.css, logs.css}}.
  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 for all agents
  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 { socket }` — single role, tool groups gate access
  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 (always
                         renders the agent section); owns
                         `write_system_prompt` (re-exported from
                         turn.rs for callers).
  src/bin/hive.rs       unified harness main (Serve + Mcp + Wake
                         subcommands); privilege boundary enforced
                         server-side at the broker socket. 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, attachment-get, 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; single
                                 `hive-ag3nt` service unit; `hyperhive.model`
                                 option (HIVE_DEFAULT_MODEL)
  templates/agent-base.nix      entry-point for sub-agent containers
  templates/manager.nix         entry-point for ruth; adds forge noise-reduction
                                 defaults (keepSubscriptions=false etc.)
  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, capabilities, 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
  tools/               per-group tool docs (bash.md, lifecycle.md,
                         scheduling.md, matrix.md, forge.md)
  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.
  • "What verbs does hive-forge support? How do I post a comment, upload an attachment, manage subscriptions?"docs/tools/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.