hyperhive — per-agent options

hyperhive.allowedRecipients

Names this agent is allowed to send to via mcp__hyperhive__send. Empty list (the default) means unrestricted — the agent can message any peer, the operator, or the manager. Non-empty list constrains the surface: only the listed names + the manager (always allowed) get through; anything else returns an error string to claude without touching the broker. The operator (operator) needs to be in the list if the agent should be able to surface output on the dashboard.

Useful for sandboxing untrusted sub-agents — set [ "manager" ] to scope them to manager-only chatter. The manager itself is always exempt; this option only affects sub-agent send.

Type: list of string

Default:

[ ]

Example:

[
  "alice"
  "manager"
]

Declared by:

hyperhive.autoCompact

Enable proactive watermark-based compaction. When true (the default) the harness automatically runs a notes-checkpoint turn followed by /compact once the context window crosses 75% of the model’s limit, keeping later turns from hitting the hard overflow path. Set to false to disable proactive compaction entirely (HIVE_COMPACT_WATERMARK_TOKENS=0); the reactive path (compact-on-overflow when the session is already past the limit) still applies.

Disable for agents that run large-context models (sonnet/opus) where the heuristic fires too early and discards useful history before the session is actually close to the limit.

Type: boolean

Default:

true

Declared by:

hyperhive.availableModels

Models offered in the per-agent web UI’s model quick-picker. Rendered into the HIVE_AVAILABLE_MODELS environment variable (comma-separated) which the harness surfaces to the agent UI, so the picker lists exactly these models instead of a hardcoded set.

Configure hive-wide by setting a shared default (e.g. in your agent.nix shared defaults) or per-agent to narrow the menu — for example a haiku-only agent can hide opus and sonnet. The current model is still set by hyperhive.model and remains switchable at runtime via the UI; this option only controls which choices the picker presents.

Values are the short model names that claude --model accepts: "haiku", "sonnet", "opus" (or any future identifier).

Type: list of string

Default:

[
  "haiku"
  "sonnet"
  "opus"
]

Example:

[
  "sonnet"
  "opus"
]

Declared by:

hyperhive.cargo.shortMessages

Auto-inject --message-format short on cargo compile subcommands (build, check, clippy, test, run, doc, bench, install, rustc, fix) when claude (or anything else) invokes cargo inside this container. Saves tokens + context — the verbose default output floods the response window with per-crate progress lines that carry no signal beyond the warning/error summary.

Implementation: contributes a cargo shell function to /etc/hyperhive/bash-env.sh (see hyperhive._bashEnvFragments). Loaded via BASH_ENV for non-interactive shells (bash -c — what the claude Bash tool runs) and sourced from programs.bash.interactiveShellInit for interactive shells. The function:

Set to false for agents that need full cargo output (e.g. tooling that parses --message-format json programmatically and doesn’t pass the flag explicitly).

Type: boolean

Default:

true

Example:

false

Declared by:

hyperhive.claudeMarketplaces

Claude Code plugin marketplaces to add at harness boot. Each entry is passed to claude plugin marketplace add <source> (owner/repo, full git URL, or local path). Idempotent — re-adding an existing marketplace is treated as success. Required before hyperhive.claudePlugins entries that reference a marketplace (e.g. foo@claude-plugins-official). Rendered to /etc/hyperhive/claude-marketplaces.json.

Defaults to Anthropic’s official marketplace; agents get it out of the box without any per-agent.nix wiring.

Type: list of string

Default:

[
  "anthropics/claude-plugins-official"
]

Example:

[
  "anthropics/claude-plugins-official"
  "anthropics/claude-plugins-community"
]

Declared by:

hyperhive.claudePlugins

Claude Code plugins to install at harness boot. Each entry is passed verbatim to claude plugin install <spec> once per container start, before the turn loop opens. claude plugin install is expected to be idempotent, so reinstalling on every boot is cheap. Failures log a warning but do not abort boot — a missing plugin is preferable to a non-serving agent. Rendered to /etc/hyperhive/claude-plugins.json; the harness reads it via plugins::install_configured.

Type: list of string

Default:

[ ]

Example:

[
  "formatter@my-marketplace"
  "thinking-tools@anthropics"
]

Declared by:

hyperhive.claudePluginsAutoUpdate

When true, the harness runs claude plugin marketplace update before installing plugins at boot, pulling the latest index from all configured marketplaces. Disabled by default — most agents want pinned plugin versions and the network round-trip adds to boot time. Enable for agents that should always install the latest available version of their plugins.

Type: boolean

Default:

false

Declared by:

Extra navigation links surfaced on the hive-c0re dashboard card for this agent. Declare any additional web UI pages the agent exposes — stats pages, custom UIs, etc. hive-c0re reads the JSON file this option produces at each container-view snapshot and attaches the links to the agent card without any code changes.

Type: list of (submodule)

Default:

[ ]

Example:

[
  { label = "Stats"; icon = "📊"; url = "http://localhost:9001/stats"; }
]

Declared by:

hyperhive.dashboardLinks.*.icon

Optional icon emoji or short glyph.

Type: string

Default:

""

Declared by:

hyperhive.dashboardLinks.*.label

Display label for the link.

Type: string

Declared by:

hyperhive.dashboardLinks.*.url

Full URL (may include a different port, e.g. http://localhost:9001/stats)\.

Type: string

Declared by:

hyperhive.docs.enable

Whether to enable make the hyperhive reference docs (the repo docs/ tree, shipped read-only as the standalone hyperhive-docs derivation) available in-container. When enabled the harness exposes the docs dir to claude via claude --add-dir, so the markdown is readable at $HIVE_DOCS_DIR/, and appends a single pointer sentence to the agent’s system prompt so it knows the docs exist (see hive-agent::prompt::render). Default-on for the root/manager agent (see ../templates/ruth.nix), off elsewhere; any agent can flip it from its agent.nix. .

Type: boolean

Default:

false

Example:

true

Declared by:

hyperhive.docs.source

Store path of the reference-docs tree exposed at $HIVE_DOCS_DIR when hyperhive.docs.enable is set. Defaults to the flake’s reference-docs package (the nix/packages/reference-docs.nix build) so a standalone container build from a full checkout works unchanged. The generated meta flake overrides this with the narrow hyperhive-docs flake input so a doc edit only re-locks that input instead of rebuilding the container from a re-hashed hyperhive source.

Type: absolute path

Default: hyperhive.packages.reference-docs (built from the repo docs/ tree)

Declared by:

hyperhive.effortLevel

Baseline claude effort level for this agent. Rendered into the HIVE_DEFAULT_EFFORT environment variable; the harness resolves effort as operator-override-file → this env → built-in "medium", and passes the result to claude --effort at turn launch.

Ascending scale: "low" (minimal thinking budget), "medium" (default — balanced), "high" (platform default), "xhigh" (recommended for autonomous coding on capable models), "max" (maximum thinking budget, highest cost). The operator can override at runtime per-agent via the web UI (applied on the next session); any rebuild that changes this option resets that override.

Type: one of “low”, “medium”, “high”, “xhigh”, “max”

Default:

"medium"

Example:

"high"

Declared by:

hyperhive.extraMcpServers

Extra MCP servers claude sees alongside the hyperhive tool surface. Keys are the server names (claude addresses tools as mcp__<key>__<tool>). Rendered to /etc/hyperhive/extra-mcp.json at activation time; the harness reads that file at boot and merges it into --mcp-config + --allowedTools. Take effect on the agent’s next harness restart (no operator approval needed beyond whatever brought the new agent.nix into deployed/*).

The bash entry above is illustrative only — it’s auto-injected below (hyperhive.extraMcpServers.bash via lib.mkDefault) already tracking hyperhive.mcp.bashHttpPort, so overriding it directly with a hardcoded port (as shown) is unusual and will drift if bashHttpPort is changed separately; bump bashHttpPort instead.

Type: attribute set of (submodule)

Default:

{ }

Example:

{
  matrix = {
    command = "/run/current-system/sw/bin/mcp-matrix";
    args = [ "--config" "/state/matrix.toml" ];
    env.MATRIX_HOMESERVER = "https://matrix.example.org";
    allowedTools = [ "send_message" "join_room" ];
  };
  bash = {
    type = "http";
    url = "http://127.0.0.1:8791/mcp";
  };
}

Declared by:

hyperhive.extraMcpServers.<name>.allowedTools

Tool names this MCP server is auto-approved to call via --allowedTools. Single entry "*" (the default) means “every tool from this server” — convenient but trusting. Tighten to a specific list when you only want a subset. Names are bare (e.g. send_message); the harness prepends mcp__<server-key>__ at build time.

Type: list of string

Default:

[
  "*"
]

Example:

[
  "send_message"
  "join_room"
]

Declared by:

hyperhive.extraMcpServers.<name>.args

Args passed to the MCP server binary. "stdio" only.

Type: list of string

Default:

[ ]

Declared by:

hyperhive.extraMcpServers.<name>.command

Absolute path to the MCP server binary. Use ${pkgs.foo}/bin/foo or /run/current-system/sw/bin/foo. Required when type = "stdio"; ignored (leave null) for "http".

Type: null or string

Default:

null

Declared by:

hyperhive.extraMcpServers.<name>.env

Environment variables for the MCP server child process. "stdio" only.

Type: attribute set of string

Default:

{ }

Declared by:

hyperhive.extraMcpServers.<name>.type

Transport for this MCP server. "stdio" (the default) spawns command as a fresh child process every turn, talking JSON-RPC over its stdin/stdout — existing entries need zero changes to keep this behaviour. "http" points claude at a long-lived streamable-http url instead: no per-turn spawn, no re-registration race, same shape as the built-in hyperhive surface (hive-mcp-http) — use this for a server backed by an always-on daemon. command/args/env only apply to "stdio"; url only to "http".

Type: one of “stdio”, “http”

Default:

"stdio"

Declared by:

hyperhive.extraMcpServers.<name>.url

Streamable-http URL (e.g. http://127.0.0.1:8791/mcp) of the always-on daemon serving this MCP surface. Required when type = "http"; ignored (leave null) for "stdio".

Type: null or string

Default:

null

Declared by:

hyperhive.extraWebProxies

Transparent reverse-proxies mounted under /extra/ in the per-agent web UI. Each attribute name becomes the sub-path and the value is the upstream. E.g. { "stats" = "http://127.0.0.1:3737"; } mounts a proxy at /agent/<name>/extra/stats/ that forwards to port 3737 with the prefix stripped. All user-declared proxies live under /extra/ so they can never conflict with native agent endpoints (/api/*, /events/*, etc.).

The upstream value is either an http(s):// URL or a Unix domain socket, spelled unix:<path> (e.g. unix:/run/myapp/http.sock) — for agents whose secondary web server only listens on a UDS.

Intended for agents that run secondary web servers in the same container. Static assets served by the secondary app must use relative paths to resolve correctly under the sub-path prefix.

Sets the HIVE_EXTRA_WEB_PROXIES environment variable (JSON object) on the harness service unit.

Type: attribute set of string

Default:

{ }

Example:

{ "stats" = "http://127.0.0.1:3737"; }

Declared by:

hyperhive.forge.url

Base URL of the hyperhive-managed Forgejo. Used at container boot by a oneshot systemd unit that calls tea login add --url <this> --token "$(cat $HYPERHIVE_STATE_DIR/forge-token)" (= /agents/<name>/state/forge-token) so the agent’s claude can shell out to tea without an extra auth dance. No-op when the forge-token file is missing (i.e. hive-forge isn’t running on the host).

Type: string

Default:

"http://localhost:3000"

Example:

"http://forge.internal:3000"

Declared by:

hyperhive.frontend.dist

The shipped frontend dist (built by nix/packages/frontend.nix). Output layout: dashboard/ (used by hive-c0re on the host) and agent/ (used here, layered with extraFiles below at activation time). Override to ship a fully custom per-agent SPA; the JSON contract (/api/state, /events/stream, the action endpoints) is the source of truth for any replacement.

Type: package

Default: hyperhive.packages.frontend (the flake’s frontend dist)

Declared by:

hyperhive.frontend.extraFiles

Per-agent additions layered on top of the default frontend dist. Each entry copies its source into the served static tree under target. Useful for shipping a self-contained agent-specific surface alongside the standard agent UI (e.g. the bitburner agent’s game page at /bitburner/).

The default agent UI remains served at /; entries here only add new routes and never replace the default. Overwrite semantics are hard-fail: if target collides with an existing file or directory in the default dist (or with a prior entry’s target), the mergedDist build aborts with refusing to overwrite existing path '<target>' in the default dist. To override a default file, fork the dist via hyperhive.frontend.dist instead — extraFiles is for pure additions.

target must be a relative path inside the static dir. An assertion rejects leading / and .. segments at config eval time (string-concat-into-paths safety, even though agent.nix goes through operator review before deploy).

Type: attribute set of (submodule)

Default:

{ }

Example:

{
  bitburner = {
    source = ./bitburner-dist;
    # served at GET /bitburner/...
  };
}

Declared by:

hyperhive.frontend.extraFiles.<name>.source

Source file or directory to layer over the default agent dist. A path (relative to agent.nix or absolute) — nix copies its contents into the merged static tree.

Type: absolute path

Declared by:

hyperhive.frontend.extraFiles.<name>.target

Destination path within the merged static tree, used as both the served URL prefix (/<target>/...) and the on-disk layout in the merged derivation. Defaults to the attribute name. Use forward slashes for nested layouts (e.g. "games/bitburner").

Constrained shape: must start with an alphanumeric or _, and only contain alphanumerics, _, ., /, -. .. segments are separately rejected at config eval time.

Type: string matching the pattern ^[A-Za-z0-9_][A-Za-z0-9_./-]*$

Default: the attribute name

Declared by:

hyperhive.frontend.mergedDist

Computed: the merged static tree consumed by the harness via HIVE_STATIC_DIR. Composed at evaluation time by copying hyperhive.frontend.dist’s agent/ subdir as the base, then layering each extraFiles entry on top. Read-only — do not set directly.

Type: package (read only)

Declared by:

hyperhive.github.enable

Install the GitHub integration in this agent: a gh CLI wrapper and a git credential helper for https://github.com, both authenticated from an operator-supplied personal access token (PAT). The PAT is written to <state>/github-token out of band — the dashboard credentials tab or hivectl github set-token — so giving an agent GitHub is a runtime paste, no per-agent config or rebuild. The wrappers read the token file at invocation, so a freshly-pasted PAT takes effect immediately; until one exists, gh / git push just fail unauthenticated.

github.com only. git authenticates as x-access-token + the PAT (GitHub ignores the username for PAT auth); gh derives its identity from the token. Keep the PAT minimally scoped: the agent has passwordless sudo, so a compromised agent can act within the token’s scopes — scope is the real blast-radius limiter.

On by default. Host-driven: set services.hyperhive.github.enable = false to turn the integration off hive-wide (meta.rs propagates the override into every agent).

Type: boolean

Default:

true

Declared by:

hyperhive.gui.enable

Run Weston with the VNC backend as a systemd service, for in-browser GUI access via the harness /screen/ws WebSocket relay. Renders in software (pixman) — no GPU, DRM, or VT access, so no extra container capabilities are needed.

Weston binds a fixed VNC port (hyperhive.gui.vncPort) on the container’s own loopback. Network isolation is unconditional (each agent has its own netns), so a fixed port can’t collide across containers — no per-agent hashing needed. The harness learns the port from the HIVE_GUI_VNC_PORT env var (set by the harness service when gui is enabled). The unit is Type = "simple" so a misconfigured weston degrades to a restart loop instead of blocking nixos-container update.

Weston, the wayland client and the agent harness run as the agent’s own non-root user (hyperhive.user.name), sharing one session: a fixed XDG_RUNTIME_DIR=/run/gui, one wayland display, and one D-Bus session bus at /run/gui/bus (gui-dbus.service), so GUI clients need no private dbus-run-session.

Type: boolean

Default:

false

Declared by:

hyperhive.icon

Path to an SVG file used as this agent’s icon — shown on the dashboard and the per-agent web UI (header + favicon). Commit the SVG into the agent’s config repo next to agent.nix and reference it as a relative path (./icon.svg).

When null (the default) the agent falls back to the shared hyperhive logo. The harness serves the icon (configured or default) at GET /icon on the per-agent web port.

Type: null or absolute path

Default:

null

Example:

./icon.svg

Declared by:

hyperhive.matrix.enable

Enable per-agent matrix integration via hive-matrix-daemon. When true (the default), the harness:

Set to false for agents that should NOT have matrix tools at all (e.g. agents on a host without hyperhive.matrix.enable on the meta side). When token file is absent the daemon and MCP both no-op cleanly anyway, so false is rarely necessary.

Type: boolean

Default:

true

Declared by:

hyperhive.matrix.url

Matrix homeserver URL the agent’s hive-matrix-daemon connects to. At runtime hive-c0re forwards the isolation-aware URL (matrix.<domain> via the gateway) so isolated agents reach the homeserver without crossing host loopback. Override per-agent when an agent should talk to an external homeserver instead (e.g. a federation-only setup or a remote hive’s tuwunel reached via a vpn).

Type: string

Default:

"http://localhost:8008"

Example:

"https://matrix.darkest.space"

Declared by:

hyperhive.matrixAccounts

Declare additional matrix accounts served by the single hive-matrix-daemon (one matrix-sdk Client + sync loop each), beyond the agent’s built-in hive-internal account. The attribute name keys each account (unique by construction) and is the handle the matrix MCP tools target via their account argument.

The hive-internal account is always present and is the primary: it is named main, synthesized by the daemon from hyperhive.matrix.url + <state>/matrix-token + <state>/matrix-sdk-state, and is the account a tool call acts as when it omits account. You never declare it here — this option is only for the extras (e.g. an external public-matrix account).

Leave empty (the default) for the common single-account case: the agent then has only main. When non-empty, the extras are serialized to the daemon’s HIVE_MATRIX_ACCOUNTS environment variable and the daemon appends them after main. Requires hyperhive.matrix.enable (there is no main to extend otherwise).

Type: attribute set of (submodule)

Default:

{ }

Example:

{
  ccc = {
    tokenFile = "/agents/dmatrix/state/matrix-token-ccc";
    sessionDir = "/agents/dmatrix/state/matrix-sdk-state-ccc";
    homeserver = "https://matrix.example.org";
  };
}

Declared by:

hyperhive.matrixAccounts.<name>.homeserver

Homeserver URL for this account. When null (the default), the account falls back to hyperhive.matrix.url. Set it for an account on a different homeserver than the agent’s default (e.g. an external public-matrix account).

Type: null or string

Default:

null

Example:

"https://matrix.example.org"

Declared by:

hyperhive.matrixAccounts.<name>.sessionDir

Per-account matrix-sdk sqlite store directory (crypto keys

Type: string

Example:

"/agents/dmatrix/state/matrix-sdk-state-ccc"

Declared by:

hyperhive.matrixAccounts.<name>.tokenFile

Path to this account’s bearer-token file. The daemon reads the token from here to restore the matrix session; how the file gets populated is the provisioner’s concern (an operator-supplied secret for an external account). The daemon skips an extra account whose token file is absent.

Type: string

Example:

"/agents/dmatrix/state/matrix-token-ccc"

Declared by:

hyperhive.mcp.bashHttpPort

Loopback port hive-bash-daemon serves its MCP tools (run/status/kill) on. Same shape as hyperhive.mcp.httpPort for the built-in surface: HTTP is the sole transport (no stdio bridge — the daemon that owns the subprocess runner serves the MCP tools directly in-process), Restart = "always" keeps the listener self-healing, and loopback-only binding means no auth token is needed (same allowed_hosts reasoning as hyperhive.mcp.httpPort). Safe as a single fixed default across all agents (private per-container network namespace — see docs/network.md).

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

8791

Example:

8792

Declared by:

hyperhive.mcp.httpPort

Loopback port the built-in hyperhive MCP surface is served on. HTTP is the sole transport for the built-in surface: a long-lived hive-mcp-http systemd unit runs hive-agent-mcp --http 127.0.0.1:<port> and render_claude_config points claude at the stable http://127.0.0.1:<port>/mcp URL. That URL survives the per-turn claude re-spawn (and a host-side hive-c0re restart — each tool call dials the control socket fresh), so there is no per-turn MCP re-registration race (a resumed stdio child could emit its first tool call before that turn’s async initialize/tools-list completed, stranding the agent with No such tool — the http endpoint eliminates that). matrix stays a stdio bridge; bash runs its own persistent http listener (see hyperhive.mcp.bashHttpPort).

Bound loopback-only; the rmcp streamable-http transport’s default allowed_hosts (localhost / 127.0.0.1 / ::1) rejects Host headers from anywhere else, so no auth token is required for a container-local endpoint.

Failure-mode note: with no stdio fallback, if hive-mcp-http is down claude hits a dead URL until the unit restarts (guarded by Restart=always, RestartSec=3). Intended shape: no per-turn race while up, a bounded self-healing gap while restarting.

Safe as a single fixed default across all agents: each container runs in its own private network namespace (isolation is always-on — see docs/network.md), so 127.0.0.1:<port> is per-container-private and cannot collide across agents. Override only if a container-local service already occupies this port.

Must match mcp_config::DEFAULT_MCP_HTTP_PORT (the harness always exports HYPERHIVE_MCP_HTTP_PORT, so the const is only a fallback).

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

8790

Example:

8791

Declared by:

hyperhive.mcp.matrixHttpPort

Loopback port hive-matrix-daemon serves its MCP tools (send_message, list_rooms, read_room, …) on. Same shape as hyperhive.mcp.bashHttpPort: HTTP is the sole transport (no stdio bridge — the daemon that owns the matrix-sdk Client registry serves the MCP tools directly in-process), Restart = "always" keeps the listener self-healing, and loopback-only binding means no auth token is needed (same allowed_hosts reasoning as hyperhive.mcp.httpPort). Safe as a single fixed default across all agents (private per-container network namespace — see docs/network.md).

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

8792

Example:

8793

Declared by:

hyperhive.model

Claude model for this agent. Sets the HIVE_DEFAULT_MODEL environment variable; the harness applies it at boot and it takes priority over any persisted runtime override. The operator can still switch the model at runtime via the per-agent web UI — that choice is tracked in the state dir for the current session but is reset by any rebuild that changes this option.

Valid values are the short model names that claude --model accepts: "haiku", "sonnet", "opus" (or any future identifier). Context window sizes are looked up at runtime from the HIVE_CONTEXT_WINDOW_TOKENS_<KEY_UPPER> env vars injected by the meta flake; override sizes via services.hyperhive.c0re.contextWindowTokens on the host.

Type: string

Default:

"haiku"

Example:

"sonnet"

Declared by:

hyperhive.user.gid

Optional fixed GID for the per-agent unix group. null (default) lets NixOS auto-assign. Usually set alongside hyperhive.user.uid to the same value (the conventional Unix pattern for per-user groups where uid == gid), but can be set independently.

Type: null or signed integer

Default:

null

Example:

1100

Declared by:

hyperhive.user.name

Unix user the harness service runs as inside the container. The meta-flake overrides this to the agent’s own name so the user inside the container matches the agent label (HIVE_LABEL). Stand-alone evaluation defaults to "agent" so module evaluation without the meta-flake wrapper still builds.

Constraints match useradd’s NAME_REGEX: lowercase / _ start, total length ≤ 31, no special characters. UID is auto-assigned by NixOS unless hyperhive.user.uid is explicitly set.

Type: string matching the pattern ^[a-z_][a-z0-9_-]{0,30}$

Default:

"agent"

Example:

"iris"

Declared by:

hyperhive.user.passwordlessSudo

Grant agent passwordless sudo (NOPASSWD: ALL). True by default so claude’s Bash tool keeps working for tools that expect root inside the container (systemctl, package managers in dev shells, etc.) — the same surface the previous root-user shape had, just elevated explicitly instead of implicitly.

Flip to false for agents that should be strictly unprivileged. Anything claude shells out to that needs root will then fail loudly with the standard sudo error rather than silently succeeding — easier to spot the leak.

Type: boolean

Default:

true

Example:

false

Declared by:

hyperhive.user.uid

Optional fixed UID for the per-agent unix user. null (default) lets NixOS auto-assign from the normal-user range (≥ 1000), which is the right default for most deployments — the UID stays stable across container rebuilds because each container only has one normal user and the assignment is written into the container’s /etc/passwd at activation time.

Set an explicit value only when the host needs a predictable UID for the agent’s state files — e.g. if an operator script references files by numeric UID, or to keep ownership stable across full container destroy + recreate on a fresh host.

Values must be in [1000, 60000). Using UIDs < 1000 clashes with system accounts and is rejected by NixOS.

Type: null or signed integer

Default:

null

Example:

1100

Declared by: