# Agent config knobs Optional per-agent knobs the meta flake wires into the container from `services.hyperhive.agents.`, read at boot or per turn by the harness. Absent means the default. (The claude spawn + compaction themselves live in [claude-invocation](claude-invocation.md).) ## Reference docs (`hyperhive.docs.enable`) ```nix hyperhive.docs.enable = true; # default: false (true for the manager agent) ``` Makes the hyperhive `docs/` tree available inside the container at a nix store path read from `$HIVE_DOCS_DIR`, and injects a single pointer sentence into the agent's system prompt so it knows the docs exist and where to find them. The tree is served by `claude --add-dir` so the full markdown is readable during every turn. Enabled by default only for the root/manager agent (`nix/templates/ruth.nix`). Any agent can opt in by adding the line above to its `agent.nix`. The `docs/` source is a narrow flake input (`hyperhive-docs`) tracked separately from the main `hyperhive` flake so editing docs re-locks only that input — not every agent's container gets rebuilt on a doc-only change. ## Agent icon ```nix hyperhive.icon = ./icon.svg; # default: null (falls back to shared hyperhive logo) ``` Path to an SVG file used as this agent's visual identity — shown in the per-agent page header, as the page favicon, and uploaded to the agent's Forgejo profile avatar (via the `forge-avatar-sync` boot unit) and Matrix profile avatar (set by `hive-matrix-daemon` over its live Client). Commit the SVG next to `agent.nix` in the config repo and reference it as a relative path. When `null` (the default), the agent falls back to the shared hyperhive branding mark. The harness serves whichever icon is active at `GET /icon` on the per-agent web port. ## `user.passwordlessSudo` ```nix hyperhive.user.passwordlessSudo = true; # default ``` Grants the per-agent unix user passwordless `sudo` (`NOPASSWD: ALL`). Enabled by default so claude's shell tools work for operations that need root inside the container (`systemctl`, package managers in dev shells, etc.) — the agent user gets root explicitly via `sudo` rather than running as root itself. Set to `false` for agents that should be strictly unprivileged. Any tool invocation that needs root then fails loudly with the standard sudo rejection rather than silently succeeding — easier to audit. `hyperhive.user.uid`, `hyperhive.user.gid`, and `hyperhive.user.name` are the companion options; see `docs/agent-hierarchy.md` — "Harness systemd unit shape" for the full `user.*` surface. ## Dashboard links ```nix hyperhive.dashboardLinks = [ { label = "Stats"; icon = "📊"; url = "http://localhost:9001/stats"; } { label = "Scratchpad"; url = "http://localhost:8080"; } ]; ``` Declares extra navigation links that appear in the per-agent page header alongside the built-in forge / config / container links. Each entry has: | Field | Required | Description | |-------|----------|-------------| | `label` | yes | Display text shown in the icon strip tooltip and meta-nav. | | `url` | yes | Absolute URL — may include a different port (the dashboard renders it as a plain anchor). | | `icon` | no | Emoji or short glyph prefix. Defaults to empty string. | The list is written to `/hyperhive-dashboard-links.json` by a one-shot systemd unit at container boot. The harness's own web UI (`agent_links` in `hive-agent/src/web_ui/state.rs`) reads the file on each `/api/state` snapshot and appends the entries to the per-agent nav as `kind = External` links — no `hive-c0re` / operator-dashboard involvement, and no code change needed to pick up a new entry. Omitting the option (default empty) produces no extra links. ## Custom static files ```nix hyperhive.frontend.extraFiles = { "games/bitburner" = { source = ./bitburner-dist; # path relative to agent.nix # target defaults to attribute name: "games/bitburner" }; "my-page" = { source = ./my-page.html; target = "my-page.html"; # explicit override }; }; ``` Layers additional files over the default per-agent web UI dist. Each attribute defines one overlay entry: - **`source`** — a Nix path (file or directory) copied into the merged static tree. Evaluated at nix build time; the resulting derivation is pointed at by `HIVE_STATIC_DIR`. - **`target`** — destination path within the merged tree, used as both the served URL prefix (`//…`) and the on-disk layout. Defaults to the attribute name. Forward slashes create nested layouts (`"games/bitburner"` serves at `/games/bitburner/…`). Constraints: `target` must start with an alphanumeric or `_` and contain only alphanumerics, `_`, `.`, `/`, `-`. `..` segments are rejected by a config assertion. The merge step refuses to overwrite files already present in the default dist — pick a target name that does not collide with existing paths (`static/`, `index.html`, etc.). The default dist ships at `hyperhive.frontend.dist` (the `hyperhive-frontend` package output, read-only). To replace the entire UI rather than layer on top, override `frontend.dist` directly. ## Connectivity overrides Two `hyperhive.forge.*` / `hyperhive.matrix.*` options override where the per-agent daemons connect. Both rarely need changing on a standard single-host deploy, but are useful for multi-hive or custom-network setups. ```nix hyperhive.forge.url = "http://forge.example:3000"; # default: null hyperhive.matrix.url = "https://matrix.example"; # default: null ``` **`hyperhive.forge.url`** — base URL of the Forgejo instance. Used by a one-shot boot unit (`tea-login`) that writes `~/.config/tea/config.yml` directly from the agent's `forge-token`, so `tea` and `hive-forge` work without an interactive auth step. The unit is a no-op when `forge-token` is absent. Override when the agent should connect to a Forgejo on a different host or port (e.g. a swarm peer's forge). Validated: must be an `http://` or `https://` URL, or `null`. **Defaults to `null`, meaning "no forge" — not a guessed address.** A loopback default would only ever be correct when the forge shares the agent's network namespace, and inside a container `localhost` is the agent itself, so the default was a value that built fine and then talked to the wrong machine. With `null` the `tea-login` and `forge-avatar-sync` units are not generated at all: an absent integration rather than a misdirected one. You do not normally set this — hive-c0re renders the host's real forge URL into every agent, and refuses to write a meta flake without one, so `null` only survives where the agent modules are evaluated outside a hive. **`hyperhive.matrix.url`** — homeserver URL used by `hive-matrix-daemon` when connecting via the matrix-sdk. hive-c0re writes it into every agent at deploy time as the gateway-routed `chat.` URL, so isolated agents can reach the homeserver. Override per-agent when an agent should talk to a different homeserver — for example a remote hive's tuwunel reached over a VPN, or an external Matrix server for a federation-only agent. **Defaults to `null`, meaning "no matrix" — same reasoning as `forge.url` above** (a loopback default would resolve inside the agent's own netns to the agent itself, not the homeserver). With `null` the daemon has no homeserver and no-ops exactly as it does without a token. The hive only forwards `HIVE_MATRIX_URL` when it actually has a matrix vhost to name, so `null` survives where a hive runs no homeserver, or where the agent modules are evaluated outside a hive. ## Claude Code plugins The harness installs Claude Code plugins before the serve loop opens. Three per-agent `agent.nix` options control this: ```nix hyperhive.claudeMarketplaces = [ # default "anthropics/claude-plugins-official" "${hyperhive.packages.claude-plugins}" # hive's own local marketplace, registered as `hyperhive` ]; hyperhive.claudePlugins = [ # default "skill-creator@claude-plugins-official" "base@hyperhive" ]; hyperhive.claudePluginsAutoUpdate = false; # default ``` - **`claudeMarketplaces`** — list of marketplace sources passed to `claude plugin marketplace add `. Defaults to Anthropic's official marketplace plus hyperhive's own `claude-plugins` nix package (see `nix/packages/claude-plugins.nix`) — a local-path marketplace registered under the name `hyperhive`, so a hive-authored skill needs no forge repo or git remote to ship. Override or extend to add custom marketplaces. Idempotent — re-adding an existing source is a no-op. - **`claudePlugins`** — list of plugin specs passed to `claude plugin install `. Each spec is installed on every boot (`install` is expected to be idempotent); failures log a warning but do not abort boot. Defaults to Anthropic's `skill-creator` (so every agent can author, refine, and evaluate its own skills) plus hyperhive's own `base` plugin — skills that apply to every agent regardless of role (currently just `state-hygiene`) — all without any per-agent wiring. > Both plugin lists follow ordinary NixOS list-option semantics: a > per-agent definition **replaces** the default, it does not extend it. > An agent that sets `claudePlugins` and still wants the defaults has > to list `skill-creator@claude-plugins-official` and `base@hyperhive` > explicitly alongside its own entries — likewise for the two default > entries in `claudeMarketplaces`. - **`claudePluginsAutoUpdate`** — when `true`, runs `claude plugin marketplace update` before installing plugins to pull the latest index. Disabled by default to keep boot times short and plugin versions pinned. ## `cargo.shortMessages` ```nix hyperhive.cargo.shortMessages = true; # default ``` When enabled (the default), the harness injects a `cargo` shell function into `/etc/hyperhive/bash-env.sh` that transparently appends `--message-format short` to compile subcommands (`build`, `check`, `clippy`, `test`, `run`, `doc`, `bench`, `install`, `rustc`, `fix`). This suppresses the per-crate progress lines that flood the response window, leaving only warnings and errors. The function handles `+toolchain` selectors (`cargo +nightly build`) and passes through cleanly when `--message-format` is already present. Non-compile subcommands (`new`, `add`, third-party `cargo-*`) are left untouched. Set to `false` for agents that parse cargo's JSON output programmatically and do not pass `--message-format json` themselves. ## API-key backend (`useApiKey` / `backendEnvironmentFile`) ```nix hyperhive.useApiKey = true; # default: false hyperhive.backendEnvironmentFile = "/agents/myagent/harness/openrouter.env"; # default: null hyperhive.model = "anthropic/claude-3.5-sonnet"; # provider-specific model string ``` Runs this agent's `claude` against an API-key backend (e.g. OpenRouter) instead of a Claude subscription via OAuth. Two options, paired — each is a no-op without the other: - **`useApiKey`** tells the harness itself not to wait for a Claude OAuth session: at boot, `LoginState::from_dir` reports `Online` without checking `~/.claude/` (`hive_agent::login::using_api_key`, reads `HIVE_USE_API_KEY`), and the fact is stamped into the consolidated harness state file so the operator dashboard also stops reading this agent's empty `~/.claude/` as "needs login". An api-key agent that hits a real 401 (the key itself is bad) still surfaces `needs_login` — only the boot-time "have I ever logged in" check is bypassed, not the auth-failure path. - **`backendEnvironmentFile`** points at an operator-managed file (outside the nix store, one `KEY=value` per line, systemd `EnvironmentFile` syntax) supplying the credentials `claude` itself reads from the environment — typically `ANTHROPIC_API_KEY` and `ANTHROPIC_BASE_URL`. Loaded as an *optional* `EnvironmentFile` (leading `-`), so setting the option before the file exists doesn't strand the harness at boot. Provision the file once, out of band (never through nix — an API key in the store is world-readable and travels with the flake closure): ```sh # on the host, once per agent that should use an api-key backend sudo install -m 0600 -o root /dev/stdin \ /var/lib/hyperhive/agents//harness/openrouter.env <