keep hivectl verb help concise: short about + terse long help (#2512)

This commit is contained in:
damocles 2026-07-15 23:27:25 +02:00 committed by mara
commit 30e48d202b
2 changed files with 219 additions and 306 deletions

View file

@ -63,18 +63,18 @@ Sibling to the `hive-c0re` daemon binary. Covers host-side admin operations that
###### **Subcommands:** ###### **Subcommands:**
* `forge` — Forgejo user provisioning. Manual entry point to the same idempotent flow c0re runs automatically at boot (`forge::ensure_all`) — useful for recovery, ad-hoc reprovisioning, or single-agent fixes without bouncing the daemon * `forge` — Forgejo user provisioning
* `matrix` — matrix-tuwunel user provisioning. Manual entry point to the same idempotent flow c0re runs automatically at boot (`matrix::ensure_all`) — useful when the boot-time sweep skipped an agent (e.g. matrix container wasn't up yet) or to re-register after wiping a token file * `matrix` — matrix-tuwunel user provisioning
* `github` — GitHub account provisioning: write an operator-supplied personal access token (PAT) into an agent's `github-token` state file so its `gh` wrapper + git credential helper can authenticate. Unlike forge/matrix there is no account creation — the operator supplies a PAT for an existing GitHub account. A CLI alternative to the dashboard credentials tab; the integration is on by default (`hyperhive.github.enable`), so no per-agent config is needed * `github` — GitHub account provisioning
* `gateway` — Gateway htpasswd user management. Add, remove, or list users in an htpasswd file used by the gateway's HTTP Basic auth (`services.hyperhive.gateway.auth`). Credentials are stored as `BCrypt` hashes — no extra service or PAM required * `gateway` — Gateway htpasswd user management
* `agents` — Agent container management. Requires the hive-c0re daemon to be running (connects to the host admin socket) * `agents` — Agent container management
* `approvals` — Operator approval queue: list pending requests, approve / deny them. Requires the hive-c0re daemon to be running (connects to the host admin socket) * `approvals` — Operator approval queue: list, approve, or deny pending requests
* `wg` — WireGuard inter-hive mesh setup helpers (`services.hyperhive.swarm`) * `wg` — WireGuard inter-hive mesh setup helpers
* `peer-config` — Generate the federation peer-config block for THIS hive — the nix a peer operator pastes into their `services.hyperhive.swarm.peers` to trust + reach this hive. Emits `caCert` (+ a `cp` line for the cert) when this hive serves a self-signed CA, the WireGuard public key when the mesh key exists, and the `wireguard{Address,Endpoint}` you pass. The hive's own domain is filled in automatically from the running daemon (`services.hyperhive.domain`). Reads local state (the TLS CA cert, the wg key); never mutates. `wg init` calls this at the end, so a fresh mesh setup prints the hand-over block too * `peer-config` — Generate the federation peer-config block for THIS hive
* `choom` — Open an interactive Claude session inside an agent container * `choom` — Open an interactive Claude session inside an agent container
* `stop` — Stop containers hive-wide in one operator action. Bare `hivectl stop` stops **everything** — all sub-agents plus the ci, forge, gateway, and matrix infra containers. Narrow it with scope flags: `--agents` (all sub-agents), `--ci` / `--forge` / `--gateway` / `--matrix` (named infra), and `--agent <name>` (repeatable) for specific sub-agents. Flags are additive (e.g. `--agents --matrix`). Requires the hive-c0re daemon (connects to the host admin socket). hive-c0re itself is never stopped — it services the request * `stop` — Stop containers hive-wide in one operator action
* `start` — Start containers hive-wide — the inverse of `hivectl stop`. Bare `hivectl start` restores the previously-running agents from the last broad-scope `stop`, or starts everything if no prior stop exists; the same scope flags as `stop` narrow it (`--agents`, `--ci`, `--forge`, `--gateway`, `--matrix`, `--agent <name>`). A targeted `--agent <name>` start is never filtered. Requires the hive-c0re daemon * `start` — Start containers hive-wide — the inverse of `hivectl stop`
* `restart` — Restart containers hive-wide — `stop` then `start` over the same scope. Bare `hivectl restart` restarts **everything** (all sub-agents plus the ci/forge/gateway/matrix infra containers); the same scope flags as `stop`/`start` narrow it (`--agents`, `--ci`, `--forge`, `--gateway`, `--matrix`, `--agent <name>`). If the stop phase reports a failure the start phase is skipped so the operator can investigate. Requires the hive-c0re daemon * `restart` — Restart containers hive-wide — `stop` then `start` over one scope
* `quota` — Per-agent disk accounting + optional quotas via btrfs qgroups * `quota` — Per-agent disk accounting + optional quotas via btrfs qgroups
* `subvol` — btrfs subvolume management for agent state dirs * `subvol` — btrfs subvolume management for agent state dirs
* `open` — Print (and best-effort open in a browser) a hive web surface URL * `open` — Print (and best-effort open in a browser) a hive web surface URL
@ -90,7 +90,9 @@ Sibling to the `hive-c0re` daemon binary. Covers host-side admin operations that
## `hivectl forge` ## `hivectl forge`
Forgejo user provisioning. Manual entry point to the same idempotent flow c0re runs automatically at boot (`forge::ensure_all`) — useful for recovery, ad-hoc reprovisioning, or single-agent fixes without bouncing the daemon Forgejo user provisioning.
Manual entry point to the same idempotent provisioning c0re runs at boot — for recovery, ad-hoc reprovisioning, or fixing one agent without bouncing the daemon.
**Usage:** `hivectl forge <COMMAND>` **Usage:** `hivectl forge <COMMAND>`
@ -104,11 +106,7 @@ Forgejo user provisioning. Manual entry point to the same idempotent flow c0re r
Create or refresh the Forgejo account + token for `<name>`. Create or refresh the Forgejo account + token for `<name>`.
When `<name>` matches an existing agent (i.e. it has a state dir under `/var/lib/hyperhive/agents/`), persists the token to `<state>/forge-token` (idempotent: re-mints + rewrites every call so the on-disk scope matches the current `forge::TOKEN_SCOPES`). For an existing agent, persists the token to its state dir; for a human/other account, prints the token to stdout. Set a password to enable forge web-UI login (a random throwaway is used otherwise).
When `<name>` is **not** an agent (a human or any other non-container account), creates the forgejo user and prints the freshly-minted token to stdout — no `/var/lib/hyperhive/agents/` directory is created for the user.
Without `--password` / `--password-stdin` a random throwaway is used (fine for agents — they auth by token via tea / hive-forge). Set a password to log into the forge web UI afterwards. `--password` is idempotent: re-running with the same value sets the same password (covers password resets on already-created accounts since `forgejo admin user create` silently no-ops once the user exists).
**Usage:** `hivectl forge create-user [OPTIONS] <NAME>` **Usage:** `hivectl forge create-user [OPTIONS] <NAME>`
@ -125,17 +123,19 @@ Without `--password` / `--password-stdin` a random throwaway is used (fine for a
## `hivectl matrix` ## `hivectl matrix`
matrix-tuwunel user provisioning. Manual entry point to the same idempotent flow c0re runs automatically at boot (`matrix::ensure_all`) — useful when the boot-time sweep skipped an agent (e.g. matrix container wasn't up yet) or to re-register after wiping a token file matrix-tuwunel user provisioning.
Manual entry point to the same idempotent provisioning c0re runs at boot — for re-registering an agent the boot sweep skipped, or after wiping a token file.
**Usage:** `hivectl matrix <COMMAND>` **Usage:** `hivectl matrix <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `create-user` — Create or refresh the matrix account + access token for `<name>` * `create-user` — Create or refresh the matrix account + access token for `<name>`
* `sync-admin` — Provision (or re-provision) the hive system admin matrix account (`@hive:<server>`). hive-c0re runs this automatically on startup before the agent sweep so the account is the first registered user — Conduit/tuwunel grants admin rights to the first user. Run manually to recover a missing admin token file * `sync-admin` — Provision (or re-provision) the hive system admin matrix account
* `promote-user` — Promote a matrix user to homeserver admin via the admin API. Uses the hive system admin token at `/var/lib/hyperhive/matrix/admin-token`. The `server_name` is discovered automatically from the running homeserver * `promote-user` — Promote a matrix user to homeserver admin
* `reset-password` — Reset a matrix user's password via the admin API and persist the new password to `/var/lib/hyperhive/matrix/creds/<name>-password` so the next `ensure_user_for` (or `create-user`) can re-login * `reset-password` — Reset a matrix user's password via the admin API
* `invite` — Invite a matrix user to the hive Space (default) or a specific room. Uses the hive admin token; the admin account must be a member of the target room with invite power (it owns the hive Space). Idempotent — already-member / already-invited is a no-op * `invite` — Invite a matrix user to the hive Space, or a specific room with `--room`. Idempotent
@ -143,11 +143,7 @@ matrix-tuwunel user provisioning. Manual entry point to the same idempotent flow
Create or refresh the matrix account + access token for `<name>`. Create or refresh the matrix account + access token for `<name>`.
When `<name>` matches an existing agent (i.e. it has a state dir under `/var/lib/hyperhive/agents/`), persists the token to `<state>/matrix-token`. Skips registration when the file is already populated; delete it to force re-registration. For an existing agent, persists the token to its state dir; for a human/other account, prints the access token to stdout. Set a password to enable matrix web-client login (a random throwaway is used otherwise).
When `<name>` is **not** an agent (a human or any other non-container account), registers the matrix user and prints the freshly-minted access token to stdout — no `/var/lib/hyperhive/agents/` directory is created for the user.
Without `--password` / `--password-stdin` a random throwaway is used (fine for agents — they auth by `access_token`, never by password). Set a password to log into a matrix web client afterwards.
**Usage:** `hivectl matrix create-user [OPTIONS] <NAME>` **Usage:** `hivectl matrix create-user [OPTIONS] <NAME>`
@ -164,7 +160,9 @@ Without `--password` / `--password-stdin` a random throwaway is used (fine for a
## `hivectl matrix sync-admin` ## `hivectl matrix sync-admin`
Provision (or re-provision) the hive system admin matrix account (`@hive:<server>`). hive-c0re runs this automatically on startup before the agent sweep so the account is the first registered user — Conduit/tuwunel grants admin rights to the first user. Run manually to recover a missing admin token file Provision (or re-provision) the hive system admin matrix account.
Runs automatically on startup; run manually to recover a missing admin token.
**Usage:** `hivectl matrix sync-admin` **Usage:** `hivectl matrix sync-admin`
@ -172,7 +170,7 @@ Provision (or re-provision) the hive system admin matrix account (`@hive:<server
## `hivectl matrix promote-user` ## `hivectl matrix promote-user`
Promote a matrix user to homeserver admin via the admin API. Uses the hive system admin token at `/var/lib/hyperhive/matrix/admin-token`. The `server_name` is discovered automatically from the running homeserver Promote a matrix user to homeserver admin
**Usage:** `hivectl matrix promote-user <NAME>` **Usage:** `hivectl matrix promote-user <NAME>`
@ -184,9 +182,9 @@ Promote a matrix user to homeserver admin via the admin API. Uses the hive syste
## `hivectl matrix reset-password` ## `hivectl matrix reset-password`
Reset a matrix user's password via the admin API and persist the new password to `/var/lib/hyperhive/matrix/creds/<name>-password` so the next `ensure_user_for` (or `create-user`) can re-login. Reset a matrix user's password via the admin API.
After this command succeeds, run `hivectl matrix create-user <name>` to mint a fresh access token for the agent. Persists the new password so a later `create-user` can re-login.
**Usage:** `hivectl matrix reset-password <NAME>` **Usage:** `hivectl matrix reset-password <NAME>`
@ -198,7 +196,7 @@ After this command succeeds, run `hivectl matrix create-user <name>` to mint a f
## `hivectl matrix invite` ## `hivectl matrix invite`
Invite a matrix user to the hive Space (default) or a specific room. Uses the hive admin token; the admin account must be a member of the target room with invite power (it owns the hive Space). Idempotent — already-member / already-invited is a no-op Invite a matrix user to the hive Space, or a specific room with `--room`. Idempotent
**Usage:** `hivectl matrix invite [OPTIONS] <USER>` **Usage:** `hivectl matrix invite [OPTIONS] <USER>`
@ -214,19 +212,23 @@ Invite a matrix user to the hive Space (default) or a specific room. Uses the hi
## `hivectl github` ## `hivectl github`
GitHub account provisioning: write an operator-supplied personal access token (PAT) into an agent's `github-token` state file so its `gh` wrapper + git credential helper can authenticate. Unlike forge/matrix there is no account creation — the operator supplies a PAT for an existing GitHub account. A CLI alternative to the dashboard credentials tab; the integration is on by default (`hyperhive.github.enable`), so no per-agent config is needed GitHub account provisioning.
Store an operator-supplied personal access token (PAT) for an agent so its `gh` and git can authenticate. No account is created — the PAT is for an existing GitHub account.
**Usage:** `hivectl github <COMMAND>` **Usage:** `hivectl github <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `set-token`Write a GitHub PAT into `<agent>`'s state dir (`github-token`, 0600, agent-owned) via hive-priv. The GitHub integration is on by default (`hyperhive.github.enable`), so the `gh` wrapper + git credential helper pick the token up with no per-agent config. The token is read live at invocation, so no rebuild/restart is needed. Prefer `--token-stdin`: an inline `--token` is visible in shell history + process listings * `set-token`Store a GitHub PAT for `<agent>` so its `gh` and git can authenticate
## `hivectl github set-token` ## `hivectl github set-token`
Write a GitHub PAT into `<agent>`'s state dir (`github-token`, 0600, agent-owned) via hive-priv. The GitHub integration is on by default (`hyperhive.github.enable`), so the `gh` wrapper + git credential helper pick the token up with no per-agent config. The token is read live at invocation, so no rebuild/restart is needed. Prefer `--token-stdin`: an inline `--token` is visible in shell history + process listings Store a GitHub PAT for `<agent>` so its `gh` and git can authenticate.
Prefer `--token-stdin` — an inline `--token` is visible in shell history.
**Usage:** `hivectl github set-token [OPTIONS] <AGENT>` **Usage:** `hivectl github set-token [OPTIONS] <AGENT>`
@ -243,23 +245,25 @@ Write a GitHub PAT into `<agent>`'s state dir (`github-token`, 0600, agent-owned
## `hivectl gateway` ## `hivectl gateway`
Gateway htpasswd user management. Add, remove, or list users in an htpasswd file used by the gateway's HTTP Basic auth (`services.hyperhive.gateway.auth`). Credentials are stored as `BCrypt` hashes — no extra service or PAM required Gateway htpasswd user management.
Add, remove, or list users for the gateway's HTTP Basic auth.
**Usage:** `hivectl gateway <COMMAND>` **Usage:** `hivectl gateway <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `create-user` — Add a new user or update the password of an existing user in the gateway htpasswd file. The daemon bcrypt-hashes the password (cost 12) and writes the credential store — hivectl relays over the host socket and never touches the file * `create-user` — Add a user or update an existing user's password in the gateway htpasswd
* `delete-user` — Remove a user from the gateway htpasswd file. Exits with an error when the user is not found so callers can detect the no-op case * `delete-user` — Remove a user from the gateway htpasswd
* `list-users` — List all gateway htpasswd usernames, one per line * `list-users` — List all gateway htpasswd usernames, one per line
## `hivectl gateway create-user` ## `hivectl gateway create-user`
Add a new user or update the password of an existing user in the gateway htpasswd file. The daemon bcrypt-hashes the password (cost 12) and writes the credential store — hivectl relays over the host socket and never touches the file. Add a user or update an existing user's password in the gateway htpasswd.
Pass `--password-stdin` when scripting or when you don't want the password visible in shell history. Use `--password-stdin` to keep the password out of shell history.
**Usage:** `hivectl gateway create-user [OPTIONS] <USERNAME>` **Usage:** `hivectl gateway create-user [OPTIONS] <USERNAME>`
@ -276,7 +280,7 @@ Pass `--password-stdin` when scripting or when you don't want the password visib
## `hivectl gateway delete-user` ## `hivectl gateway delete-user`
Remove a user from the gateway htpasswd file. Exits with an error when the user is not found so callers can detect the no-op case Remove a user from the gateway htpasswd
**Usage:** `hivectl gateway delete-user <USERNAME>` **Usage:** `hivectl gateway delete-user <USERNAME>`
@ -296,27 +300,29 @@ List all gateway htpasswd usernames, one per line
## `hivectl agents` ## `hivectl agents`
Agent container management. Requires the hive-c0re daemon to be running (connects to the host admin socket) Agent container management.
Lifecycle actions on managed agent containers. Needs the hive-c0re daemon running.
**Usage:** `hivectl agents <COMMAND>` **Usage:** `hivectl agents <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `list` — Show all managed agents with their status (running / needs-login / needs-update) and technical state (deployed sha, parent, pending reminders). The host roster overview; reuses the dashboard's per-agent aggregation. Requires the daemon running * `list` — Show all managed agents with their status and technical state
* `restart` — Stop and start a single agent container without rebuilding config. Useful for "kick the container" when the process is stuck or the container needs a clean restart without changing the NixOS config. Rides the job queue (serialized against in-flight rebuilds for the same agent); waits with live progress unless `--no-wait` * `restart` — Stop and start a single agent container without rebuilding config
* `restart-all` — Restart ALL managed agent containers via one restart DAG each — unrelated agents overlap, each serializes on its own lease. Waits for the whole set with live progress unless `--no-wait` * `restart-all` — Restart all managed agent containers
* `spawn` — Spawn a new agent container directly (`h-<name>`). Bypasses the approval queue — operator-on-the-host only. For approval-gated spawns, use `request-spawn` * `spawn` — Spawn a new agent container directly, bypassing the approval queue
* `request-spawn` — Queue a spawn request as an approval. The container is created on `hivectl approvals approve <id>` (or the dashboard APPR0VE button) * `request-spawn` — Queue a spawn request for operator approval
* `kill` — Stop a managed container (graceful) * `kill` — Stop a managed container (graceful)
* `destroy` — Tear down a sub-agent container. The container is removed; persistent state (config repos + Claude credentials) is kept by default. Pass `--purge` to also wipe the agent's state dirs (config + creds + notes). No undo * `destroy` — Tear down a sub-agent container, keeping its state by default. No undo
* `rebuild` — Apply pending config to a managed container * `rebuild` — Apply pending config to a managed container
* `set-parent` — Move an agent in the topology tree. Set `--parent` to a new parent agent name, or pass `--root` to promote the agent to root (no parent). Exactly one is required. Refuses cycles and unknown agents * `set-parent` — Move an agent in the topology tree — under a new parent, or to root
## `hivectl agents list` ## `hivectl agents list`
Show all managed agents with their status (running / needs-login / needs-update) and technical state (deployed sha, parent, pending reminders). The host roster overview; reuses the dashboard's per-agent aggregation. Requires the daemon running Show all managed agents with their status and technical state
**Usage:** `hivectl agents list [OPTIONS]` **Usage:** `hivectl agents list [OPTIONS]`
@ -328,7 +334,7 @@ Show all managed agents with their status (running / needs-login / needs-update)
## `hivectl agents restart` ## `hivectl agents restart`
Stop and start a single agent container without rebuilding config. Useful for "kick the container" when the process is stuck or the container needs a clean restart without changing the NixOS config. Rides the job queue (serialized against in-flight rebuilds for the same agent); waits with live progress unless `--no-wait` Stop and start a single agent container without rebuilding config
**Usage:** `hivectl agents restart [OPTIONS] <NAME>` **Usage:** `hivectl agents restart [OPTIONS] <NAME>`
@ -344,7 +350,7 @@ Stop and start a single agent container without rebuilding config. Useful for "k
## `hivectl agents restart-all` ## `hivectl agents restart-all`
Restart ALL managed agent containers via one restart DAG each — unrelated agents overlap, each serializes on its own lease. Waits for the whole set with live progress unless `--no-wait` Restart all managed agent containers
**Usage:** `hivectl agents restart-all [OPTIONS]` **Usage:** `hivectl agents restart-all [OPTIONS]`
@ -356,7 +362,9 @@ Restart ALL managed agent containers via one restart DAG each — unrelated agen
## `hivectl agents spawn` ## `hivectl agents spawn`
Spawn a new agent container directly (`h-<name>`). Bypasses the approval queue — operator-on-the-host only. For approval-gated spawns, use `request-spawn` Spawn a new agent container directly, bypassing the approval queue.
Operator-on-the-host only; use `request-spawn` for an approval-gated spawn.
**Usage:** `hivectl agents spawn <NAME>` **Usage:** `hivectl agents spawn <NAME>`
@ -368,7 +376,7 @@ Spawn a new agent container directly (`h-<name>`). Bypasses the approval queue
## `hivectl agents request-spawn` ## `hivectl agents request-spawn`
Queue a spawn request as an approval. The container is created on `hivectl approvals approve <id>` (or the dashboard APPR0VE button) Queue a spawn request for operator approval
**Usage:** `hivectl agents request-spawn <NAME>` **Usage:** `hivectl agents request-spawn <NAME>`
@ -392,7 +400,7 @@ Stop a managed container (graceful)
## `hivectl agents destroy` ## `hivectl agents destroy`
Tear down a sub-agent container. The container is removed; persistent state (config repos + Claude credentials) is kept by default. Pass `--purge` to also wipe the agent's state dirs (config + creds + notes). No undo Tear down a sub-agent container, keeping its state by default. No undo
**Usage:** `hivectl agents destroy [OPTIONS] <NAME>` **Usage:** `hivectl agents destroy [OPTIONS] <NAME>`
@ -402,7 +410,7 @@ Tear down a sub-agent container. The container is removed; persistent state (con
###### **Options:** ###### **Options:**
* `--purge` * `--purge` — Also wipe the agent's state dirs (config + creds + notes)
@ -420,7 +428,7 @@ Apply pending config to a managed container
## `hivectl agents set-parent` ## `hivectl agents set-parent`
Move an agent in the topology tree. Set `--parent` to a new parent agent name, or pass `--root` to promote the agent to root (no parent). Exactly one is required. Refuses cycles and unknown agents Move an agent in the topology tree — under a new parent, or to root
**Usage:** `hivectl agents set-parent [OPTIONS] <CHILD>` **Usage:** `hivectl agents set-parent [OPTIONS] <CHILD>`
@ -437,7 +445,9 @@ Move an agent in the topology tree. Set `--parent` to a new parent agent name, o
## `hivectl approvals` ## `hivectl approvals`
Operator approval queue: list pending requests, approve / deny them. Requires the hive-c0re daemon to be running (connects to the host admin socket) Operator approval queue: list, approve, or deny pending requests.
Needs the hive-c0re daemon running.
**Usage:** `hivectl approvals <COMMAND>` **Usage:** `hivectl approvals <COMMAND>`
@ -483,23 +493,23 @@ Deny a pending request by id
## `hivectl wg` ## `hivectl wg`
WireGuard inter-hive mesh setup helpers (`services.hyperhive.swarm`). WireGuard inter-hive mesh setup helpers.
One-time-setup convenience so nobody has to remember the `wg` dance: `wg init` generates + stores this hive's private key and prints the public key plus the nix snippet to enable the mesh; `wg peer` prints the snippet to add a remote hive; `wg status` wraps `wg show`. The verbs own the imperative state (the key file); the printed nix goes into the operator's host config (kept in git), so nothing here mutates declarative config behind the operator's back. Generate this hive's mesh key and print the nix to enable the mesh, add a peer, or inspect live interface state.
**Usage:** `hivectl wg <COMMAND>` **Usage:** `hivectl wg <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `init` — Generate (if absent) this hive's WireGuard private key, print its public key, and print the nix snippet to enable the mesh. Idempotent: an existing key is reused, never clobbered (clobbering would break a live mesh). Share the printed public key with peer hives * `init` — Generate this hive's WireGuard key (if absent) and print its public key plus the nix to enable the mesh
* `peer` — Print the nix snippet to add a peer hive to the mesh. Pure output — paste it into this hive's config. Get `<pubkey>` from the peer's `hivectl wg init` * `peer` — Print the nix to add a peer hive to the mesh
* `status` — Show the live mesh interface state (`wg show wg-hive`). Requires the mesh to be enabled + up * `status` — Show the live mesh interface state
## `hivectl wg init` ## `hivectl wg init`
Generate (if absent) this hive's WireGuard private key, print its public key, and print the nix snippet to enable the mesh. Idempotent: an existing key is reused, never clobbered (clobbering would break a live mesh). Share the printed public key with peer hives Generate this hive's WireGuard key (if absent) and print its public key plus the nix to enable the mesh
**Usage:** `hivectl wg init [OPTIONS]` **Usage:** `hivectl wg init [OPTIONS]`
@ -511,7 +521,7 @@ Generate (if absent) this hive's WireGuard private key, print its public key, an
## `hivectl wg peer` ## `hivectl wg peer`
Print the nix snippet to add a peer hive to the mesh. Pure output — paste it into this hive's config. Get `<pubkey>` from the peer's `hivectl wg init` Print the nix to add a peer hive to the mesh
**Usage:** `hivectl wg peer [OPTIONS] --pubkey <PUBKEY> --address <ADDRESS> <DOMAIN>` **Usage:** `hivectl wg peer [OPTIONS] --pubkey <PUBKEY> --address <ADDRESS> <DOMAIN>`
@ -529,7 +539,7 @@ Print the nix snippet to add a peer hive to the mesh. Pure output — paste it i
## `hivectl wg status` ## `hivectl wg status`
Show the live mesh interface state (`wg show wg-hive`). Requires the mesh to be enabled + up Show the live mesh interface state
**Usage:** `hivectl wg status` **Usage:** `hivectl wg status`
@ -537,7 +547,9 @@ Show the live mesh interface state (`wg show wg-hive`). Requires the mesh to be
## `hivectl peer-config` ## `hivectl peer-config`
Generate the federation peer-config block for THIS hive — the nix a peer operator pastes into their `services.hyperhive.swarm.peers` to trust + reach this hive. Emits `caCert` (+ a `cp` line for the cert) when this hive serves a self-signed CA, the WireGuard public key when the mesh key exists, and the `wireguard{Address,Endpoint}` you pass. The hive's own domain is filled in automatically from the running daemon (`services.hyperhive.domain`). Reads local state (the TLS CA cert, the wg key); never mutates. `wg init` calls this at the end, so a fresh mesh setup prints the hand-over block too Generate the federation peer-config block for THIS hive.
Prints the nix a peer operator pastes into their swarm config to trust and reach this hive.
**Usage:** `hivectl peer-config [OPTIONS]` **Usage:** `hivectl peer-config [OPTIONS]`
@ -552,7 +564,7 @@ Generate the federation peer-config block for THIS hive — the nix a peer opera
Open an interactive Claude session inside an agent container. Open an interactive Claude session inside an agent container.
Runs claude as the agent user from its state dir with the harness's settings / MCP / system prompt. Bare `choom <name>` is a fresh session; `--resume <session-id>` rejoins a prior one. Never collides with the harness's live session. Requires root + a running container. See `docs/tools/hivectl.md` (Choom) for details. A fresh session by default, or resume a prior one. Requires root and a running container.
**Usage:** `hivectl choom [OPTIONS] <NAME>` **Usage:** `hivectl choom [OPTIONS] <NAME>`
@ -568,7 +580,9 @@ Runs claude as the agent user from its state dir with the harness's settings / M
## `hivectl stop` ## `hivectl stop`
Stop containers hive-wide in one operator action. Bare `hivectl stop` stops **everything** — all sub-agents plus the ci, forge, gateway, and matrix infra containers. Narrow it with scope flags: `--agents` (all sub-agents), `--ci` / `--forge` / `--gateway` / `--matrix` (named infra), and `--agent <name>` (repeatable) for specific sub-agents. Flags are additive (e.g. `--agents --matrix`). Requires the hive-c0re daemon (connects to the host admin socket). hive-c0re itself is never stopped — it services the request Stop containers hive-wide in one operator action.
Bare `hivectl stop` stops everything; scope flags narrow it to specific sub-agents or infra containers.
**Usage:** `hivectl stop [OPTIONS]` **Usage:** `hivectl stop [OPTIONS]`
@ -587,7 +601,9 @@ Stop containers hive-wide in one operator action. Bare `hivectl stop` stops **ev
## `hivectl start` ## `hivectl start`
Start containers hive-wide — the inverse of `hivectl stop`. Bare `hivectl start` restores the previously-running agents from the last broad-scope `stop`, or starts everything if no prior stop exists; the same scope flags as `stop` narrow it (`--agents`, `--ci`, `--forge`, `--gateway`, `--matrix`, `--agent <name>`). A targeted `--agent <name>` start is never filtered. Requires the hive-c0re daemon Start containers hive-wide — the inverse of `hivectl stop`.
Bare `hivectl start` restores the agents stopped by the last broad-scope `stop` (or starts everything if none); scope flags narrow it.
**Usage:** `hivectl start [OPTIONS]` **Usage:** `hivectl start [OPTIONS]`
@ -605,7 +621,9 @@ Start containers hive-wide — the inverse of `hivectl stop`. Bare `hivectl star
## `hivectl restart` ## `hivectl restart`
Restart containers hive-wide — `stop` then `start` over the same scope. Bare `hivectl restart` restarts **everything** (all sub-agents plus the ci/forge/gateway/matrix infra containers); the same scope flags as `stop`/`start` narrow it (`--agents`, `--ci`, `--forge`, `--gateway`, `--matrix`, `--agent <name>`). If the stop phase reports a failure the start phase is skipped so the operator can investigate. Requires the hive-c0re daemon Restart containers hive-wide — `stop` then `start` over one scope.
Bare `hivectl restart` restarts everything; scope flags narrow it.
**Usage:** `hivectl restart [OPTIONS]` **Usage:** `hivectl restart [OPTIONS]`
@ -625,21 +643,23 @@ Restart containers hive-wide — `stop` then `start` over the same scope. Bare `
Per-agent disk accounting + optional quotas via btrfs qgroups. Per-agent disk accounting + optional quotas via btrfs qgroups.
Opt-in: `quota enable` turns on btrfs qgroup accounting for the agent-state filesystem (a one-time, I/O-heavy rescan — that's why it isn't automatic). Then `quota show` reports per-agent usage and `quota limit` caps an agent. No-op on non-btrfs hosts. Operates on agent state subvolumes (created by the btrfs-subvolume migration); agents still on a plain dir report no qgroup usage. Opt-in: enable qgroup accounting, then report per-agent usage or cap an agent. No-op on non-btrfs hosts.
**Usage:** `hivectl quota <COMMAND>` **Usage:** `hivectl quota <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `enable` — Enable btrfs qgroup accounting on the agent-state filesystem. Run once before `show` / `limit`. Triggers a full btrfs rescan (I/O heavy on a large filesystem), so it's a deliberate opt-in. Idempotent; a no-op on non-btrfs hosts * `enable` — Enable btrfs qgroup accounting on the agent-state filesystem
* `show` — Report per-agent disk usage (referenced + exclusive bytes) from btrfs qgroups. With no name, shows every agent that has a state subvolume; pass a name to show just that one. Requires `enable` first * `show` — Report per-agent disk usage from btrfs qgroups (all agents, or one by name)
* `limit` — Set or clear an agent's disk quota (a referenced-usage cap). `size` accepts a byte count or a `K`/`M`/`G`/`T` suffix (e.g. `5G`), or `none` to clear the limit. Requires `enable` first * `limit` — Set or clear an agent's disk-usage quota
## `hivectl quota enable` ## `hivectl quota enable`
Enable btrfs qgroup accounting on the agent-state filesystem. Run once before `show` / `limit`. Triggers a full btrfs rescan (I/O heavy on a large filesystem), so it's a deliberate opt-in. Idempotent; a no-op on non-btrfs hosts Enable btrfs qgroup accounting on the agent-state filesystem.
Run once before `show` / `limit`. No-op on non-btrfs hosts.
**Usage:** `hivectl quota enable` **Usage:** `hivectl quota enable`
@ -647,7 +667,7 @@ Enable btrfs qgroup accounting on the agent-state filesystem. Run once before `s
## `hivectl quota show` ## `hivectl quota show`
Report per-agent disk usage (referenced + exclusive bytes) from btrfs qgroups. With no name, shows every agent that has a state subvolume; pass a name to show just that one. Requires `enable` first Report per-agent disk usage from btrfs qgroups (all agents, or one by name)
**Usage:** `hivectl quota show [NAME]` **Usage:** `hivectl quota show [NAME]`
@ -659,7 +679,7 @@ Report per-agent disk usage (referenced + exclusive bytes) from btrfs qgroups. W
## `hivectl quota limit` ## `hivectl quota limit`
Set or clear an agent's disk quota (a referenced-usage cap). `size` accepts a byte count or a `K`/`M`/`G`/`T` suffix (e.g. `5G`), or `none` to clear the limit. Requires `enable` first Set or clear an agent's disk-usage quota
**Usage:** `hivectl quota limit <NAME> <SIZE>` **Usage:** `hivectl quota limit <NAME> <SIZE>`
@ -674,20 +694,22 @@ Set or clear an agent's disk quota (a referenced-usage cap). `size` accepts a by
btrfs subvolume management for agent state dirs. btrfs subvolume management for agent state dirs.
New agents get a btrfs subvolume state root automatically (when the host FS is btrfs); agents that predate that are left on plain dirs. `subvol upgrade <agent>` opts an existing plain-dir agent into the subvolume feature set (snapshots, per-subvol usage/quota, migration) by migrating its state dir in place. Requires the hive-c0re daemon (for the stop/start) and root (for the privileged migration). Upgrade an existing plain-dir agent's state into a btrfs subvolume so it gains snapshots and per-subvol usage/quota.
**Usage:** `hivectl subvol <COMMAND>` **Usage:** `hivectl subvol <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `upgrade` — Convert an existing plain-dir agent state root into a btrfs subvolume in place. Stops the agent (so its state bind-mount is released), migrates `…/agents/<name>/` to a subvolume preserving ownership/permissions/xattrs, then restarts it. Idempotent (no-op if already a subvolume) and safe (the original dir is left untouched on any failure before the final swap). Requires `--yes` since it bounces the agent and moves its state * `upgrade` — Convert a plain-dir agent state root into a btrfs subvolume in place, so it gains snapshots and per-subvol usage/quota
* `snapshot` — Read-only snapshots of an agent's state subvolume — the first step of the (in-progress) inter-hive migration path, or a manual point-in-time backup * `snapshot` — Read-only snapshots of an agent's state subvolume
## `hivectl subvol upgrade` ## `hivectl subvol upgrade`
Convert an existing plain-dir agent state root into a btrfs subvolume in place. Stops the agent (so its state bind-mount is released), migrates `…/agents/<name>/` to a subvolume preserving ownership/permissions/xattrs, then restarts it. Idempotent (no-op if already a subvolume) and safe (the original dir is left untouched on any failure before the final swap). Requires `--yes` since it bounces the agent and moves its state Convert a plain-dir agent state root into a btrfs subvolume in place, so it gains snapshots and per-subvol usage/quota.
Bounces the agent to migrate its state, so it requires `--yes`.
**Usage:** `hivectl subvol upgrade [OPTIONS] <NAME>` **Usage:** `hivectl subvol upgrade [OPTIONS] <NAME>`
@ -703,13 +725,13 @@ Convert an existing plain-dir agent state root into a btrfs subvolume in place.
## `hivectl subvol snapshot` ## `hivectl subvol snapshot`
Read-only snapshots of an agent's state subvolume — the first step of the (in-progress) inter-hive migration path, or a manual point-in-time backup Read-only snapshots of an agent's state subvolume
**Usage:** `hivectl subvol snapshot <COMMAND>` **Usage:** `hivectl subvol snapshot <COMMAND>`
###### **Subcommands:** ###### **Subcommands:**
* `create` — Create a read-only snapshot. Agent must already be a subvolume (`subvol upgrade` first). Prints the snapshot's host path * `create` — Create a read-only snapshot (agent must already be a subvolume)
* `delete` — Delete a snapshot created by `subvol snapshot create` * `delete` — Delete a snapshot created by `subvol snapshot create`
* `send` — Export a snapshot to a local file via `btrfs send` (the local-file half of inter-hive migration transport; the cross-hive `ssh ... btrfs receive` leg isn't wired up yet). Also useful standalone as a point-in-time backup: a full send with no `--parent` produces a self-contained archive of the snapshot * `send` — Export a snapshot to a local file via `btrfs send` (the local-file half of inter-hive migration transport; the cross-hive `ssh ... btrfs receive` leg isn't wired up yet). Also useful standalone as a point-in-time backup: a full send with no `--parent` produces a self-contained archive of the snapshot
@ -717,7 +739,7 @@ Read-only snapshots of an agent's state subvolume — the first step of the (in-
## `hivectl subvol snapshot create` ## `hivectl subvol snapshot create`
Create a read-only snapshot. Agent must already be a subvolume (`subvol upgrade` first). Prints the snapshot's host path Create a read-only snapshot (agent must already be a subvolume)
**Usage:** `hivectl subvol snapshot create --label <LABEL> <NAME>` **Usage:** `hivectl subvol snapshot create --label <LABEL> <NAME>`
@ -766,7 +788,7 @@ Export a snapshot to a local file via `btrfs send` (the local-file half of inter
Print (and best-effort open in a browser) a hive web surface URL. Print (and best-effort open in a browser) a hive web surface URL.
Resolves the URL from the running daemon (`HostRequest::Urls`), so custom forge / matrix domains work without guessing `forge.<domain>`. Prints the URL unconditionally — the reliable core, since the host is usually headless / driven over SSH where `xdg-open` is a no-op — then tries `xdg-open` as a convenience. Bare `hivectl open` opens the operator dashboard. Resolves the URL from the running daemon so custom forge / matrix domains work. Bare `hivectl open` opens the operator dashboard.
**Usage:** `hivectl open [TARGET]` **Usage:** `hivectl open [TARGET]`
@ -791,7 +813,7 @@ Resolves the URL from the running daemon (`HostRequest::Urls`), so custom forge
Generate a shell completion script for `hivectl` and print it to stdout. Generate a shell completion script for `hivectl` and print it to stdout.
Pipe it into your shell's completion path — e.g. for zsh: `hivectl completions zsh > ~/.zsh/completions/_hivectl` (with that dir on `$fpath`). The hyperhive NixOS module installs the zsh script system-wide automatically, so this is mainly for ad-hoc / other-shell use. Supports bash, zsh, fish, elvish, and powershell. Supports bash, zsh, fish, elvish, and powershell. The NixOS module already installs the zsh script system-wide; this is for ad-hoc or other-shell use.
**Usage:** `hivectl completions <SHELL>` **Usage:** `hivectl completions <SHELL>`

View file

@ -53,77 +53,67 @@ struct Cli {
#[derive(Subcommand)] #[derive(Subcommand)]
enum Cmd { enum Cmd {
/// Forgejo user provisioning. Manual entry point to the same /// Forgejo user provisioning.
/// idempotent flow c0re runs automatically at boot ///
/// (`forge::ensure_all`) — useful for recovery, ad-hoc reprovisioning, /// Manual entry point to the same idempotent provisioning c0re runs at
/// or single-agent fixes without bouncing the daemon. /// boot — for recovery, ad-hoc reprovisioning, or fixing one agent
/// without bouncing the daemon.
Forge { Forge {
#[command(subcommand)] #[command(subcommand)]
cmd: ForgeCmd, cmd: ForgeCmd,
}, },
/// matrix-tuwunel user provisioning. Manual entry point to the same /// matrix-tuwunel user provisioning.
/// idempotent flow c0re runs automatically at boot ///
/// (`matrix::ensure_all`) — useful when the boot-time sweep skipped /// Manual entry point to the same idempotent provisioning c0re runs at
/// an agent (e.g. matrix container wasn't up yet) or to re-register /// boot — for re-registering an agent the boot sweep skipped, or after
/// after wiping a token file. /// wiping a token file.
Matrix { Matrix {
#[command(subcommand)] #[command(subcommand)]
cmd: MatrixCmd, cmd: MatrixCmd,
}, },
/// GitHub account provisioning: write an operator-supplied personal /// GitHub account provisioning.
/// access token (PAT) into an agent's `github-token` state file so its ///
/// `gh` wrapper + git credential helper can authenticate. Unlike /// Store an operator-supplied personal access token (PAT) for an agent
/// forge/matrix there is no account creation — the operator supplies a /// so its `gh` and git can authenticate. No account is created — the
/// PAT for an existing GitHub account. A CLI alternative to the dashboard /// PAT is for an existing GitHub account.
/// credentials tab; the integration is on by default
/// (`hyperhive.github.enable`), so no per-agent config is needed.
Github { Github {
#[command(subcommand)] #[command(subcommand)]
cmd: GithubCmd, cmd: GithubCmd,
}, },
/// Gateway htpasswd user management. Add, remove, or list users in /// Gateway htpasswd user management.
/// an htpasswd file used by the gateway's HTTP Basic auth ///
/// (`services.hyperhive.gateway.auth`). Credentials are stored as /// Add, remove, or list users for the gateway's HTTP Basic auth.
/// `BCrypt` hashes — no extra service or PAM required.
Gateway { Gateway {
#[command(subcommand)] #[command(subcommand)]
cmd: GatewayCmd, cmd: GatewayCmd,
}, },
/// Agent container management. Requires the hive-c0re daemon to be /// Agent container management.
/// running (connects to the host admin socket). ///
/// Lifecycle actions on managed agent containers. Needs the hive-c0re
/// daemon running.
Agents { Agents {
#[command(subcommand)] #[command(subcommand)]
cmd: AgentsCmd, cmd: AgentsCmd,
}, },
/// Operator approval queue: list pending requests, approve / deny them. /// Operator approval queue: list, approve, or deny pending requests.
/// Requires the hive-c0re daemon to be running (connects to the host ///
/// admin socket). /// Needs the hive-c0re daemon running.
Approvals { Approvals {
#[command(subcommand)] #[command(subcommand)]
cmd: ApprovalsCmd, cmd: ApprovalsCmd,
}, },
/// WireGuard inter-hive mesh setup helpers (`services.hyperhive.swarm`). /// WireGuard inter-hive mesh setup helpers.
/// ///
/// One-time-setup convenience so nobody has to remember the `wg` dance: /// Generate this hive's mesh key and print the nix to enable the mesh,
/// `wg init` generates + stores this hive's private key and prints the /// add a peer, or inspect live interface state.
/// public key plus the nix snippet to enable the mesh; `wg peer` prints
/// the snippet to add a remote hive; `wg status` wraps `wg show`. The
/// verbs own the imperative state (the key file); the printed nix goes
/// into the operator's host config (kept in git), so nothing here mutates
/// declarative config behind the operator's back.
Wg { Wg {
#[command(subcommand)] #[command(subcommand)]
cmd: WgCmd, cmd: WgCmd,
}, },
/// Generate the federation peer-config block for THIS hive — the nix /// Generate the federation peer-config block for THIS hive.
/// a peer operator pastes into their `services.hyperhive.swarm.peers` ///
/// to trust + reach this hive. Emits `caCert` (+ a `cp` line for the /// Prints the nix a peer operator pastes into their swarm config to
/// cert) when this hive serves a self-signed CA, the WireGuard public /// trust and reach this hive.
/// key when the mesh key exists, and the `wireguard{Address,Endpoint}`
/// you pass. The hive's own domain is filled in automatically from the
/// running daemon (`services.hyperhive.domain`). Reads local state (the
/// TLS CA cert, the wg key); never mutates. `wg init` calls this at the
/// end, so a fresh mesh setup prints the hand-over block too.
PeerConfig { PeerConfig {
/// This hive's WireGuard mesh address (e.g. `10.42.0.1/32`), /// This hive's WireGuard mesh address (e.g. `10.42.0.1/32`),
/// emitted as `wireguardAddress`. Omit when not running the mesh. /// emitted as `wireguardAddress`. Omit when not running the mesh.
@ -136,11 +126,8 @@ enum Cmd {
}, },
/// Open an interactive Claude session inside an agent container. /// Open an interactive Claude session inside an agent container.
/// ///
/// Runs claude as the agent user from its state dir with the harness's /// A fresh session by default, or resume a prior one. Requires root
/// settings / MCP / system prompt. Bare `choom <name>` is a fresh /// and a running container.
/// session; `--resume <session-id>` rejoins a prior one. Never
/// collides with the harness's live session. Requires root + a running
/// container. See `docs/tools/hivectl.md` (Choom) for details.
Choom { Choom {
/// Agent name (e.g. `damocles`, `iris`). /// Agent name (e.g. `damocles`, `iris`).
name: String, name: String,
@ -153,14 +140,10 @@ enum Cmd {
#[arg(long = "resume", value_name = "SESSION")] #[arg(long = "resume", value_name = "SESSION")]
resume_session: Option<String>, resume_session: Option<String>,
}, },
/// Stop containers hive-wide in one operator action. Bare `hivectl /// Stop containers hive-wide in one operator action.
/// stop` stops **everything** — all sub-agents plus the ci, forge, ///
/// gateway, and matrix infra containers. Narrow it with scope flags: /// Bare `hivectl stop` stops everything; scope flags narrow it to
/// `--agents` (all sub-agents), `--ci` / `--forge` / `--gateway` / /// specific sub-agents or infra containers.
/// `--matrix` (named infra), and `--agent <name>` (repeatable) for
/// specific sub-agents. Flags are additive (e.g. `--agents --matrix`).
/// Requires the hive-c0re daemon (connects to the host admin socket).
/// hive-c0re itself is never stopped — it services the request.
Stop { Stop {
#[command(flatten)] #[command(flatten)]
scope: ScopeArgs, scope: ScopeArgs,
@ -177,13 +160,11 @@ enum Cmd {
#[arg(long)] #[arg(long)]
no_wait: bool, no_wait: bool,
}, },
/// Start containers hive-wide — the inverse of `hivectl stop`. Bare /// Start containers hive-wide — the inverse of `hivectl stop`.
/// `hivectl start` restores the previously-running agents from the ///
/// last broad-scope `stop`, or starts everything if no prior stop /// Bare `hivectl start` restores the agents stopped by the last
/// exists; the same scope flags as `stop` narrow it (`--agents`, /// broad-scope `stop` (or starts everything if none); scope flags
/// `--ci`, `--forge`, `--gateway`, `--matrix`, `--agent <name>`). A /// narrow it.
/// targeted `--agent <name>` start is never filtered. Requires the
/// hive-c0re daemon.
Start { Start {
#[command(flatten)] #[command(flatten)]
scope: ScopeArgs, scope: ScopeArgs,
@ -192,13 +173,9 @@ enum Cmd {
#[arg(long)] #[arg(long)]
no_wait: bool, no_wait: bool,
}, },
/// Restart containers hive-wide — `stop` then `start` over the same /// Restart containers hive-wide — `stop` then `start` over one scope.
/// scope. Bare `hivectl restart` restarts **everything** (all sub-agents ///
/// plus the ci/forge/gateway/matrix infra containers); the same scope /// Bare `hivectl restart` restarts everything; scope flags narrow it.
/// flags as `stop`/`start` narrow it (`--agents`, `--ci`, `--forge`,
/// `--gateway`, `--matrix`, `--agent <name>`). If the stop phase reports
/// a failure the start phase is skipped so the operator can investigate.
/// Requires the hive-c0re daemon.
Restart { Restart {
#[command(flatten)] #[command(flatten)]
scope: ScopeArgs, scope: ScopeArgs,
@ -209,36 +186,24 @@ enum Cmd {
}, },
/// Per-agent disk accounting + optional quotas via btrfs qgroups. /// Per-agent disk accounting + optional quotas via btrfs qgroups.
/// ///
/// Opt-in: `quota enable` turns on btrfs qgroup accounting for the /// Opt-in: enable qgroup accounting, then report per-agent usage or
/// agent-state filesystem (a one-time, I/O-heavy rescan — that's why /// cap an agent. No-op on non-btrfs hosts.
/// it isn't automatic). Then `quota show` reports per-agent usage and
/// `quota limit` caps an agent. No-op on non-btrfs hosts. Operates on
/// agent state subvolumes (created by the btrfs-subvolume migration);
/// agents still on a plain dir report no qgroup usage.
Quota { Quota {
#[command(subcommand)] #[command(subcommand)]
cmd: QuotaCmd, cmd: QuotaCmd,
}, },
/// btrfs subvolume management for agent state dirs. /// btrfs subvolume management for agent state dirs.
/// ///
/// New agents get a btrfs subvolume state root automatically (when the /// Upgrade an existing plain-dir agent's state into a btrfs subvolume
/// host FS is btrfs); agents that predate that are left on plain dirs. /// so it gains snapshots and per-subvol usage/quota.
/// `subvol upgrade <agent>` opts an existing plain-dir agent into the
/// subvolume feature set (snapshots, per-subvol usage/quota, migration)
/// by migrating its state dir in place. Requires the hive-c0re daemon
/// (for the stop/start) and root (for the privileged migration).
Subvol { Subvol {
#[command(subcommand)] #[command(subcommand)]
cmd: SubvolCmd, cmd: SubvolCmd,
}, },
/// Print (and best-effort open in a browser) a hive web surface URL. /// Print (and best-effort open in a browser) a hive web surface URL.
/// ///
/// Resolves the URL from the running daemon (`HostRequest::Urls`), so /// Resolves the URL from the running daemon so custom forge / matrix
/// custom forge / matrix domains work without guessing `forge.<domain>`. /// domains work. Bare `hivectl open` opens the operator dashboard.
/// Prints the URL unconditionally — the reliable core, since the host
/// is usually headless / driven over SSH where `xdg-open` is a no-op —
/// then tries `xdg-open` as a convenience. Bare `hivectl open` opens the
/// operator dashboard.
Open { Open {
/// Which surface to open. Defaults to the operator dashboard. /// Which surface to open. Defaults to the operator dashboard.
#[arg(value_enum, default_value_t = OpenTarget::Home)] #[arg(value_enum, default_value_t = OpenTarget::Home)]
@ -246,21 +211,16 @@ enum Cmd {
}, },
/// Emit the full CLI reference as `CommonMark` to stdout. /// Emit the full CLI reference as `CommonMark` to stdout.
/// ///
/// Hidden tooling command (not part of day-to-day operator admin): /// Hidden tooling command used by the docs build to keep the published
/// walks this binary's own clap command tree and renders every verb, /// `hivectl` reference in lockstep with the code.
/// flag, and help string as markdown. Used by the docs build to keep
/// the published `hivectl` reference in lockstep with the code — no
/// hand-maintained command list to drift out of date.
#[command(hide = true)] #[command(hide = true)]
MarkdownDocs, MarkdownDocs,
/// Generate a shell completion script for `hivectl` and print it to /// Generate a shell completion script for `hivectl` and print it to
/// stdout. /// stdout.
/// ///
/// Pipe it into your shell's completion path — e.g. for zsh: /// Supports bash, zsh, fish, elvish, and powershell. The NixOS module
/// `hivectl completions zsh > ~/.zsh/completions/_hivectl` (with that /// already installs the zsh script system-wide; this is for ad-hoc or
/// dir on `$fpath`). The hyperhive NixOS module installs the zsh script /// other-shell use.
/// system-wide automatically, so this is mainly for ad-hoc / other-shell
/// use. Supports bash, zsh, fish, elvish, and powershell.
Completions { Completions {
/// Shell to emit completions for. /// Shell to emit completions for.
shell: clap_complete::Shell, shell: clap_complete::Shell,
@ -325,24 +285,9 @@ impl ScopeArgs {
enum ForgeCmd { enum ForgeCmd {
/// Create or refresh the Forgejo account + token for `<name>`. /// Create or refresh the Forgejo account + token for `<name>`.
/// ///
/// When `<name>` matches an existing agent (i.e. it has a state /// For an existing agent, persists the token to its state dir; for a
/// dir under `/var/lib/hyperhive/agents/`), persists the token to /// human/other account, prints the token to stdout. Set a password to
/// `<state>/forge-token` (idempotent: re-mints + rewrites every /// enable forge web-UI login (a random throwaway is used otherwise).
/// call so the on-disk scope matches the current
/// `forge::TOKEN_SCOPES`).
///
/// When `<name>` is **not** an agent (a human or any other
/// non-container account), creates the forgejo user and prints the
/// freshly-minted token to stdout — no `/var/lib/hyperhive/agents/`
/// directory is created for the user.
///
/// Without `--password` / `--password-stdin` a random throwaway is
/// used (fine for agents — they auth by token via tea / hive-forge).
/// Set a password to log into the forge web UI afterwards.
/// `--password` is idempotent: re-running with the same value sets
/// the same password (covers password resets on already-created
/// accounts since `forgejo admin user create` silently no-ops once
/// the user exists).
CreateUser { CreateUser {
/// Forgejo username. For agents: the container/agent name /// Forgejo username. For agents: the container/agent name
/// (`<n>` in `h-<n>`; manager uses the literal `manager`). /// (`<n>` in `h-<n>`; manager uses the literal `manager`).
@ -368,20 +313,10 @@ enum ForgeCmd {
enum MatrixCmd { enum MatrixCmd {
/// Create or refresh the matrix account + access token for `<name>`. /// Create or refresh the matrix account + access token for `<name>`.
/// ///
/// When `<name>` matches an existing agent (i.e. it has a state /// For an existing agent, persists the token to its state dir; for a
/// dir under `/var/lib/hyperhive/agents/`), persists the token to /// human/other account, prints the access token to stdout. Set a
/// `<state>/matrix-token`. Skips registration when the file is /// password to enable matrix web-client login (a random throwaway is
/// already populated; delete it to force re-registration. /// used otherwise).
///
/// When `<name>` is **not** an agent (a human or any other
/// non-container account), registers the matrix user and prints
/// the freshly-minted access token to stdout — no
/// `/var/lib/hyperhive/agents/` directory is created for the user.
///
/// Without `--password` / `--password-stdin` a random throwaway is
/// used (fine for agents — they auth by `access_token`, never by
/// password). Set a password to log into a matrix web client
/// afterwards.
CreateUser { CreateUser {
/// Matrix localpart. For agents: the container/agent name. /// Matrix localpart. For agents: the container/agent name.
/// For humans: any matrix localpart — `mara`, `damocles`, etc. /// For humans: any matrix localpart — `mara`, `damocles`, etc.
@ -400,34 +335,25 @@ enum MatrixCmd {
#[arg(long, conflicts_with = "password")] #[arg(long, conflicts_with = "password")]
password_stdin: bool, password_stdin: bool,
}, },
/// Provision (or re-provision) the hive system admin matrix account /// Provision (or re-provision) the hive system admin matrix account.
/// (`@hive:<server>`). hive-c0re runs this automatically on startup ///
/// before the agent sweep so the account is the first registered /// Runs automatically on startup; run manually to recover a missing
/// user — Conduit/tuwunel grants admin rights to the first user. /// admin token.
/// Run manually to recover a missing admin token file.
SyncAdmin, SyncAdmin,
/// Promote a matrix user to homeserver admin via the admin API. /// Promote a matrix user to homeserver admin.
/// Uses the hive system admin token at
/// `/var/lib/hyperhive/matrix/admin-token`. The `server_name` is
/// discovered automatically from the running homeserver.
PromoteUser { PromoteUser {
/// Matrix localpart of the user to promote (e.g. `argus`). /// Matrix localpart of the user to promote (e.g. `argus`).
name: String, name: String,
}, },
/// Reset a matrix user's password via the admin API and persist the /// Reset a matrix user's password via the admin API.
/// new password to `/var/lib/hyperhive/matrix/creds/<name>-password`
/// so the next `ensure_user_for` (or `create-user`) can re-login.
/// ///
/// After this command succeeds, run `hivectl matrix create-user /// Persists the new password so a later `create-user` can re-login.
/// <name>` to mint a fresh access token for the agent.
ResetPassword { ResetPassword {
/// Matrix localpart of the account to reset (e.g. `argus`). /// Matrix localpart of the account to reset (e.g. `argus`).
name: String, name: String,
}, },
/// Invite a matrix user to the hive Space (default) or a specific /// Invite a matrix user to the hive Space, or a specific room with
/// room. Uses the hive admin token; the admin account must be a /// `--room`. Idempotent.
/// member of the target room with invite power (it owns the hive
/// Space). Idempotent — already-member / already-invited is a no-op.
Invite { Invite {
/// User to invite: a full id (`@mara:server`) or a bare /// User to invite: a full id (`@mara:server`) or a bare
/// localpart (qualified with the homeserver's `server_name`). /// localpart (qualified with the homeserver's `server_name`).
@ -441,13 +367,11 @@ enum MatrixCmd {
#[derive(Subcommand)] #[derive(Subcommand)]
enum GithubCmd { enum GithubCmd {
/// Write a GitHub PAT into `<agent>`'s state dir (`github-token`, 0600, /// Store a GitHub PAT for `<agent>` so its `gh` and git can
/// agent-owned) via hive-priv. The GitHub integration is on by default /// authenticate.
/// (`hyperhive.github.enable`), so the `gh` wrapper + git credential ///
/// helper pick the token up with no per-agent config. The token is read /// Prefer `--token-stdin` — an inline `--token` is visible in shell
/// live at invocation, so no rebuild/restart is needed. Prefer /// history.
/// `--token-stdin`: an inline `--token` is visible in shell history +
/// process listings.
SetToken { SetToken {
/// Logical agent name (the container/agent name). /// Logical agent name (the container/agent name).
agent: String, agent: String,
@ -463,13 +387,10 @@ enum GithubCmd {
#[derive(Subcommand)] #[derive(Subcommand)]
enum GatewayCmd { enum GatewayCmd {
/// Add a new user or update the password of an existing user in the /// Add a user or update an existing user's password in the gateway
/// gateway htpasswd file. The daemon bcrypt-hashes the password (cost 12) /// htpasswd.
/// and writes the credential store — hivectl relays over the host socket
/// and never touches the file.
/// ///
/// Pass `--password-stdin` when scripting or when you don't want the /// Use `--password-stdin` to keep the password out of shell history.
/// password visible in shell history.
CreateUser { CreateUser {
/// Username to add or update. /// Username to add or update.
username: String, username: String,
@ -483,8 +404,7 @@ enum GatewayCmd {
#[arg(long)] #[arg(long)]
password_stdin: bool, password_stdin: bool,
}, },
/// Remove a user from the gateway htpasswd file. Exits with an error /// Remove a user from the gateway htpasswd.
/// when the user is not found so callers can detect the no-op case.
DeleteUser { DeleteUser {
/// Username to remove. /// Username to remove.
username: String, username: String,
@ -495,19 +415,15 @@ enum GatewayCmd {
#[derive(Subcommand)] #[derive(Subcommand)]
enum WgCmd { enum WgCmd {
/// Generate (if absent) this hive's WireGuard private key, print its /// Generate this hive's WireGuard key (if absent) and print its public
/// public key, and print the nix snippet to enable the mesh. Idempotent: /// key plus the nix to enable the mesh.
/// an existing key is reused, never clobbered (clobbering would break a
/// live mesh). Share the printed public key with peer hives.
Init { Init {
/// This hive's mesh address (e.g. `10.42.0.1/32`) to bake into the /// This hive's mesh address (e.g. `10.42.0.1/32`) to bake into the
/// printed snippet. Omit to get a placeholder you fill in. /// printed snippet. Omit to get a placeholder you fill in.
#[arg(long)] #[arg(long)]
address: Option<String>, address: Option<String>,
}, },
/// Print the nix snippet to add a peer hive to the mesh. Pure output — /// Print the nix to add a peer hive to the mesh.
/// paste it into this hive's config. Get `<pubkey>` from the peer's
/// `hivectl wg init`.
Peer { Peer {
/// Peer hive's DNS domain (the `swarm.peers` attrset key). /// Peer hive's DNS domain (the `swarm.peers` attrset key).
domain: String, domain: String,
@ -522,29 +438,23 @@ enum WgCmd {
#[arg(long)] #[arg(long)]
endpoint: Option<String>, endpoint: Option<String>,
}, },
/// Show the live mesh interface state (`wg show wg-hive`). Requires the /// Show the live mesh interface state.
/// mesh to be enabled + up.
Status, Status,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
enum QuotaCmd { enum QuotaCmd {
/// Enable btrfs qgroup accounting on the agent-state filesystem. Run /// Enable btrfs qgroup accounting on the agent-state filesystem.
/// once before `show` / `limit`. Triggers a full btrfs rescan (I/O ///
/// heavy on a large filesystem), so it's a deliberate opt-in. /// Run once before `show` / `limit`. No-op on non-btrfs hosts.
/// Idempotent; a no-op on non-btrfs hosts.
Enable, Enable,
/// Report per-agent disk usage (referenced + exclusive bytes) from /// Report per-agent disk usage from btrfs qgroups (all agents, or one
/// btrfs qgroups. With no name, shows every agent that has a state /// by name).
/// subvolume; pass a name to show just that one. Requires `enable`
/// first.
Show { Show {
/// Agent to show (omit for all agents with a state subvolume). /// Agent to show (omit for all agents with a state subvolume).
name: Option<String>, name: Option<String>,
}, },
/// Set or clear an agent's disk quota (a referenced-usage cap). `size` /// Set or clear an agent's disk-usage quota.
/// accepts a byte count or a `K`/`M`/`G`/`T` suffix (e.g. `5G`), or
/// `none` to clear the limit. Requires `enable` first.
Limit { Limit {
/// Agent whose state subvolume to limit. /// Agent whose state subvolume to limit.
name: String, name: String,
@ -560,10 +470,7 @@ use hive_host_sock::HOST_SOCKET as DEFAULT_HOST_SOCKET;
#[derive(Subcommand)] #[derive(Subcommand)]
enum AgentsCmd { enum AgentsCmd {
/// Show all managed agents with their status (running / needs-login / /// Show all managed agents with their status and technical state.
/// needs-update) and technical state (deployed sha, parent, pending
/// reminders). The host roster overview; reuses the dashboard's
/// per-agent aggregation. Requires the daemon running.
List { List {
/// Emit the raw JSON rows instead of the padded table (for /// Emit the raw JSON rows instead of the padded table (for
/// scripting). The table is the default human-readable shape. /// scripting). The table is the default human-readable shape.
@ -571,10 +478,6 @@ enum AgentsCmd {
json: bool, json: bool,
}, },
/// Stop and start a single agent container without rebuilding config. /// Stop and start a single agent container without rebuilding config.
/// Useful for "kick the container" when the process is stuck or the
/// container needs a clean restart without changing the NixOS config.
/// Rides the job queue (serialized against in-flight rebuilds for
/// the same agent); waits with live progress unless `--no-wait`.
Restart { Restart {
/// Agent name (e.g. `damocles`, `ruth`). /// Agent name (e.g. `damocles`, `ruth`).
name: String, name: String,
@ -582,23 +485,21 @@ enum AgentsCmd {
#[arg(long)] #[arg(long)]
no_wait: bool, no_wait: bool,
}, },
/// Restart ALL managed agent containers via one restart DAG each — /// Restart all managed agent containers.
/// unrelated agents overlap, each serializes on its own lease.
/// Waits for the whole set with live progress unless `--no-wait`.
RestartAll { RestartAll {
/// Return immediately after the restart DAGs are queued. /// Return immediately after the restart DAGs are queued.
#[arg(long)] #[arg(long)]
no_wait: bool, no_wait: bool,
}, },
/// Spawn a new agent container directly (`h-<name>`). Bypasses the /// Spawn a new agent container directly, bypassing the approval queue.
/// approval queue — operator-on-the-host only. For approval-gated ///
/// spawns, use `request-spawn`. /// Operator-on-the-host only; use `request-spawn` for an approval-gated
/// spawn.
Spawn { Spawn {
/// Agent name (e.g. `iris`). /// Agent name (e.g. `iris`).
name: String, name: String,
}, },
/// Queue a spawn request as an approval. The container is created on /// Queue a spawn request for operator approval.
/// `hivectl approvals approve <id>` (or the dashboard APPR0VE button).
RequestSpawn { RequestSpawn {
/// Agent name. /// Agent name.
name: String, name: String,
@ -608,13 +509,12 @@ enum AgentsCmd {
/// Agent name. /// Agent name.
name: String, name: String,
}, },
/// Tear down a sub-agent container. The container is removed; persistent /// Tear down a sub-agent container, keeping its state by default. No
/// state (config repos + Claude credentials) is kept by default. Pass /// undo.
/// `--purge` to also wipe the agent's state dirs (config + creds +
/// notes). No undo.
Destroy { Destroy {
/// Agent name. /// Agent name.
name: String, name: String,
/// Also wipe the agent's state dirs (config + creds + notes).
#[arg(long)] #[arg(long)]
purge: bool, purge: bool,
}, },
@ -623,9 +523,7 @@ enum AgentsCmd {
/// Agent name. /// Agent name.
name: String, name: String,
}, },
/// Move an agent in the topology tree. Set `--parent` to a new parent /// Move an agent in the topology tree — under a new parent, or to root.
/// agent name, or pass `--root` to promote the agent to root (no
/// parent). Exactly one is required. Refuses cycles and unknown agents.
SetParent { SetParent {
/// Agent to move. /// Agent to move.
child: String, child: String,
@ -638,8 +536,7 @@ enum AgentsCmd {
}, },
} }
/// Operator approval queue: list pending requests and approve / deny them. /// Operator approval queue: list, approve, or deny pending requests.
/// Requires the hive-c0re daemon (connects to the host admin socket).
#[derive(Subcommand)] #[derive(Subcommand)]
enum ApprovalsCmd { enum ApprovalsCmd {
/// List pending approval requests submitted by agents. /// List pending approval requests submitted by agents.
@ -658,13 +555,10 @@ enum ApprovalsCmd {
#[derive(Subcommand)] #[derive(Subcommand)]
enum SubvolCmd { enum SubvolCmd {
/// Convert an existing plain-dir agent state root into a btrfs subvolume /// Convert a plain-dir agent state root into a btrfs subvolume in
/// in place. Stops the agent (so its state bind-mount is released), /// place, so it gains snapshots and per-subvol usage/quota.
/// migrates `…/agents/<name>/` to a subvolume preserving ///
/// ownership/permissions/xattrs, then restarts it. Idempotent (no-op if /// Bounces the agent to migrate its state, so it requires `--yes`.
/// already a subvolume) and safe (the original dir is left untouched on
/// any failure before the final swap). Requires `--yes` since it bounces
/// the agent and moves its state.
Upgrade { Upgrade {
/// Agent name (e.g. `damocles`, `iris`). /// Agent name (e.g. `damocles`, `iris`).
name: String, name: String,
@ -673,9 +567,7 @@ enum SubvolCmd {
#[arg(long)] #[arg(long)]
yes: bool, yes: bool,
}, },
/// Read-only snapshots of an agent's state subvolume — the first step /// Read-only snapshots of an agent's state subvolume.
/// of the (in-progress) inter-hive migration path, or a manual
/// point-in-time backup.
Snapshot { Snapshot {
#[command(subcommand)] #[command(subcommand)]
cmd: SnapshotCmd, cmd: SnapshotCmd,
@ -684,8 +576,7 @@ enum SubvolCmd {
#[derive(Subcommand)] #[derive(Subcommand)]
enum SnapshotCmd { enum SnapshotCmd {
/// Create a read-only snapshot. Agent must already be a subvolume /// Create a read-only snapshot (agent must already be a subvolume).
/// (`subvol upgrade` first). Prints the snapshot's host path.
Create { Create {
/// Agent name (e.g. `damocles`, `iris`). /// Agent name (e.g. `damocles`, `iris`).
name: String, name: String,