- Rust 68.5%
- Nix 15.6%
- JavaScript 7.1%
- CSS 3.8%
- TypeScript 3.5%
- Other 1.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
iris's diagnosis on #643 (mara's fluffychat-web login attempt): the gateway's `/matrix/` location used try_files $uri $uri/ /matrix/index.html; which silently returned `index.html` (Content-Type: text/html, status 200) for ANY missing path under `/matrix/`, including static assets like `native_executor.js`. flutter's bootstrap requested that JS file, got HTML back, failed to load the JS runtime, and the page rendered blank without any visible error in the browser console. (Confirmed root cause for the missing file itself: the upstream `fluffychat-web` dist in nixpkgs ships `native_executor.dart` but no compiled `native_executor.js`, even though `main.dart.js` references the latter. That's a separate fluffychat-web packaging issue — tracked separately; this PR fixes only the gateway-side masking that hides such failures.) Replaces the inline `try_files` fallback with a named-location fallback that distinguishes between route-shaped URIs (no extension) and asset-shaped URIs (any `.<ext>` suffix): location /matrix/ { alias <pkg>/; try_files $uri $uri/ @matrix_spa_fallback; } location @matrix_spa_fallback { if ($uri ~ "\.[A-Za-z0-9]+$") { return 404; } rewrite ^ /matrix/index.html last; } Routes still fall back to `index.html` so SPA client-side routing keeps working; missing assets now surface a real 404 so flutter (and the operator's devtools) can see the failure. Verified the rendered nginx location attr via `nix eval .#nixosConfigurations.* .... locations."@matrix_spa_fallback".extraConfig`. |
||
| branding | ||
| docs | ||
| frontend | ||
| hive-ag3nt | ||
| hive-c0re | ||
| hive-forge | ||
| hive-matrix-mcp | ||
| hive-sh4re | ||
| nix | ||
| scripts | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| TODO.md | ||
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 <domain> (bare hive domain, since #660); the hive-gateway serves
.well-known/matrix/{client,server} endpoints so clients auto-discover the
homeserver without a subdomain. Existing homeservers must set
services.hyperhive.matrix.serverName = "matrix.<domain>"; explicitly to
preserve pre-#660 user/room IDs. Override with
services.hyperhive.matrix.serverName = "chat.example.com"; for a custom
server name. 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"). SetsHIVE_DEFAULT_MODELin 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 (viasend). 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-tokenis missing. -
hyperhive.forge.keepSubscriptions— Boolean. Iftrue, the agent's forge repo subscriptions are never auto-cleaned during rebuild; useful for agents that want to watch specific repos. Rendered asHIVE_FORGE_KEEP_SUBSCRIPTIONS. -
hyperhive.forge.skipNotifyReasons— List of forge notificationreasonvalues 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 asHIVE_FORGE_NOTIFY_SKIP_REASONS(comma-separated). -
hyperhive.frontend.dist— Override the default frontend package (pkgs.hyperhive-frontend, built bynix/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 asource(nix path) and an optionaltarget(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; usefrontend.distto replace the whole dist. Paths with leading/or..segments are rejected at eval time. -
hyperhive.matrix.enable— Boolean (defaulttrue). When true, each agent container runshive-matrix-daemon(a long-running matrix-sdk process that holds the per-agent client + sync) and auto-injectshive-matrix-mcpas 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;roomargs accept both!id:serverand#alias:serverforms). Silently no-ops when<state>/matrix-tokenis absent (i.e., the host-levelhyperhive.matrixtuwunel container hasn't provisioned the account yet). Set tofalseto opt a specific agent out of matrix. -
hyperhive.user.name— Unix username the agent runs as inside the container (default: the agent's own label, injected by the meta-flake). Agents no longer run as root. Stand-alone module eval without the meta-flake falls back to"agent". -
hyperhive.user.passwordlessSudo— Boolean (defaulttrue). Grants the agent userNOPASSWD: ALLsudo so claude'sBashtool can still escalate when needed — same surface as the old root-user shape, just explicit. Setfalsefor strictly unprivileged agents.
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>