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 65.9%
  • Nix 18.2%
  • JavaScript 6%
  • TypeScript 4.8%
  • CSS 3.5%
  • Other 1.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
atlas 98945d4c5a otel: scrape each collector's own loss counters
A collector's `refused` / `failed` / queue-depth counters are the only
signal that says telemetry is being dropped, and nothing read them at
any tier — so a collector losing records looked exactly like a quiet
system.

The hive tier could not be scraped without first naming its port. 8888
is the collector's built-in default and appeared in no config, which is
also why nothing comparing configured ports could see it clash with a
co-located collector — swarm-otel.nix sidesteps 8888 by hand for that
reason, and says so. Declaring the port and binding it explicitly makes
the value comparable; wiring the scrape is then one entry per tier.

Extending the port-collision assertion to cover it is deliberately left
out: that belongs with the other port work, and coupling a collision
fix to a scraping fix makes both harder to review.

Gate: 101 module properties hold, was 95. The six cases pin the rendered
scrape job rather than the option; the metrics pipeline naming the
prometheus receiver, a path never emitted on any hive before this since
the hive tier's scrapeTargets was empty everywhere; the `readers`
spelling, with a control so a missing telemetry block cannot pass the
port check vacuously; the swarm tier's own entry; the two tiers not
claiming the same port; and the absence arm, a hive with no collector
declaring no target.

scrapeTargets' description said "Empty by default, and that is the
shipped case". This makes that false, so the paragraph moves with it.
2026-09-12 10:34:06 +02:00
.forgejo/workflows ci: drop bare issue tags from ci.yml comments (mara, #4146) 2026-09-09 22:55:28 +02:00
branding docs(#1182): remove component-diagram.svg; trim README; link to website + options 2026-06-03 19:06:06 +02:00
claude-plugins docs, prompts, hive-forge: stop handing readers the renamed verbs 2026-09-10 17:22:57 +02:00
docs swarm: give agent containers their own queue principal 2026-09-12 10:33:06 +02:00
frontend remove operator as target for scheduled prompts 2026-09-11 23:32:45 +02:00
hive-agent docs: use pr status's positional form in the two remaining --pr examples 2026-09-11 17:27:49 +02:00
hive-agent-mcp remove operator as target for scheduled prompts 2026-09-11 23:32:45 +02:00
hive-agent-sock treefmt: apply prettier 2026-09-02 15:25:07 +02:00
hive-bash-mcp hive-bash-mcp: stop naming a private fn in the module's public doc 2026-09-11 19:25:33 +02:00
hive-c0re job_queue: fix dangling rustdoc intra-doc link left by strum conversion 2026-09-12 00:06:31 +02:00
hive-core-agent-sock hive-c0re: scope list_schedules to what the requester can actually act on 2026-09-11 18:05:13 +02:00
hive-forge hive-forge: timeline --since no longer errors on an empty window 2026-09-12 10:33:30 +02:00
hive-forge-notify hive-forge-notify: fix notify.rs's dangling doc pointer 2026-09-11 09:04:46 +02:00
hive-host-sock host.sock: push a live agent-status stream instead of poll-only 2026-09-07 18:43:47 +02:00
hive-jobq treefmt: apply prettier 2026-09-02 15:25:07 +02:00
hive-jobq-metrics move otel_http_client from swarm-queue-client into swarm-controller 2026-08-29 11:17:24 +02:00
hive-jobq-wire address review: move parse_states/filter_nodes_by_state to hive-jobq-wire, rename placeholder enums, trim core-mirroring framing 2026-08-16 16:59:54 +02:00
hive-matrix-mcp raise mcp streamable-http session keepalive from 5m to 24h 2026-08-31 12:53:07 +02:00
hive-metric docs: restructure into topic subdirectories, collapse duplicated index 2026-09-02 01:55:37 +02:00
hive-priv hive-priv: make the tmpfiles modes assertable 2026-09-11 13:02:22 +02:00
hive-priv-sock docs: restructure into topic subdirectories, collapse duplicated index 2026-09-02 01:55:37 +02:00
hive-screen-mcp treefmt: apply prettier 2026-09-02 15:25:07 +02:00
hive-sh4re remove as_str() legacy wrappers, callers use .into() directly 2026-09-12 00:06:31 +02:00
hive-sock-client treefmt: apply prettier 2026-09-02 15:25:07 +02:00
hive-subagent-mcp hive-subagent-mcp: fix resolve_dir commit ordering + add non-committing peek_dir 2026-09-12 01:48:55 +02:00
hive-types docs: restructure into topic subdirectories, collapse duplicated index 2026-09-02 01:55:37 +02:00
hivectl hivectl, docs: choom is not root-only, and set-limits takes no agent name 2026-09-11 19:11:13 +02:00
nix otel: scrape each collector's own loss counters 2026-09-12 10:34:06 +02:00
scripts check-issue-refs: scan .yml/.yaml too, closes #4148 2026-09-09 23:25:54 +02:00
swagger-ui-theme treefmt: apply prettier 2026-09-02 15:25:07 +02:00
swarm-authelia-bridge check-issue-refs: catch full forge issue URLs too, drop internal links from docs entirely 2026-09-09 21:15:28 +02:00
swarm-authelia-bridge-sock feat(swarm-authelia-bridge): report a heal as its own outcome 2026-08-23 19:00:41 +02:00
swarm-controller remove the two remaining as_str-style wrappers (DeliveryKind::parse, Wanted::parse) 2026-09-12 00:06:31 +02:00
swarm-nats-auth swarm: name the agent client after its hive, not after "agent" 2026-09-12 10:33:06 +02:00
swarm-queue-client remove as_str() legacy wrappers, callers use .into() directly 2026-09-12 00:06:31 +02:00
swarm-secret-client remove as_str() legacy wrappers, callers use .into() directly 2026-09-12 00:06:31 +02:00
swarmctl docs: clear the remaining error-level vale lints 2026-09-09 22:55:28 +02:00
.gitignore docs: address review — redundancy proof for Passive, wave-2 split, re-enable Contractions 2026-09-07 11:56:31 +02:00
.mailmap chore(#2165): add damocles@pr1ma + lexis@pr1ma mailmap entries 2026-07-04 13:50:16 +02:00
.prettierignore hive-forge: add markdown-docs generator and CI freshness check 2026-09-02 19:38:34 +02:00
.prettierrc temp: add prettier configs 2026-07-02 23:33:11 +02:00
.vale.ini Disable Microsoft.HeadingColons and Microsoft.Percentages, fix Plurals hits 2026-09-07 14:19:24 +02:00
Cargo.lock convert hand-written enum as_str matches to strum derives workspace-wide 2026-09-12 00:06:31 +02:00
Cargo.toml swarm-secret-client: derive Kind's segment strings via strum instead of a hand-written match 2026-09-12 00:06:31 +02:00
CLAUDE.md subagent: add status tool, cut docs down to operator-facing + no cli flags 2026-09-09 23:45:12 +02:00
clippy.toml hivectl: wireguard mesh setup verbs (#1756) 2026-06-19 14:37:50 +02:00
flake.lock flake: bump nixpkgs 569d5785 -> 5dfba623 2026-09-02 14:16:57 +02:00
flake.nix nix: wire the independent hive-subagent-daemon systemd unit and MCP server 2026-09-09 23:45:12 +02:00
README.md docs/hive-c0re: fix ask/answer removal doc gaps argus caught on #3741 2026-08-30 03:02:31 +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 / 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.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 forge create-user mara                       # provisions a forge user
sudo hivectl forge create-user mara --password 'hunter2'  # … with a fixed password
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 (e.g. the operator's own forge/matrix account), it prints the token to stdout and writes nothing.

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>