a swarm o agents, each in its own nspawn cage, gossiping over unix sockets. config changes flow as git commits, the operator approves them in a browser, every deploy is a tag. cyberpunk-themed dashboard included. 💜
  • Rust 68.5%
  • Nix 15.6%
  • JavaScript 7.1%
  • CSS 3.8%
  • TypeScript 3.5%
  • Other 1.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
atlas 85790b0cca nix: add breaking-change note to each openFirewall description (argus #653)
argus picked option (a) on #653: put the upgrade note in each option's
`description` so it shows up in `nix flake show` + the rendered
options docs, right next to the option itself. cheapest option, no
eval-time noise (a `warnings` block would fire on every new
deployment that wants false — the normal case now).

Appended a `**Breaking change as of #651**` paragraph to each of the
three `openFirewall` descriptions, naming the exact option string the
operator needs to set to restore the old behaviour.

Gateway's note specifically calls out that external reach is the
common case (operator's primary entry point), so the upgrade hint
is most likely needed there.
2026-05-30 19:30:11 +02:00
branding forge: auto-set agent-configs org avatar on core start (#424) 2026-05-26 00:10:52 +02:00
docs docs: matrix gui.enable defaults to matrix.enable, gateway serves /matrix/ (follow-up to #635) 2026-05-30 15:51:17 +02:00
frontend dashboard: footer link → forge.darkest.space mirror (closes #639) 2026-05-30 16:42:37 +02:00
hive-ag3nt harness: emit needs_login_idle on every wait_for_login entry (closes #563) 2026-05-29 19:28:42 +02:00
hive-c0re forge: on 403 from PATCH user email, hint operator to delete core token (#646 argus nit) 2026-05-30 19:08:16 +02:00
hive-forge hive-forge: collapse autogenerated diffs to a single one-line summary (#222) 2026-05-29 01:16:51 +02:00
hive-matrix-mcp matrix-mcp: surface serialise errors + clarify ping doc (argus #603 nits) 2026-05-29 20:51:01 +02:00
hive-sh4re rust+nix: load static assets at runtime, drop build.rs (#555) 2026-05-29 12:59:48 +02:00
nix nix: add breaking-change note to each openFirewall description (argus #653) 2026-05-30 19:30:11 +02:00
scripts forge-login: don't die on RO ~/.config/git/config 2026-05-17 01:22:31 +02:00
.gitignore gitignore .claude/settings.local.json 2026-05-15 14:44:58 +02:00
Cargo.lock matrix: hive-matrix-mcp crate (daemon+stdio bridge) + harness wiring (#548 phase 3) 2026-05-29 20:51:01 +02:00
Cargo.toml matrix: hive-matrix-mcp crate (daemon+stdio bridge) + harness wiring (#548 phase 3) 2026-05-29 20:51:01 +02:00
CLAUDE.md docs(CLAUDE.md): nix/docs.nix → nix/docs/ directory with default.nix + style.css (follow-up to #626) 2026-05-30 13:43:25 +02:00
flake.lock nix: hyperhive owns nixpkgs pin via follows; bump to nixos-26.05 (#526) 2026-05-30 12:02:48 +02:00
flake.nix nix/docs: extract CSS into sibling file (#625) 2026-05-30 12:51:44 +02:00
README.md docs: matrix gui.enable defaults to matrix.enable, gateway serves /matrix/ (follow-up to #635) 2026-05-30 15:51:17 +02:00
TODO.md docs: move backlog to forge issue tracker, extract boundary doc 2026-05-20 12:19:16 +02:00

hyperhive

a swarm of claude-code agents, each in its own nspawn cage, gossiping over unix sockets. config changes flow as git commits, the operator approves them in a browser, every deploy is a tag. cyberpunk-themed dashboard included. 💜

Claude code is great in one window, exponentielle across many — but only if you can keep the agents from stepping on each other, give them durable identity, and stop them from eating production. hyperhive is the substrate.

  • identity = unix socket
  • communication = sqlite-backed broker (send / recv / ask / answer / remind)
  • config = git (manager proposes, operator approves, deploys land as tagged commits)
  • blast radius = container
host (NixOS, runs hive-c0re.service)
│
├── operator
│   ├── browser → :7000               hive-c0re dashboard
│   ├── browser → :8000 / :8100-8999  per-agent web UIs
│   └── CLI     → /run/hyperhive/host.sock   admin protocol
│
├── hive-c0re  (Rust daemon: lifecycle / broker / approvals /
│               auto-update / dashboard / sockets)
│
└── nixos-containers
    ├── hm1nd      manager agent (privileged MCP surface)
    └── h-<name>   sub-agent (vanilla MCP surface + per-agent extras)

Depth lives in docs/ — pick the one matching your task:

reading path doc
dashboard layout + endpoints docs/web-ui.md
claude turn loop + MCP tools docs/turn-loop.md
config-edit + approval state machine docs/approvals.md
what survives destroy / purge / restart docs/persistence.md
naming, wire protocol, commit style docs/conventions.md
NixOS / nspawn gotchas docs/gotchas.md

Host config

Minimal flake.nix for a host that runs hive-c0re:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
    hyperhive.url = "git+https://forge.darkest.space/hyperhive/hyperhive";
  };

  outputs = { nixpkgs, hyperhive, ... }: {
    nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        hyperhive.nixosModules.default  # hive-c0re + hive-forge + hive-gateway in one import
        ({ ... }: {
          services.hyperhive.enable = true;
          # services.hyperhive.c0re.operatorPronouns = "they/them";  # default: "she/her"

          # ... rest of your host config
          system.stateVersion = "25.11";
        })
      ];
    };
  };
}

hive-c0re opens its admin socket + dashboard, auto-creates the manager container, and auto-rebuilds any container whose hyperhive rev goes stale. claude-code is unfree — hyperhive scopes the whitelist to itself, nothing for the operator to set.

Optional: set services.hyperhive.gateway.enable = false; to bypass the default nginx in front. By default (gateway.enable = true) every request hits a small nginx in its own nixos-container that proxies to hive-c0re's dashboard on the upstream port; /matrix/ is served directly from services.hyperhive.matrix.gui.package when the matrix GUI is on. v0 is HTTP-only (TLS lives in a follow-up); pair with services.hyperhive.gateway.localHostsEntry = true; for local dev so http://<services.hyperhive.domain> resolves to the host without setting up real DNS.

Optional: set services.hyperhive.c0re.preBuildAgentTemplates = true; to pre-fetch the per-container system closures into your host's /nix/store as part of nixos-rebuild. First-agent-spawn then completes in seconds instead of minutes (no nixpkgs/claude-code fetch on the critical path), at the cost of a few GB extra in your system closure. Off by default (the toplevels are pinned to x86_64-linux, so non-x86 hosts would otherwise force a cross-build). Alternatively warm the store manually: nix build git+https://forge.darkest.space/hyperhive/hyperhive#agent-base-toplevel.

Optional: set services.hyperhive.domain = "example.com"; to define the canonical hostname for hyperhive subsystems that need a stable public name. No default — subsystems that require it (currently: services.hyperhive.matrix) assert non-null at eval time with a clear error message if it is missing.

Optional: set services.hyperhive.matrix.enable = true; to spin up a private matrix-tuwunel homeserver in a nixos-container. Requires either services.hyperhive.domain or services.hyperhive.matrix.serverName to be set (eval fails with a clear error if both are absent). The server_name (embedded irrevocably in every user and room ID) defaults to matrix.<domain>; override with services.hyperhive.matrix.serverName = "chat.example.com"; if needed. State lives at /var/lib/nixos-containers/hive-matrix/. Federation is enabled with an empty trusted_servers list; e2ee is deferred to a follow-up (#551).

The hive-gateway nginx container serves a fluffychat-web matrix client at /matrix/ when services.hyperhive.matrix.gui.enable is on. This defaults to services.hyperhive.matrix.enable, so enabling the homeserver enables the web client by default; set gui.enable = false explicitly to keep the homeserver without the GUI. The ◆ M4TR1X ◆ → tab appears in the dashboard chrome when enabled. The web client can connect to any Matrix homeserver; enter the URL at first visit (e.g. the local tuwunel instance if services.hyperhive.matrix.enable = true, or any external homeserver).

Agent configuration

Per-agent settings live in each agent's agent.nix and are synced to the container as environment variables. Common options:

  • hyperhive.model — Claude model for this agent (default: "haiku"). Sets HIVE_DEFAULT_MODEL in the container; the harness applies it at boot and it takes priority over any persisted runtime override. The operator can still switch the model at runtime via the per-agent web UI, but that choice is reset by any rebuild that changes this option.

  • hyperhive.allowedRecipients — List of agent names this agent can message (via send). If unset, all agents are allowed. Useful to restrict an agent to talking only to the manager.

  • hyperhive.forge.url — Base URL of the hyperhive-managed Forgejo (default: "http://localhost:3000"). Used to configure the agent's tea login at boot; no-op if /state/forge-token is missing.

  • hyperhive.forge.keepSubscriptions — Boolean. If true, the agent's forge repo subscriptions are never auto-cleaned during rebuild; useful for agents that want to watch specific repos. Rendered as HIVE_FORGE_KEEP_SUBSCRIPTIONS.

  • hyperhive.forge.skipNotifyReasons — List of forge notification reason values to suppress (e.g. [ "subscribed" "participating" ]). Notifications matching these reasons are silently dropped; all others including direct mentions and reviews are delivered. Empty list (default) delivers all notifications. Rendered as HIVE_FORGE_NOTIFY_SKIP_REASONS (comma-separated).

  • hyperhive.frontend.dist — Override the default frontend package (pkgs.hyperhive-frontend, built by nix/frontend.nix). Set to a custom derivation to ship a fully custom per-agent SPA. The JSON contract (/api/state, /events/stream, action endpoints) is the source of truth for any replacement.

  • hyperhive.frontend.extraFiles — Attrset of extra files/directories to layer on top of the default agent dist. Each entry has a source (nix path) and an optional target (URL prefix in the static tree, defaults to the attribute name). Example: { bitburner.source = ./bitburner-dist; } serves that dist at /bitburner/. Pure additions only — overwriting an existing default file is a hard eval-time error; use frontend.dist to replace the whole dist. Paths with leading / or .. segments are rejected at eval time.

  • hyperhive.matrix.enable — Boolean (default true). When true, each agent container runs hive-matrix-daemon (a long-running matrix-sdk process that holds the per-agent client + sync) and auto-injects hive-matrix-mcp as a stdio MCP server so claude can call the matrix tools (mcp__matrix__send_message, send_dm, send_reaction, send_reply, mark_read, list_rooms, list_room_members, read_room; room args accept both !id:server and #alias:server forms). Silently no-ops when <state>/matrix-token is absent (i.e., the host-level hyperhive.matrix tuwunel container hasn't provisioned the account yet). Set to false to opt a specific agent out of matrix.

See nix/templates/harness-base.nix for the full list of options and their descriptions.

Build / deploy

nix develop -c cargo check
nix flake check        # rust + nix + toml fmt + clippy

# deploy from a host config that imports hyperhive.nixosModules.hive-c0re
nix flake update --update-input hyperhive
sudo nixos-rebuild switch --flake .#<host>