- Rust 64%
- Nix 22.3%
- JavaScript 4.8%
- TypeScript 4.4%
- CSS 3%
- Other 1.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
An agent's store identity was signed in swarm-controller's memory by a CA a controller-host unit generated on disk, and the listener never trusted that CA. Agent leaves now come from the store itself: a `pki-agents` PKI mount whose root openbao generates internally, so the agent CA's key never exists outside the store. - swarm-bao-agent-pki (new, store host, as the bao granter): enables and tunes the mount, generates the root once (guarded on an empty issuer list, no replace branch), upserts the `swarm-agent` role (client certificates named `hive-agent-*` only, 90 days), caches the CA at /var/lib/swarm-bao-tls/agent-ca.pem and composes the listener bundle. - The listener's tls_client_ca_file is a new listener-client-ca.pem (client-ca.pem, then the agent CA). Host cert-auth roles still pin client-ca.pem, so an agent leaf satisfies no host role. swarm-bao-certs composes the same bundle before openbao starts. - openbao reads tls_client_ca_file only at start, so when the bundle changed after openbao started, swarm-bao-agent-pki restarts openbao.service in the container; under `seal = "shamir"` it prints the step instead. Once swarm-bao-certs has a cached CA, later boots start openbao with it and do not restart. - The controller policy gains exactly `update` on pki-agents/issue/swarm-agent. mint_and_verify now asks that role for the leaf (the store generates the key), writes the agent's cert-auth role pinning the issuing CA bao returned, and writes the agent's policy as render_agent alone: the hive-shared queue credential stanza is gone. - deploy.bao.agentPkiRoleName (must start `swarm-`, asserted with the other pki role names); swarm-controller gets SWARM_CONTROLLER_AGENT_PKI_MOUNT/_ROLE from the deploy.bao options. Deleted: swarm-controller-agent-ca and its options (agentCaFile, agentCaKeyFile), env, LoadCredential entries and assertion; agent_identity's Authority, rcgen signing and validity window; the rcgen and time dependencies of swarm-controller (rcgen leaves the workspace); policy::render_agent_with_queue and its tests. The CN-prefix assertion policy.rs said was owed is not: agent and host roles pin different CAs. Migration is re-creating each agent after deploy; that overwrites the stale role and policy. Closes #4756 |
||
| .forgejo/workflows | ||
| branding | ||
| claude-plugins | ||
| docs | ||
| frontend | ||
| hive-agent | ||
| hive-agent-mcp | ||
| hive-agent-sock | ||
| hive-bash-mcp | ||
| hive-c0re | ||
| hive-core-agent-sock | ||
| hive-forge | ||
| hive-forge-notify | ||
| hive-host-sock | ||
| hive-jobq | ||
| hive-jobq-metrics | ||
| hive-jobq-wire | ||
| hive-log | ||
| hive-matrix-mcp | ||
| hive-metric | ||
| hive-priv | ||
| hive-priv-sock | ||
| hive-screen-mcp | ||
| hive-sh4re | ||
| hive-sock-client | ||
| hive-subagent-mcp | ||
| hive-types | ||
| hivectl | ||
| nix | ||
| scripts | ||
| swagger-ui-theme | ||
| swarm-authelia-bridge | ||
| swarm-authelia-bridge-sock | ||
| swarm-controller | ||
| swarm-logs | ||
| swarm-matrix-client | ||
| swarm-matrix-ctl | ||
| swarm-nats-auth | ||
| swarm-queue-client | ||
| swarm-secret-client | ||
| swarmctl | ||
| .gitignore | ||
| .mailmap | ||
| .prettierignore | ||
| .prettierrc | ||
| .vale.ini | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| clippy.toml | ||
| flake.lock | ||
| flake.nix | ||
| README.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/remind) - config = git (manager proposes, operator approves, deploys land as tagged commits)
- blast radius = container
every hive (NixOS host, runs hive-c0re.service)
│
├── operator
│ ├── browser → :80 (hive-gateway) dashboard + per-agent UIs
│ │ /agent/<name>/ → per-agent unix socket
│ └── CLI → /run/hyperhive/host.sock admin protocol
│
├── hive-c0re (Rust daemon: lifecycle / broker / approvals /
│ auto-update / dashboard / sockets)
│
├── hive-gateway (optional) nginx — proxies :80 → c0re dashboard + per-agent sockets
│
└── agent containers
├── h-ruth manager (privileged MCP surface, approval gating)
└── h-<name> sub-agent (claude + MCP tools + per-agent web UI + unix socket)
one host per swarm (optional — connects hives; can be any hive, including
one that's also running the tree above)
│
├── hive-forge Forgejo — swarm-wide singleton, per-agent accounts + config mirror
├── hive-matrix tuwunel — swarm-wide singleton, Matrix homeserver + per-agent accounts
├── swarm-controller cross-hive state: hive directory, agent roster, jobs
├── swarm-ui swarm-wide SPA, served straight off the gateway (no own container)
├── swarm-authelia SSO — one login gates swarm-ui + Grafana + more
├── swarm-nats message queue (JetStream KV: hive-status, …)
├── swarm-otel telemetry collector, sole holder of the upstream credential
├── swarm-victoriametrics metrics store
├── swarm-victorialogs log store
└── swarm-grafana dashboards over the metrics/log stores, own OIDC login
→ website · → docs · → options reference
Depth lives in docs/ (rendered at
hyperhive.darkest.space/docs/) —
start at docs/README.md and pick the page matching
your task rather than reading front to back.
Quick start
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";
# Pin hyperhive to your own nixpkgs instead of the one it ships with
# (see "Overriding nixpkgs" below) — recommended for most hosts:
hyperhive.inputs.nixpkgs.follows = "nixpkgs";
};
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.deploy.hive-controller.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.
Overriding nixpkgs
hyperhive pins its own nixpkgs so it builds standalone in CI. Add
hyperhive.inputs.nixpkgs.follows = "nixpkgs" (as in the quick-start above)
to build it against your host's nixpkgs instead — one less nixpkgs
evaluation, no version drift from the rest of your system. Standard flake
follows pattern; works as long as your channel is reasonably close to the
nixos-26.05 hyperhive develops against. Drop it again if a much
older/newer channel hits breakage hyperhive's CI doesn't catch.
For the full list of host and agent NixOS options see the options reference.
Operator CLI
hivectl is the operator-facing host CLI for ad-hoc administration that
doesn't go through the broker (built alongside hive-c0re when the host
module is enabled):
sudo hivectl matrix create-user mara # provisions a matrix user
sudo hivectl matrix create-user mara --password-stdin # … reading one line from stdin
For a name that's a managed agent, hivectl persists the resulting token
to that agent's state dir, the same as the boot sweep does. For a
non-agent name (for example the operator's own matrix account), it prints the
token to stdout and writes nothing.
A human's first SSO login to the forge makes their forge account, not
hivectl; swarmctl forge make-admin <name> on the swarm-controller's
host makes it a site admin.
Build / deploy
nix develop -c cargo check
nix flake check # rust + nix + toml fmt + clippy
# deploy from a host config that imports hyperhive.nixosModules.default
nix flake update --update-input hyperhive
sudo nixos-rebuild switch --flake .#<host>