{ description = "hyperhive — multi-Claude-Code-agent orchestration on nixos-containers"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; # Crane (replaces naersk #538). Stateless — no nixpkgs input to # follow; `crane.mkLib pkgs` returns the lib at whatever pkgs we # pass it (we use the project's pinned nixpkgs). crane.url = "github:ipetkov/crane"; treefmt-nix = { url = "github:numtide/treefmt-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, crane, treefmt-nix, }: let inherit (nixpkgs) lib; systems = [ "aarch64-linux" "x86_64-linux" ]; treefmt-config = { projectRootFile = "flake.nix"; programs = { keep-sorted.enable = true; nixfmt.enable = true; rustfmt.enable = true; taplo.enable = true; }; }; forAllSystems = f: lib.genAttrs systems ( system: f rec { inherit system; pkgs = nixpkgs.legacyPackages.${system}; treefmt-eval = treefmt-nix.lib.evalModule pkgs treefmt-config; craneLib = crane.mkLib pkgs; # Build the workspace's dependency tree once, cached as # its own derivation. `buildPackage` and `cargoClippy` # both reuse this via `inherit cargoArtifacts;` so a # workspace-only edit doesn't rebuild deps. Same # `nativeBuildInputs` as the workspace build itself — # build.rs runs during dep-build too (any deps with a # build.rs need rsvg too if they transitively pull it # in; harmless if they don't). cargoArtifacts = craneLib.buildDepsOnly { src = ./.; # Workspace Cargo.toml is virtual (no `[package].name`), # so crane can't auto-derive a name. Spell it out # explicitly here and below — keeps the derivation name # stable across crane bumps + silences the placeholder # warning. Same `pname` everywhere so dep + workspace + # clippy share a clean naming family. pname = "hyperhive-workspace"; version = "0.1.0"; inherit nativeBuildInputs; }; # Shared between buildDepsOnly + buildPackage + cargoClippy # so the three derivations see the same toolchain shape. # librsvg: hive-c0re/build.rs invokes `rsvg-convert` to # render branding/agent-configs.svg → PNG that the daemon # `include_bytes!`s (#424); SVG stays source-of-truth. # git: naersk used to auto-include it; crane is more # minimal, so we add it explicitly so hive-c0re's # `lifecycle::tests::setup_proposed_*` (which shell out to # `git init` + commit) pass under `cargo test` in the # sandbox. nativeBuildInputs = [ pkgs.librsvg pkgs.git ]; } ); in { packages = forAllSystems ( { pkgs, craneLib, cargoArtifacts, nativeBuildInputs, ... }: { default = craneLib.buildPackage { src = ./.; inherit cargoArtifacts nativeBuildInputs; pname = "hyperhive-workspace"; version = "0.1.0"; meta.description = "hyperhive workspace (hive-c0re, hive-ag3nt, hive-m1nd)"; }; # Bundled browser assets — see ./nix/frontend.nix. Output is # $out/{dashboard,agent}/ which the Rust binaries serve via # tower_http::ServeDir (wired up in Phase 4 of #273). 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; } ); overlays = { default = final: prev: { hyperhive = self.packages.${prev.stdenv.hostPlatform.system}.default; # Bundled frontend dist (see ./nix/frontend.nix). Output is # $out/{dashboard,agent}/; consumers pick the surface they # need. Exposed via the overlay so containers' nix evaluations # can reach it as `pkgs.hyperhive-frontend` once the overlay # is applied (manager + agent containers both apply it via # `mkContainer` further down). hyperhive-frontend = self.packages.${prev.stdenv.hostPlatform.system}.frontend; }; claude-unstable = final: prev: let # The overlay imports its own nixpkgs-unstable instance to # pin claude-code there. That instance has its own config # (independent from the user's prev.config), so we have to # set allowUnfreePredicate inline to whitelist claude-code # specifically — otherwise the unstable import itself # refuses to evaluate. This is scoped: only claude-code # bypasses unfree, nothing else. unstable = import nixpkgs-unstable { inherit (prev.stdenv.hostPlatform) system; config.allowUnfreePredicate = pkg: builtins.elem (prev.lib.getName pkg) [ "claude-code" ]; }; in { inherit (unstable) claude-code; }; }; nixosModules = { agent-base = ./nix/templates/agent-base.nix; manager = ./nix/templates/manager.nix; # The hive-c0re module wants `pkgs.hyperhive` for its default # `services.hive-c0re.package`. To avoid making operators apply an # overlay (which would also pollute their host pkgs with our # build), we thread the package straight from this flake's # `packages..default` via a `hyperhivePackage` argument. # The `claude-unstable` overlay only matters inside our container # builds (already applied internally in `nixosConfigurations`). hive-c0re = import ./nix/modules/hive-c0re.nix { 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 # stack (hive-c0re + hive-forge, since hive-c0re already pulls # in hive-forge). Intended usage: # # imports = [ hyperhive.nixosModules.default ]; # services.hive-c0re.enable = true; # default = self.nixosModules.hive-c0re; }; nixosConfigurations = let mkContainer = module: nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ module { nixpkgs.overlays = [ self.overlays.default self.overlays.claude-unstable ]; } ]; }; in { agent-base = mkContainer self.nixosModules.agent-base; manager = mkContainer self.nixosModules.manager; }; devShells = forAllSystems ( { pkgs, ... }: { default = pkgs.mkShell { packages = with pkgs; [ cargo clippy librsvg # rsvg-convert — hive-c0re/build.rs invokes it (#424) pkg-config rust-analyzer rustc rustfmt sqlite ]; }; } ); formatter = forAllSystems ({ treefmt-eval, ... }: treefmt-eval.config.build.wrapper); checks = forAllSystems ( { treefmt-eval, craneLib, cargoArtifacts, nativeBuildInputs, ... }: { formatting = treefmt-eval.config.build.check self; # Clippy as a check via crane's first-class `cargoClippy` # builder. Reuses the shared `cargoArtifacts` (deps already # built) and runs `cargo clippy --workspace --all-targets # -- -D warnings` directly — no `overrideAttrs` hack needed, # because crane parses `cargoClippyExtraArgs` correctly # (naersk's `mode = "clippy"` used to mangle the `--` # separator, which is why the old wiring went through # overrideAttrs). clippy = craneLib.cargoClippy { src = ./.; inherit cargoArtifacts nativeBuildInputs; pname = "hyperhive-workspace"; version = "0.1.0"; cargoClippyExtraArgs = "--workspace --all-targets -- -D warnings"; }; } ); }; }