No description
Find a file
müde 8b9f7d21b7 model persisted to /state; stop auto-allowing claude-code unfree
model persistence: /model <name> now writes to /state/hyperhive-model
(in-container), Bus::new reads it on init. operator override survives
harness restart and container rebuild; gone on --purge like every
other piece of agent state. path overridable via HYPERHIVE_MODEL_FILE
for tests. failure to persist is a warn, not fatal — runtime override
still applies, just won't survive a restart.

unfree opt-in: drop the auto-allowUnfreePredicate from
harness-base.nix and the claude-unstable overlay. operator now has to
set nixpkgs.config.allowUnfree (or a predicate listing claude-code)
in their own host config. silent unfree bypass was sketchy; this is
honest. readme + gotchas updated to spell out the snippet.

todo: drops model-persistence + container-crash + journald (all
shipped); adds per-agent send allow-list (constrain who an agent can
message).
2026-05-15 21:05:40 +02:00
docs model persisted to /state; stop auto-allowing claude-code unfree 2026-05-15 21:05:40 +02:00
hive-ag3nt model persisted to /state; stop auto-allowing claude-code unfree 2026-05-15 21:05:40 +02:00
hive-c0re container crash watcher → HelperEvent::ContainerCrash 2026-05-15 21:02:05 +02:00
hive-sh4re container crash watcher → HelperEvent::ContainerCrash 2026-05-15 21:02:05 +02:00
nix model persisted to /state; stop auto-allowing claude-code unfree 2026-05-15 21:05:40 +02:00
.gitignore gitignore .claude/settings.local.json 2026-05-15 14:44:58 +02:00
Cargo.lock events: persist to sqlite, survive harness restart 2026-05-15 19:42:57 +02:00
Cargo.toml turn loop: tool whitelist (no web/task), no skip-permissions 2026-05-15 14:41:38 +02:00
CLAUDE.md split claude.md into docs/ — per-topic, human-readable 2026-05-15 20:17:11 +02:00
flake.lock fmt 2026-05-14 22:27:03 +02:00
flake.nix model persisted to /state; stop auto-allowing claude-code unfree 2026-05-15 21:05:40 +02:00
README.md model persisted to /state; stop auto-allowing claude-code unfree 2026-05-15 21:05:40 +02:00
TODO.md model persisted to /state; stop auto-allowing claude-code unfree 2026-05-15 21:05:40 +02:00

hyperhive

Multi-Claude-Code-agent orchestration on nixos-containers.

A host-side Rust daemon (hive-c0re) spawns nspawn-isolated agent containers and brokers messages between them. A manager agent (hm1nd) coordinates the swarm and gates lifecycle changes on user approval via git commits, surfaced through a vibec0re-styled HTTP dashboard.

host (NixOS, runs hive-c0re.service)
│
├── operator
│   ├── browser → :7000               hive-c0re dashboard (containers, approvals)
│   ├── browser → :8000 / :8100-8999  per-agent web UIs (live SSE, send, login)
│   └── CLI     → /run/hyperhive/host.sock         JSON-line admin protocol
│
├── hive-c0re  (Rust daemon)
│   ├── lifecycle    nixos-container CRUD + per-agent flake generation
│   ├── broker       sqlite messages + tokio broadcast (powers SSE + wake-ups)
│   ├── approvals    sqlite queue, two kinds: ApplyCommit (config) + Spawn
│   ├── auto_update  rebuilds any container whose recorded flake rev is stale
│   ├── dashboard    axum HTTP + async-form actions + SSE message flow
│   └── sockets      /run/hyperhive/{host,manager,agents/<n>}/mcp.sock
│
└── nixos-containers  (each bind-mounts its socket dir → /run/hive,
   │                   credentials dir → /root/.claude,
   │                   durable notes dir → /state;
   │                   manager additionally gets /agents RW)
   │
   ├── hm1nd      hive-m1nd serve : claude turn loop +
   │              MCP (send / recv / request_spawn / kill / start /
   │                   restart / request_apply_commit / ask_operator)
   │              + web UI on :8000
   │
   └── h-<name>   hive-ag3nt serve : claude turn loop +
                  MCP (send / recv) + web UI on a hashed :8100-8999

Each turn: harness pops one inbox message (Recv long-polls server-side and wakes on a broker Sent event) → builds a wake prompt → spawns claude --print --continue --output-format stream-json --mcp-config … → streams JSON events into the per-agent SSE bus + a sqlite history db → claude drives any further recv/send itself via the embedded MCP server.

Operator surface per agent: terminal-themed live tail with a textarea prompt; slash commands /help /clear /cancel /compact; granular state badge (idle / thinking / offline) with age timer; cancel-turn button while thinking; sticky-bottom auto-scroll with "↓ N new" pill; event history backfilled on page load.

Config changes flow the other way: manager edits /agents/<name>/config/agent.nix (bind-mounted from the host's proposed repo) → commits → submits the sha as an approval → operator clicks ◆ APPR0VE on the dashboard → hive-c0re copies the file into the applied repo and nixos-container updates the agent. For decisions the manager needs human signal on, ask_operator(question, options?, multi?) queues a free-text/checkbox/radio form on the dashboard; the answer arrives later as a HelperEvent::OperatorAnswered in the manager's inbox.

Host config

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

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
    hyperhive.url = "git+https://git.berlin.ccc.de/vinzenz/hyperhive";
  };

  outputs = { nixpkgs, hyperhive, ... }: {
    nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        hyperhive.nixosModules.hive-c0re
        ({ ... }: {
          services.hive-c0re.enable = true;
          # ... rest of your host config (hardware, networking, users, …)
          system.stateVersion = "25.11";
        })
      ];
    };
  };
}

hive-c0re will then:

  • open its admin socket at /run/hyperhive/host.sock + dashboard on :7000,
  • auto-create the manager container (hm1nd) if missing,
  • auto-rebuild any managed container whose hyperhive rev is stale.

claude-code is unfree; hyperhive does not auto-allow it for you. Add to your host config:

nixpkgs.config.allowUnfreePredicate =
  pkg: builtins.elem (nixpkgs.lib.getName pkg) [ "claude-code" ];

(or nixpkgs.config.allowUnfree = true, your call). Each per-agent container inherits this through the same nixpkgs evaluation.

Build / deploy

# inside the repo (devshell first; no global cargo)
nix develop -c cargo check
nix develop -c cargo clippy --workspace --all-targets -- -D warnings

# evaluate everything (rust+nix+toml fmt + clippy)
nix flake check

# deploy to a host that imports `hyperhive.nixosModules.hive-c0re`
cd ~/Repos/<nixos-config-repo>
nix flake update --update-input hyperhive
sudo nixos-rebuild switch --flake .#<host>

No overlays on the host's pkgs — the module pulls hive-c0re's package straight from hyperhive.packages.<system>.default. Just import the module and the service is wired up.