Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/docs/2-handbook/hives/hivectl.md
iris 7ba684a1da docs: the agent roster page is Agent permissions, and the docs say agent list
Roster named the permissions page, the hive's topology file and the swarm's list of agents without saying which. The page and its links are renamed; the implementation docs and UI text follow separately.
2026-11-11 23:52:15 +01:00

167 lines
8.8 KiB
Markdown

# 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.deploy.hive-controller.adminUsers` (adds you to the
`hive-admin` group that owns the socket; see
[`docs/2-handbook/hives/boundary.md`](boundary.md#host-admin-socket-access-hivectl)).
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: container lifecycle
shortcuts and interactive agent shell access.
This page is the curated guide. For the exhaustive flag-by-flag
reference autogenerated from the binary's own command tree, see
[`hivectl-cli.md`](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/2-handbook/hives/hivectl-cli.md`.
## 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>` — `hivectl` hoists
the name onto the parent command, so none of the verbs below repeat it.
```bash
hivectl list-agents # every agent's status + technical state
hivectl list-agents --json # same data as raw JSON rows (for scripting)
hivectl agent agent1 restart # stop + start the `agent1` container (no rebuild)
hivectl agent agent1 pause # park agent1's turn loop, leave the container running
hivectl agent agent1 resume # let it drive turns again, draining what queued up
```
`list-agents` prints a padded table with one row per managed agent —
`NAME STATUS REMIND`. STATUS collapses the health flags
(`running` / `stopped`, plus ` paused` / ` needs-login`
when set — `paused` is orthogonal to running, see below);
REMIND is the count of pending reminders. It reuses the same per-agent aggregation the dashboard
renders, so the CLI list 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 an agent at all. 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:
- **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.
- **A DAG, with an acknowledgement wait.** `pause` creates a DAG whose drain
node waits for the harness to acknowledge the marker (giving up after
3 minutes); `--no-wait` returns once the DAG exists.
- **Stopping a paused agent is still fast.** hive-c0re skips the graceful-stop
handshake 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 ` paused` in `list-agents`'s STATUS column, as a `paused`
field 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, or membership in
`hive-admin` (the same sudoless-`hivectl` group as the [host admin
socket](boundary.md) — hive-c0re ships a polkit rule
granting that group the one action `machinectl shell` needs); `choom`
checks this itself and refuses up front with a message naming the
requirement rather than letting systemd reject the exec later with an
opaque polkit prompt. Same caveat as the socket grant: a shell opened
before the operator added you to `hive-admin` doesn't see it until you log
back in — secondary group membership applies at login.
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 the daemon's user owns and which isn't group-readable, so the check
is a `HostRequest` rather than a local `stat`. An unprivileged `choom`
therefore names the grant it wants, instead of reporting a permission
problem with the state dir.
```bash
hivectl agent agent1 choom # fresh blank Claude session in agent1's container
hivectl agent agent1 choom --resume <session-id> # rejoin a prior session by id
```
Bare `choom` starts a fresh blank session. It runs Claude Code, so it works only
on agents with the `claude` runtime.
`--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, that is, the
harness's; claude would consume a value after it as the first prompt,
silently poking the live harness session.) Passing the flag requires a
value. 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 shell` defaults to root,
which would make claude read `/root/.claude` (empty) instead of the
agent's `/home/<name>/.claude` where 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 and `AGENTS.md` (the
persona) resolve against the right project dir.
- **with the harness flags**: `--settings`, `--mcp-config`, and
`--system-prompt-file` from `/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`) seeds `hasCompletedOnboarding` and the
project trust flags into `~/.claude.json` once 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.
## Watch
Follow an agent's live turn/tool-call event stream from the CLI:
```bash
hivectl agent agent1 watch # tail agent1's live events; Ctrl-C to stop
```
Dials the same unix socket the gateway's nginx `proxy_pass`es through
(`/run/hive-agent/<name>/web.sock` — see [Per-agent unix-socket
upstream](../../4-implementation/networking/gateway.md#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/4-implementation/web-ui/terminal-rendering.md`)
— that's presentation for a browser, this is a `tail -f`.
Agents write these lines, so hivectl replaces every control character except
tab with U+FFFD before printing; an escape sequence in a summary
can't reach your terminal. When stdout closes, as in `watch | head`, the
watch ends with exit 0 and no output.