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
iris 73684fb00a rust+nix: load static assets at runtime, drop build.rs (#555)
Cuts every `include_bytes!`/`include_str!` of a non-rust path in
the workspace over to runtime file loads from `$HIVE_ASSETS_DIR`
(the `hyperhive-assets` derivation introduced in the previous
commit). After this commit the rust derivation has no compile-time
dependency on `branding/*` or `hive-ag3nt/prompts/*` anymore.

Call-site flips:

- `hive-c0re/src/forge.rs::CORE_AVATAR_PNG` /
  `CONFIG_ORG_AVATAR_PNG`: were `include_bytes!` of
  `branding/hyperhive.png` and `$OUT_DIR/agent-configs.png`. Now
  `ensure_core_avatar` / `ensure_config_org_avatar` `tokio::fs::read`
  via `hive_sh4re::assets::{core_avatar_png, config_org_avatar_png}`
  at startup. The `agent-configs.png` is now rendered by the
  `hyperhive-assets` derivation's rsvg-convert step (was
  `hive-c0re/build.rs` + librsvg on the rust derivation's
  nativeBuildInputs — both gone in the next commit).
- `hive-ag3nt/src/prompt.rs::TEMPLATE`: `render` now takes the
  template as an argument; `write_system_prompt` reads it once from
  `$HIVE_ASSETS_DIR/prompts/system.md` before calling render. The
  test module still `include_str!`s the production template so
  `cargo test --workspace` doesn't need `HIVE_ASSETS_DIR` set —
  this is the only remaining compile-time reference to the file
  from the rust workspace, gated to `#[cfg(test)]`.
- `hive-ag3nt/src/turn.rs::CLAUDE_SETTINGS`: was `include_str!`'d
  and written via `tokio::fs::write`; now `tokio::fs::copy` from
  `$HIVE_ASSETS_DIR/prompts/claude-settings.json` into the
  per-agent socket dir.
- `hive-ag3nt/src/web_ui.rs::DEFAULT_ICON`: was `include_str!`'d;
  now read on-demand from `$HIVE_ASSETS_DIR/branding/hyperhive.svg`
  inside `serve_icon`. Falls back to an empty body if missing so
  the endpoint never panics on a misconfigured container (matches
  the existing "per-agent icon.svg override" fallthrough).

`HIVE_ASSETS_DIR` wiring:

- Inside containers: `nix/templates/harness-base.nix`
  `environment.variables` sets it to
  `${pkgs.hyperhive-assets}/share/hyperhive` (resolved through
  the default overlay applied in `mkContainer`). Verified by
  building `agent-base-toplevel` and grepping the resulting
  `/etc/set-environment`.
- Host-side: `nix/modules/hive-c0re.nix` adds an `assets` option
  defaulting to `hyperhive.packages.${system}.assets`, threaded
  in from the flake's nixosModules wiring, and sets the same env
  var on the `hive-c0re` systemd unit so the daemon's
  `forge::ensure_*_avatar` startup hooks find the PNGs.

`hive-c0re/build.rs` deleted entirely; `[package].build` removed
from `hive-c0re/Cargo.toml`; rsvg-convert dependency lives in the
assets derivation only.

Validated: `nix build .#default .#checks.x86_64-linux.clippy
.#agent-base-toplevel .#manager-toplevel --fallback` all succeed.
`/etc/set-environment` in the toplevel shows
`HIVE_ASSETS_DIR="/nix/store/.../hyperhive-assets-0.1.0/share/hyperhive"`.
2026-05-29 12:59:48 +02:00
branding forge: auto-set agent-configs org avatar on core start (#424) 2026-05-26 00:10:52 +02:00
docs docs: forge_notify.rs file map + wait_for_login mtime resumption (follow-up to #544 #545) 2026-05-29 00:34:11 +02:00
frontend tabs: logs flyout fills the side-panel height (closes #541) 2026-05-28 18:54:02 +02:00
hive-ag3nt rust+nix: load static assets at runtime, drop build.rs (#555) 2026-05-29 12:59:48 +02:00
hive-c0re rust+nix: load static assets at runtime, drop build.rs (#555) 2026-05-29 12:59:48 +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-sh4re rust+nix: load static assets at runtime, drop build.rs (#555) 2026-05-29 12:59:48 +02:00
nix rust+nix: load static assets at runtime, drop build.rs (#555) 2026-05-29 12:59:48 +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 cargo: regenerate Cargo.lock to add transitive deps surfaced by resolver=3 (closes #556) 2026-05-29 02:03:38 +02:00
Cargo.toml hive-forge: rewrite bash CLI helper as a rust binary (closes #280) 2026-05-25 02:16:53 +02:00
CLAUDE.md nix: add hive-matrix module + hyperhive.domain option (#548 part 1) 2026-05-29 01:25:29 +02:00
flake.lock flake: replace naersk with crane (#538) 2026-05-29 01:45:48 +02:00
flake.nix rust+nix: load static assets at runtime, drop build.rs (#555) 2026-05-29 12:59:48 +02:00
README.md docs: fix tuwunel upstream URL + clarify domain/serverName requirement 2026-05-29 02:24:13 +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 in one import
        ({ ... }: {
          services.hive-c0re.enable = true;
          # services.hive-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.hive-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 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: hyperhive.matrix) assert non-null at eval time with a clear error message if it is missing.

Optional: set hyperhive.matrix.enable = true; to spin up a private matrix-tuwunel homeserver in a nixos-container. Requires either hyperhive.domain or 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 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).

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.

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>