{ pkgs, config, ... }: let userName = config.hyperhive.user.name; in { imports = [ ./harness-base.nix ]; systemd.services.hive-ag3nt = { description = "hive-ag3nt harness"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; # systemd units get a minimal PATH by default and don't inherit # `environment.systemPackages`. Pointing at `/run/current-system/sw` # gives the harness (and any tools claude shells out to via Bash) # access to everything declared in `systemPackages` — including # anything an agent adds to its own `agent.nix` — without having to # touch the service definition. path = [ "/run/current-system/sw" ]; environment = { SHELL = "${pkgs.bashInteractive}/bin/bash"; # `HOME` defaults to `/` for systemd services without a User= # set. With #658 the harness runs as the agent user — set HOME # explicitly so claude (which the harness spawns) finds its # `~/.claude/` session dir at the bind-mounted location. HOME = "/home/${userName}"; # Path to the merged agent static dist. The harness serves this # via `tower_http::ServeDir` for any request it doesn't route to # an API endpoint. `mergedDist` is the agent-default dist with # `hyperhive.frontend.extraFiles` layered on top — both come # from harness-base.nix. HIVE_STATIC_DIR = "${config.hyperhive.frontend.mergedDist}"; # Static runtime assets (branding + claude prompts). Set on the # unit directly — `environment.variables` in harness-base.nix only # populates /etc/profile, which systemd services don't inherit. HIVE_ASSETS_DIR = "${pkgs.hyperhive-assets}/share/hyperhive"; }; serviceConfig = { ExecStart = "${pkgs.hyperhive}/bin/hive-ag3nt serve"; Restart = "on-failure"; RestartSec = 2; # Run the harness as the per-agent user (#658). claude itself # spawned by the harness then runs as that user too — drops # root inside the container while sudo (`NOPASSWD: ALL` by # default, see harness-base.nix `hyperhive.user.passwordlessSudo`) # keeps the previous root-by-default surface available # explicitly for tools that need it. User = userName; Group = userName; }; }; }