# The hive this container runs on, read at boot rather than built in, so an # agent's closure does not carry it. # # hive-priv writes `/etc/hyperhive-hive-facts` into the container before every # start, one `KEY=value` line each: # # - `HYPERHIVE_HIVE_NAME`, `HYPERHIVE_HIVE_DOMAIN`; # - `HIVE_DASHBOARD_PORT`, read by the harness's web UI (7000 when absent); # - `HYPERHIVE_CLAUDE_CODE_PATH`, the claude-code the hive pins (`claude` in # ./default.nix runs this container's own when absent); # - `HYPERHIVE_OTEL_EXTRA_RESOURCE_ATTRIBUTES`, appended to # `OTEL_RESOURCE_ATTRIBUTES` by ./otel.nix (no extra labels when absent). # # Any of them may be absent: a hive-c0re older than the agent's build writes # fewer. Two readers hand the lines on: # # - an environment generator, for the container's systemd: it passes them to # every unit it starts, `machinectl shell` sessions (`hivectl choom`) # included, since those are transient units of the same manager. A unit's # own `Environment=` still overrides them. # - `/etc/set-environment`, for login shells that no unit starts: # `nixos-container root-login` / `run` (nsenter + `su -l`, which resets the # environment) and getty logins. # # Tested by `checks.script-test-agent-hive-facts`. { config, lib, pkgs, ... }: let userName = config.services.hyperhive.agent.user.name; # Shell builtins only: nothing is assumed on PATH this early. Only the known # keys are passed on. `|| [ -n "$key" ]` keeps a last line that has # no trailing newline. generator = pkgs.writeShellScript "hyperhive-hive-facts" '' hive=unknown if [ -r /etc/hyperhive-hive-facts ]; then while IFS='=' read -r key value || [ -n "$key" ]; do case "$key" in HYPERHIVE_HIVE_NAME) hive=$value ;; HYPERHIVE_HIVE_DOMAIN | HIVE_DASHBOARD_PORT) ;; HYPERHIVE_CLAUDE_CODE_PATH | HYPERHIVE_OTEL_EXTRA_RESOURCE_ATTRIBUTES) ;; *) continue ;; esac printf '%s=%s\n' "$key" "$value" done < /etc/hyperhive-hive-facts fi # Names claude's remote-control sessions `-`. printf 'CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX=%s-%s\n' "$hive" ${lib.escapeShellArg userName} ''; # Sourced by every shell's `/etc/set-environment`, so POSIX sh only. Each # line is exported as one word and never evaluated. profile = pkgs.writeText "hyperhive-hive-facts.sh" '' while IFS= read -r __hyperhive_fact; do case "$__hyperhive_fact" in ?*=*) export "$__hyperhive_fact" ;; esac done <<__HYPERHIVE_FACTS__ $(${generator}) __HYPERHIVE_FACTS__ unset __hyperhive_fact ''; in { environment.etc."systemd/system-environment-generators/50-hyperhive-hive-facts".source = generator; environment.etc."hyperhive/hive-facts.sh".source = profile; environment.extraInit = ". /etc/hyperhive/hive-facts.sh"; }