hyperhive/flake.nix
atlas 219a1e3caa flake: wire hive-screen-mcp into the agent package set
`hyperhive.gui.enable = true` could not evaluate for any agent:

    error: attribute 'hive-screen-mcp' missing
    at nix/agent-modules/screen.nix:23:46

screen.nix is activated by `gui.enable` and reads
`config.hyperhive.packages.hive-screen-mcp`, but the flake's
`agentPackages` module — the thing that actually populates
`hyperhive.packages` from `self.packages.<system>` — never inherited
it. The package itself was fine (`nix/packages/default.nix` builds it,
and `nix/agent-modules/packages.nix` already documents
`hive-screen-mcp` as one of the keys it provides), so this was purely
the missing third wiring edit.

It went unnoticed because `hyperhive.packages` is a plain
`attrsOf package`: a missing key isn't a schema error, it only fails
where it's dereferenced. No agent on this hive currently enables the
GUI, so nothing ever dereferenced it.

Found when a config PR enabling the GUI for an agent failed its deploy
verify step.
2026-07-29 20:35:16 +02:00

188 lines
6.4 KiB
Nix

{
description = "hyperhive multi-Claude-Code-agent orchestration on nixos-containers";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
# Crane is 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";
};
};
# Thin entry point — the real logic lives under nix/:
# nix/sources.nix filtered source views (meta-flake + docs inputs)
# nix/rust.nix shared crane wiring (cleanSrc, cargoArtifacts)
# nix/packages/ every package output
# nix/checks.nix flake checks
# nix/devshell.nix dev shell
# nix/treefmt.nix formatter config
# nix/host-modules/, nix/agent-modules/, nix/templates/ the NixOS module trees
outputs =
inputs@{
self,
nixpkgs,
crane,
treefmt-nix,
}:
let
inherit (nixpkgs) lib;
systems = [
"aarch64-linux"
"x86_64-linux"
];
sources = import ./nix/sources.nix { inherit lib; };
forAllSystems =
f:
lib.genAttrs systems (
system:
f rec {
inherit system;
pkgs = nixpkgs.legacyPackages.${system};
treefmt-eval = treefmt-nix.lib.evalModule pkgs (import ./nix/treefmt.nix);
craneLib = crane.mkLib pkgs;
rust = import ./nix/rust.nix { inherit pkgs craneLib; };
}
);
in
{
packages = forAllSystems (
{
pkgs,
craneLib,
rust,
...
}:
import ./nix/packages {
inherit
pkgs
craneLib
rust
self
nixpkgs
;
}
);
nixosModules =
let
# Package wiring for agent containers — the harness modules
# consume hyperhive's own packages via the `hyperhive.packages`
# option (see nix/agent-modules/packages.nix); no overlay.
# The `mkDefault` is applied PER KEY (`mapAttrs`), not to the
# whole attrset: definition-level priority filtering runs
# before `attrsOf`'s per-key merge, so a whole-set `mkDefault`
# would be discarded entirely the moment an agent.nix
# overrides a single key. Per-key priorities make an
# individual override win while every other key keeps the
# flake default.
agentPackages =
{ lib, pkgs, ... }:
{
hyperhive.packages = lib.mapAttrs (_: lib.mkDefault) {
inherit (self.packages.${pkgs.stdenv.hostPlatform.system})
hive-agent
hive-agent-mcp
hive-bash-daemon
hive-forge
hive-forge-notify
hive-matrix-daemon
hive-metric
hive-screen-mcp
assets
frontend
reference-docs
claude-plugins
;
};
};
in
{
agent-base.imports = [
./nix/templates/agent.nix
agentPackages
];
ruth.imports = [
./nix/templates/ruth.nix
agentPackages
];
# The full host stack (nix/host-modules/default.nix aggregator) plus
# the package/source wiring from this flake. The wiring is a
# plain config module setting the `services.hyperhive.c0re.*`
# package options via `lib.mkDefault` — no overlay involved, and
# an operator override still wins. Intended usage:
#
# imports = [ hyperhive.nixosModules.default ];
# services.hyperhive.enable = true;
#
default =
{ lib, pkgs, ... }:
{
imports = [ ./nix/host-modules ];
services.hyperhive.c0re = {
package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.default;
frontend = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.frontend;
assets = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.assets;
xdgIcons = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.xdg-icons;
hyperhiveFlake = lib.mkDefault "${sources.hyperhiveFlakeSource}";
# Narrow docs/ source, threaded as its own meta-flake input
# so doc edits don't re-hash the whole flake source.
hyperhiveDocs = lib.mkDefault "${sources.hyperhiveDocsSource}";
# Per-container toplevels — wired into
# `system.extraDependencies` when
# `services.hyperhive.c0re.preBuildAgentTemplates` is on so
# the host system closure pre-fetches the heavy build
# inputs. x86_64-linux only (nixosConfigurations are
# hardcoded to that system); the gate keeps aarch64 hosts
# from pulling them in via cross-build.
agentBaseToplevel = lib.mkDefault self.packages.x86_64-linux.agent-base-toplevel;
managerToplevel = lib.mkDefault self.packages.x86_64-linux.ruth-toplevel;
};
};
hive-ci = ./nix/host-modules/hive-ci.nix;
hive-forge = ./nix/host-modules/hive-forge;
};
nixosConfigurations =
let
mkContainer =
module:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ module ];
};
in
{
agent-base = mkContainer self.nixosModules.agent-base;
ruth = mkContainer self.nixosModules.ruth;
};
devShells = forAllSystems ({ pkgs, rust, ... }: import ./nix/devshell.nix { inherit pkgs rust; });
formatter = forAllSystems ({ treefmt-eval, ... }: treefmt-eval.config.build.wrapper);
checks = forAllSystems (
{
pkgs,
system,
treefmt-eval,
craneLib,
rust,
...
}:
import ./nix/checks.nix {
inherit
pkgs
craneLib
rust
self
system
treefmt-eval
;
}
);
};
}