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
- For agents (name has a state dir under
/var/lib/hyperhive/agents/): token is persisted to<state>/forge-token. Re-running refreshes the token (idempotent — scope always matches currentTOKEN_SCOPES). - For non-agents (humans): creates the account and prints the token to stdout; no state dir is created. Re-running after account already exists re-mints the token and prints it again — safe for password resets.
- Without
--password/--password-stdina random throwaway password is used (fine for agents — they auth by token). reconcile-config <agent>shows the divergence between the agent's local applied config checkout and its forgeagent-configs/<agent>main, then reconciles.--from forgeresets the local checkout to forgemain(takes effect on the next deploy — it does not auto-rebuild).--from localis not supported yet (forgemainis core-only branch-protected; resolve via a config PR). With no--fromit prompts for the direction after the diff.
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.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
create-user: for agents, persists theaccess_tokento<state>/matrix-token. Skips registration when the file already exists — delete it first to force re-registration.sync-admin: ensures the hive's internal admin matrix user exists (used byhive-c0refor admin-room commands). Token persisted to the admin token path. Safe to run again — idempotent.promote-user: promotes an already-registered user to homeserver admin via the matrix admin API. Requiressync-adminto have run first (needs a valid admin token).reset-password: calls the matrix admin API to set a new random password and prints it to stdout. Useful if an agent or human lost credentials.invite: invites a matrix user (full@user:serveror a bare localpart, qualified with the homeserver'sserver_name) to the hive Space by default, or to a--roomid /#alias. Uses the hive admin token; the admin account must be a member of the target room with invite power (it owns the hive Space, so that case always works). Idempotent — already-member / already-invited is a no-op.
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)
set-token: writes<state>/github-token(0600, agent-owned) via hive-priv — the same credential-injection path as forge/matrix tokens. Theghwrapper / git credential helper read it live, so a freshly-set or rotated PAT takes effect with no rebuild or restart. Refuses an empty token. See github.md for the full flow + security notes.
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/hyperhive/gateway/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.
hivectl agents list # roster: every agent's status + technical state
hivectl agents list --json # same data as raw JSON rows (for scripting)
hivectl agents restart iris # stop + start the `iris` container (no rebuild)
hivectl agents restart-all # stop + start every managed agent container in sequence
hivectl agents pause iris # park iris's turn loop, leave the container running
hivectl agents resume iris # let it drive turns again, draining what queued up
list 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.
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. Failures on restart-all are collected and
reported at the end rather than aborting mid-run.
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:
- Sticky. The marker lives on the persistent harness mount, so a paused agent stays paused across a container restart — and pausing a stopped agent makes it come up parked.
- Not a DAG. Unlike
restart/stop, there's no container operation to sequence, so it applies immediately with nothing to wait on. - Stopping a paused agent is still fast. The graceful-stop handshake is skipped for a paused agent (it would never answer), which is safe precisely because the pause check sits at the top of the loop: a paused agent has no turn in flight to checkpoint.
- Visible as
pausedinagents list's STATUS column, as apausedfield on the JSON rows, and as a badge on the dashboard card.
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).
hivectl choom iris # fresh blank Claude session in iris's container
hivectl choom iris --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:
- as the agent user, not root:
machinectl shelldefaults to root, which would make claude read/root/.claude(empty) instead of the agent's/home/<name>/.claudewhere its OAuth credentials live. choom prefixes the machine with<name>@(the meta-flake sets the agent's unix user name to its label). - from
/agents/<name>/state: the session andCLAUDE.md(the persona) resolve against the right project dir. - with the harness flags:
--settings,--mcp-config, and--system-prompt-filefrom/run/hive-config/— the same files the harness writes each turn — so the operator gets the agent's settings, the hyperhive/matrix MCP tools, and the role prompt. Each flag is included only when its file exists. - without the onboarding walkthrough: a boot-time oneshot
(
hive-claude-onboarding) seedshasCompletedOnboardingand the project trust flags into~/.claude.jsononce before the harness starts, so the first interactive choom lands straight in a session instead of the onboarding/trust dialog the headless harness never completes. It's the single place hyperhive touches that file.
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.matrix.gui.enable = true. In those cases the command
exits with a hint naming the option to set.