# Option declarations for `services.hyperhive.c0re.*` — the c0re # daemon's knobs plus the package/source options the flake's # `nixosModules.default` wires to its own outputs (they carry no # in-module defaults; see ../../../flake.nix). The read-only # `servedFrontend` option lives in ./theme.nix with the stylix wiring # that computes it. { pkgs, lib, config, ... }: { options.services.hyperhive.c0re = { enable = lib.mkOption { type = lib.types.bool; default = config.services.hyperhive.enable; defaultText = lib.literalExpression "config.services.hyperhive.enable"; description = "Enable hive-c0re coordinator daemon (auto-enabled by services.hyperhive.enable)."; }; package = lib.mkOption { type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.\${system}.default"; description = '' hyperhive workspace package. Provides `/bin/hive-c0re` (coordinator daemon) and `/bin/hivectl` (operator-facing host CLI for ad-hoc administration + the host admin socket). Wired to this flake's `packages..default` by `nixosModules.default` (via `lib.mkDefault`, so setting it here wins). ''; }; frontend = lib.mkOption { type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.\${system}.frontend"; description = '' Bundled frontend dist (see `nix/packages/frontend.nix`). Output has `dashboard/` and `agent/` subdirectories — hive-c0re serves `dashboard/` via `tower_http::ServeDir` from the path passed in `HIVE_STATIC_DIR`. Override to ship a custom dashboard SPA; the JSON contract (`/api/state`, the SSE streams, the action endpoints) is the source of truth for any replacement. ''; }; assets = lib.mkOption { type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.\${system}.assets"; description = '' Bundled static runtime assets (see `nix/packages/assets.nix`): the project's branding family + the claude system-prompt template + claude-settings JSON. Output has `share/hyperhive/{branding,prompts}/`; passed to hive-c0re's systemd unit via `HIVE_ASSETS_DIR` (`hive_sh4re::assets::*` resolve paths underneath). Override to ship customised branding or prompts without rebuilding the rust derivation. ''; }; xdgIcons = lib.mkOption { type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.\${system}.xdg-icons"; description = '' XDG icon set + .desktop entries for hyperhive processes (see `nix/packages/hive-xdg-icons.nix`), installed into the host system packages so desktop environments can match hyperhive processes to their icon. ''; }; hyperhiveFlake = lib.mkOption { type = lib.types.str; defaultText = lib.literalMD "the hyperhive flake's own filtered source store path"; description = '' URL of the hyperhive flake (no fragment). Inlined into each per-agent `flake.nix` at `inputs.hyperhive.url`. The per-agent flake then pulls `hyperhive.nixosConfigurations.agent-base` to build the container. Wired by `nixosModules.default` to this flake's own filtered source — only override if you want agents tracking a different ref. ''; }; hyperhiveDocs = lib.mkOption { type = lib.types.str; defaultText = lib.literalMD "the docs/ tree's own store path"; description = '' URL of the narrow `docs/` source (no fragment). Inlined into the generated meta `flake.nix` at `inputs.hyperhive-docs.url` and threaded to each agent as `hyperhive.docs.source`, from which the harness resolves `$HIVE_DOCS_DIR`. Its own store path — separate from `hyperhiveFlake` — so a doc edit only re-locks this input instead of rebuilding every agent container. ''; }; agentBaseToplevel = lib.mkOption { type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.x86_64-linux.agent-base-toplevel"; description = '' Pre-built agent-base container system closure, pulled into the host system closure when `preBuildAgentTemplates` is on. Wired by `nixosModules.default`; only evaluated when that option is enabled. ''; }; managerToplevel = lib.mkOption { type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.x86_64-linux.ruth-toplevel"; description = '' Pre-built manager (ruth) container system closure — see `agentBaseToplevel`. ''; }; nixpkgsFlake = lib.mkOption { type = lib.types.str; default = "path:${pkgs.path}"; defaultText = lib.literalMD "`\"path:\${pkgs.path}\"`"; description = '' Store-path URL for the `nixpkgs` input in the generated meta flake. The meta flake declares this as a top-level input and wires `inputs.hyperhive.inputs.nixpkgs.follows = "nixpkgs"` so every agent container evaluates with this exact nixpkgs. Defaults to `"path:''${pkgs.path}"` — the store path of the nixpkgs the host NixOS module was evaluated with. When the operator sets `inputs.hyperhive.inputs.nixpkgs.follows = "nixpkgs"` in their host flake, `pkgs.path` resolves to the host's own nixpkgs, so agents transparently track the same channel as the host. Override to pin agents to a specific nixpkgs version regardless of the host's channel. ''; }; dashboardPort = lib.mkOption { type = lib.types.port; default = 7000; description = "TCP port the hive-c0re dashboard listens on."; }; operatorPronouns = lib.mkOption { type = lib.types.str; default = "she/her"; example = "they/them"; description = '' Operator pronouns, free text. Threaded into every agent container as the `HIVE_OPERATOR_PRONOUNS` env var; the harness substitutes it into the agent / manager system prompt at boot so claude refers to the operator naturally in third person ("ask her", "tell them", etc.). Changes propagate to running agents on the next `↻ R3BU1LD` — forwards as a meta flake env-var bump, no per-agent 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. 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 .#agent-base-toplevel` once manually to warm the store. ''; }; contextWindowTokens = lib.mkOption { type = lib.types.attrsOf lib.types.int; default = { haiku = 200000; sonnet = 1000000; opus = 1000000; }; example = { haiku = 150000; sonnet = 900000; }; description = '' Per-model context-window sizes in tokens. Each key is a model-family short name matched case-insensitively as a substring of the active model name at runtime (e.g. `"sonnet"` matches `"claude-sonnet-4-5"`). The defaults cover the known Anthropic families; add entries for new models or override existing ones here to change the window for all agents at once. Passed to `hive-c0re serve` as JSON and injected into every container's harness service environment as `HIVE_CONTEXT_WINDOW_TOKENS_`. Changes propagate on the next `↻ R3BU1LD` — no per-agent approval needed. ''; }; modelPrices = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule { options = { input = lib.mkOption { type = lib.types.numbers.nonnegative; description = "USD per million input tokens."; }; output = lib.mkOption { type = lib.types.numbers.nonnegative; description = "USD per million output tokens."; }; cache_read = lib.mkOption { type = lib.types.numbers.nonnegative; description = "USD per million cache-read tokens."; }; cache_write = lib.mkOption { type = lib.types.numbers.nonnegative; description = "USD per million cache-creation (write) tokens."; }; }; } ); # Current Anthropic list prices for the Claude 4.x family (Opus # 4.x, Sonnet 4.x, Haiku 4.5); cache_write is the 1-hour cache-TTL # price (the default through the Claude subscription the agents run # on). Keep in sync with `builtin_prices` in # hive-c0re/src/hive_stats.rs. default = { opus = { input = 5.0; output = 25.0; cache_read = 0.5; cache_write = 10.0; }; sonnet = { input = 3.0; output = 15.0; cache_read = 0.3; cache_write = 6.0; }; haiku = { input = 1.0; output = 5.0; cache_read = 0.1; cache_write = 2.0; }; }; example = { sonnet = { input = 3.0; output = 15.0; cache_read = 0.3; cache_write = 6.0; }; }; description = '' Per-model USD prices (per **million** tokens) used for the hive-wide cost *estimate* on the dashboard's ST4TS tab. Each key is a model-family short name matched case-insensitively as a substring of the active model id at runtime (e.g. `"sonnet"` matches `"claude-sonnet-4-5"`); the longest matching key wins, so a specific entry beats a generic family name. Any model not covered by this table falls back to hive-c0re's built-in estimate. The defaults track Anthropic list pricing at the time of writing — override them here to keep the estimate current without a code change. Passed to `hive-c0re serve` as JSON via `--model-prices`; read only by hive-c0re itself (not injected into containers). Changes apply on the next host rebuild. ''; }; agentCpuQuota = lib.mkOption { type = lib.types.str; default = "200%"; example = "400%"; description = '' systemd `CPUQuota=` applied to every agent container via a `container@h-.service.d/` drop-in written on each spawn/rebuild. Expressed as a percentage of one CPU core — `"200%"` allows each agent to use up to 2 cores. Bump this if agents are hitting CPU limits during builds or heavy tool use. For a hive-wide cap across all containers, set `systemd.slices.machine.serviceConfig.CPUQuota` in your NixOS config (all nspawn containers live in `machine.slice`). ''; }; agentMemoryMax = lib.mkOption { type = lib.types.str; default = "4G"; example = "8G"; description = '' systemd `MemoryMax=` applied to every agent container via the same drop-in as `agentCpuQuota`. ''; }; buildSlots = lib.mkOption { type = lib.types.ints.positive; default = 1; example = 2; description = '' Number of nix-heavy job-queue nodes (container prebuilds, profile swaps, first-spawn creates, meta lock bumps) hive-c0re runs concurrently. The default of 1 serializes all heavy nix work; raise it on hosts with the cores/RAM to build several agent toplevels at once. Per-agent correctness is independent of this count — each agent's container-affecting operations are serialized by its lifecycle lease regardless. ''; }; adminUsers = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; example = [ "alice" ]; description = '' Login users granted **sudoless `hivectl`**. Each is added to the `hive-admin` group, which group-owns the host admin socket (`/run/hyperhive/host.sock`, mode `0660`) — so listed users drive `hivectl` (and thus the whole hive) without `sudo`. This is a real privilege grant: the admin socket is *full* hive control — spawn / kill / destroy / deploy — see `docs/boundary.md`. Keep the list to trusted operators. Empty (the default) keeps the socket root-only, as before. ''; }; }; }