diff --git a/README.md b/README.md index cb513bf7..a2f48896 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,16 @@ 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 github:vinzenz/hyperhive#agent-base-toplevel`. + ## Agent configuration Per-agent settings live in each agent's `agent.nix` and are synced to diff --git a/flake.nix b/flake.nix index fa26a6db..792bf2fb 100644 --- a/flake.nix +++ b/flake.nix @@ -69,6 +69,24 @@ frontend = pkgs.callPackage ./nix/frontend.nix { branding-svg = ./branding/hyperhive.svg; }; + # Pre-built per-container system closures. Exposed as packages + # so operators can `nix build .#agent-base-toplevel` (or wire + # them into their host system closure via the + # `preBuildAgentTemplates` option on the hive-c0re module — + # see nix/modules/hive-c0re.nix). Speeds up the first agent + # spawn dramatically because the heavy lifting (nixpkgs + + # claude-code + hive-ag3nt binary) is already in the store + # when the meta evaluator goes to build the container. + # Closes #97. + # + # nixosConfigurations are pinned to x86_64-linux (nixos- + # containers only run native arch), so these toplevels are + # only useful on an x86_64-linux host — flake check across + # systems still tolerates evaluating them on aarch64 because + # they're plain derivations, but `nix build` from a non-x86 + # host would only succeed via a remote x86 builder. + agent-base-toplevel = self.nixosConfigurations.agent-base.config.system.build.toplevel; + manager-toplevel = self.nixosConfigurations.manager.config.system.build.toplevel; } ); @@ -117,6 +135,15 @@ hyperhivePackage = system: self.packages.${system}.default; hyperhiveFrontend = system: self.packages.${system}.frontend; hyperhiveFlake = "${self}"; + # Per-container toplevels — wired into `system.extraDependencies` + # when `services.hive-c0re.preBuildAgentTemplates` is on so the + # host system closure pre-fetches the heavy build inputs (#97). + # Defined only for x86_64-linux because nixosConfigurations are + # hardcoded to that system; the option's default keeps the + # extra deps gated so aarch64 hosts don't accidentally pull + # them in via cross-build. + agentBaseToplevel = self.packages.x86_64-linux.agent-base-toplevel; + managerToplevel = self.packages.x86_64-linux.manager-toplevel; }; hive-forge = ./nix/modules/hive-forge.nix; # Convenience alias: one import covers the full hyperhive host diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index 9d77eb57..467a5f7e 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -2,6 +2,8 @@ hyperhivePackage, hyperhiveFrontend, hyperhiveFlake, + agentBaseToplevel, + managerToplevel, }: { pkgs, @@ -71,6 +73,32 @@ in approval needed. ''; }; + preBuildAgentTemplates = lib.mkOption { + type = lib.types.bool; + default = false; + example = true; + description = '' + Pre-fetch the per-container system closures (agent-base + + manager toplevels) into the host's /nix/store as part of this + host's NixOS build, instead of letting the first agent spawn + do all the work. Closes #97. + + Enabling this adds roughly the full nixpkgs runtime closure + + claude-code + the harness binary to your system closure size + (low single-digit GB), but the first `nixos-container start` + for any agent then completes in seconds instead of minutes + because nothing's left to fetch. + + Off by default because the toplevels are pinned to + `x86_64-linux` (nixos-containers run native arch). Enabling + on an aarch64 host would force nix to build the x86 closure + via cross or a remote builder, which is rarely what you want. + Flip to `true` on an x86_64 host when you care more about + first-spawn latency than host store size — or just + `nix build ${hyperhiveFlake}#agent-base-toplevel` once + manually to warm the store. + ''; + }; contextWindowTokens = lib.mkOption { type = lib.types.attrsOf lib.types.int; default = { @@ -104,6 +132,17 @@ in pkgs.git ]; + # Pull the per-container toplevels into the host system closure + # (#97). `system.extraDependencies` adds paths to the system build + # without referencing them at runtime — nixos-rebuild fetches / + # builds them, they end up in /nix/store, and the first + # nixos-container update + start for an agent has nothing left to + # do. Gated because the closure is sizeable and pinned to x86_64. + system.extraDependencies = lib.optionals cfg.preBuildAgentTemplates [ + agentBaseToplevel + managerToplevel + ]; + # Dashboard + per-container web UIs share the host's network namespace and # need their ports reachable. Dashboard: `cfg.dashboardPort` (default 7000). # Manager: 8000. Sub-agents: 8100..8999 (deterministic hash; see