hivectl

hivectl is the operator-facing host CLI for hyperhive. It lives on the host (not inside any container). It talks to hive-c0re over the host admin socket /run/hyperhive/host.sock, which is root-only by default — so it needs sudo unless you grant sudoless access by listing your login user in services.hyperhive.c0re.adminUsers (adds you to the hive-admin group that owns the socket; see docs/boundary.md). Available via the hive-c0re package in the host NixOS config.

Unlike the hive-c0re daemon subcommands (which go through the broker), hivectl covers direct host-side administration: manual provisioning of forge + matrix accounts, gateway htpasswd management, container lifecycle shortcuts, and interactive agent shell access.

This page is the curated guide. For the exhaustive flag-by-flag reference auto-generated from the binary's own command tree, see hivectl-cli.md — emitted by the hidden hivectl markdown-docs subcommand and kept in lockstep with the code by the hivectl-docs flake check (CI fails if the committed copy drifts). Regenerate with nix build .#default && ./result/bin/hivectl markdown-docs > docs/tools/hivectl-cli.md.

Forge

Manual entry to the same idempotent provisioning flow hive-c0re runs at boot. Useful for recovery, ad-hoc re-provisioning, or fixing a single agent without bouncing the daemon.

hivectl forge create-user iris          # provision (or refresh) forge account for agent `iris`
hivectl forge create-user mara          # create forge account for a human user; prints token to stdout
hivectl forge create-user mara --password hunter2  # set a web-login password
hivectl forge create-user mara --password-stdin    # read password from stdin (safer for scripting)

hivectl forge reconcile-config iris             # show local-applied <-> forge config divergence, then prompt
hivectl forge reconcile-config iris --from forge   # reset local applied checkout to forge main (effective next deploy)
hivectl forge reconcile-config iris --verbose      # include the full diff, not just --stat

Matrix

Manual entry to the same idempotent matrix provisioning flow hive-c0re runs at boot. Requires the hive-matrix container to be running (services.hyperhive.swarm.matrix.enable = true).

hivectl matrix create-user iris         # provision (or re-provision) matrix account for agent `iris`
hivectl matrix create-user mara         # create matrix account for a human; prints access_token to stdout
hivectl matrix create-user mara --password hunter2  # set a client-login password
hivectl matrix sync-admin               # provision / refresh the hive internal admin account
hivectl matrix promote-user mara        # promote an existing matrix user to homeserver admin
hivectl matrix reset-password iris      # generate and set a new random password for `iris`; prints it
hivectl matrix invite mara              # invite a user to the hive Space
hivectl matrix invite @mara:server --room '#hive-chat:server'  # ...or to a specific room/alias

GitHub

Write an operator-supplied GitHub personal access token (PAT) into an agent's token file so its gh wrapper + git credential helper can act as the bot account. Unlike forge/matrix there is no account creation — the PAT is for an existing GitHub account. A CLI alternative to the dashboard credentials tab; the GitHub integration is on by default (hyperhive.github.enable), so no per-agent config is needed.

hivectl github set-token damocles --token-stdin   # paste the PAT on stdin (preferred)
hivectl github set-token damocles --token <pat>    # inline (visible in shell history)

Gateway

Manage users in the gateway's HTTP Basic auth htpasswd file (services.hyperhive.gateway.auth). hivectl sends the request over the host admin socket; the hive-c0re daemon owns the htpasswd file at its canonical path (/var/lib/hive-gateway/conf/gateway.htpasswd) and performs the write.

hivectl gateway create-user alice --password-stdin  # add (or update) user; read password from stdin
hivectl gateway create-user bob --password hunter2  # add user inline (visible in shell history)
hivectl gateway delete-user bob                     # remove user
hivectl gateway list-users                          # list all usernames, one per line

Passwords are hashed with BCrypt (cost 12) by the daemon. The file is created if it does not exist. Re-running create-user with the same username updates the password hash in place.

Agents

Container lifecycle shortcuts that go through the host admin socket. Requires the hive-c0re daemon to be running. Everything scoped to a single agent lives under hivectl agent <name> <verb> — the name is hoisted onto the parent command, so none of the verbs below repeat it.

hivectl list-agents                # roster: every agent's status + technical state
hivectl list-agents --json         # same data as raw JSON rows (for scripting)
hivectl agent iris restart         # stop + start the `iris` container (no rebuild)
hivectl agent iris pause           # park iris's turn loop, leave the container running
hivectl agent iris resume          # let it drive turns again, draining what queued up

list-agents prints a padded table with one row per managed agent — NAME STATUS REV PARENT REMIND. STATUS collapses the health flags (running / stopped, plus paused / needs-login / needs-update when set — paused is orthogonal to running, see below); REV is the first 12 chars of the agent's locked config sha; PARENT is its place in the topology tree (- for a root agent); REMIND is the count of pending reminders. It reuses the same per-agent aggregation the dashboard renders, so the CLI roster and the web UI never drift. --json emits the raw rows instead of the table.

agent <name> restart is the manual equivalent of the MCP restart tool — useful when you need to kick a container from the host without going through the agent hierarchy. For more than one agent at once, use the top-level hivectl restart --agents (or --agent <name> repeated) — it rides a single DAG and reports per-target failures at the end rather than aborting mid-run, instead of shelling out to agent <name> restart in a loop.

pause / resume are the "stop burning tokens without losing the container" pair. Pausing writes a marker file into the agent's harness dir (<state>/<name>/harness/paused) which the harness re-stats every 5 s at the top of its serve loop; while it's there the agent drives no turns, but the container, its mounts, its warm caches, its web UI and its MCP daemons all stay up. Inbox messages queue unacked, so a resume drains the backlog rather than dropping it. Points worth knowing:

Per-agent resource limits

hivectl agent sock set-limits --cpu-quota 400% --memory-max 8G
hivectl agent sock set-limits --memory-max 8G    # CPU falls back to the hive default
hivectl agent sock set-limits --reset            # drop all overrides

Overrides the hive-wide services.hyperhive.agentCpuQuota / agentMemoryMax for one agent, persisted to meta/resource-limits.json (see persistence.md). Values are systemd's CPUQuota= / MemoryMax= syntax: a percentage (400% = four full cores) for CPU; a size (8G), a percentage of physical RAM, or infinity for memory. Both are validated before they're persisted — they go into a systemd drop-in verbatim, and a typo there makes the unit fail to start.

Declarative, not incremental: each invocation replaces the agent's whole entry. set-limits sock --memory-max 8G leaves sock with only a memory override, reverting any previously-set CPU quota to the hive default. To avoid a forgotten flag silently wiping an override, a bare set-limits <name> with no flags is rejected — clearing requires the explicit --reset.

The command rewrites the container's drop-in and reloads systemd, so new containers and restarts pick the values up immediately.

Choom

Drop into an interactive Claude session inside an agent container. Replaces the current process with machinectl shell <name>@h-<name> running claude from the agent's state dir. Requires root (same as all machinectl shell operations) — hyperhive ships no polkit rule granting those actions to the operator group, so choom refuses up front with a message naming that requirement rather than letting systemd reject the exec later.

It also needs the daemon socket, unlike the other exec-into-a-container paths: the "is this actually an agent?" pre-flight reads the agents root, which is owned by the daemon's user and not group-readable, so the check is a HostRequest rather than a local stat. A rootless choom therefore tells you it needs root, instead of reporting a permission problem with the state dir.

hivectl agent iris choom                          # fresh blank Claude session in iris's container
hivectl agent iris choom --resume <session-id>    # rejoin a prior session by id

Bare choom starts a fresh blank session. --resume <value> passes through as claude --resume <value> to rejoin a prior session by its session id — the flag name deliberately matches the claude flag it maps to. (choom never uses claude's --continue: that's a bare flag that takes no argument and resumes the cwd's latest session, i.e. the harness's; a value after it would be consumed as the first prompt, silently poking the live harness session.) A value is required when the flag is given. Either way choom never collides with the harness's live session in the same project dir: the harness pins its own id via --resume, so a blank choom session is invisible to it. The container must be running.

choom reproduces the harness's own claude invocation so the operator lands in a faithful copy of the agent's environment:

Watch

Follow an agent's live turn/tool-call event stream from the CLI:

hivectl agent iris watch    # tail iris's live events; Ctrl-C to stop

Dials the same unix socket the gateway's nginx proxy_passes through (/run/hive-agent/<name>/web.sock — see Per-agent unix-socket upstream) directly and speaks a bare HTTP/1.1 request for the agent's existing /events/stream SSE endpoint over it. No gateway hop, no daemon round-trip for the stream itself — the daemon socket is only used for the "does this agent exist" pre-flight, same reasoning as choom above. Requires the agent to be running with its web UI socket bound; a fresh spawn/rebuild that hasn't come up yet gets a clear connection-refused hint rather than a raw OS error.

Prints one compact line per event — reuses the _icon/_summary fields the harness already stamps onto stream-json events for the web UI (stream_enrich.rs), so tool calls and turn markers read as short glyph-prefixed lines instead of raw JSON. Not an attempt at the web UI's full collapsible-details rendering (docs/terminal-rendering.md) — that's presentation for a browser, this is a tail -f.

Open

Print (and best-effort open in a browser) one of the hive's web surfaces. Requires the hive-c0re daemon to be running.

hivectl open            # operator dashboard (same as `open home`)
hivectl open home       # operator dashboard (https://<domain>/)
hivectl open forge      # the forge (Forgejo) web UI
hivectl open matrix     # the matrix GUI (fluffychat)

The URL is resolved from the running daemon (HostRequest::Urls), which reads the per-surface public URLs from c0re's service env — so custom forge / matrix domains resolve correctly instead of assuming forge.<domain>. The URL is always printed (the reliable core, since the host is usually headless / driven over SSH), then xdg-open is tried as a convenience — a missing or failing opener is reported as a note, not an error.

A surface has no URL when it isn't browser-reachable: home needs services.hyperhive.domain; forge needs services.hyperhive.forge.behindGateway = true; matrix needs services.hyperhive.swarm.matrix.gui.enable = true. In those cases the command exits with a hint naming the option to set.