hivectl: add hive-wide restart verb (stop then start)

`hivectl restart [scope]` cycles the scoped containers — composes the
existing stop + start daemon ops client-side (reusing the merged Stop/Start
wire ops + global --socket), so no new wire/c0re surface. Same scope model
as stop/start (--agents/--agent/--ci/--forge/--gateway/--matrix), and
--graceful on the stop half. If the stop phase reports a failure the start
phase is skipped so a half-stopped hive isn't blindly started over.
Regenerated docs/tools/hivectl-cli.md.
This commit is contained in:
atlas 2026-06-19 12:04:35 +02:00
commit 31a4947aff
2 changed files with 47 additions and 0 deletions

View file

@ -23,6 +23,7 @@ This document contains the help content for the `hivectl` command-line program.
* [`hivectl choom`↴](#hivectl-choom)
* [`hivectl stop`↴](#hivectl-stop)
* [`hivectl start`↴](#hivectl-start)
* [`hivectl restart`↴](#hivectl-restart)
## `hivectl`
@ -39,6 +40,7 @@ Sibling to the `hive-c0re` daemon binary. Covers host-side admin operations that
* `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
* `start` — Start containers hive-wide — the inverse of `hivectl stop`. Bare `hivectl start` starts everything back up; the same scope flags as `stop` narrow it (`--agents`, `--ci`, `--forge`, `--gateway`, `--matrix`, `--agent <name>`). Requires the hive-c0re daemon
* `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
###### **Options:**
@ -330,6 +332,24 @@ Start containers hive-wide — the inverse of `hivectl stop`. Bare `hivectl star
## `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
**Usage:** `hivectl restart [OPTIONS]`
###### **Options:**
* `--agents` — All sub-agent containers
* `--agent <NAME>` — A specific sub-agent by name. Repeatable: `--agent a --agent b`
* `--ci` — The CI runner container (`hive-ci`)
* `--forge` — The forge container (`hive-forge`)
* `--gateway` — The gateway container (`hive-gateway`)
* `--matrix` — The matrix container (`hive-matrix`)
* `--graceful` — Gracefully quiesce each agent on the stop half (see `stop --graceful`). NOTE: not yet effective — falls through to a hard stop until the per-agent quiesce lands
<hr/>
<small><i>

View file

@ -133,6 +133,22 @@ enum Cmd {
#[command(flatten)]
scope: ScopeArgs,
},
/// 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 {
#[command(flatten)]
scope: ScopeArgs,
/// Gracefully quiesce each agent on the stop half (see
/// `stop --graceful`). NOTE: not yet effective — falls through to a
/// hard stop until the per-agent quiesce lands.
#[arg(long)]
graceful: bool,
},
/// Emit the full CLI reference as `CommonMark` to stdout.
///
/// Hidden tooling command (not part of day-to-day operator admin):
@ -420,6 +436,7 @@ async fn main() -> Result<()> {
},
Cmd::Stop { scope, graceful } => stop(&socket, scope.to_scope(), graceful).await,
Cmd::Start { scope } => start(&socket, scope.to_scope()).await,
Cmd::Restart { scope, graceful } => restart(&socket, scope.to_scope(), graceful).await,
Cmd::Choom { name, fresh } => choom(&name, fresh),
Cmd::MarkdownDocs => {
print!("{}", clap_markdown::help_markdown::<Cli>());
@ -891,6 +908,16 @@ async fn start(socket: &Path, scope: hive_sh4re::LifecycleScope) -> Result<()> {
render_lifecycle(&resp, "started")
}
/// Restart = `stop` then `start` over the same scope, composed client-side
/// from the two daemon ops (no dedicated wire op). The stop phase honours
/// `--graceful`; if it reports a failure (`stop` returns `Err`) the `?`
/// short-circuits before the start phase, so a half-stopped hive isn't
/// blindly started over — the operator sees the stop errors and can recover.
async fn restart(socket: &Path, scope: hive_sh4re::LifecycleScope, graceful: bool) -> Result<()> {
stop(socket, scope.clone(), graceful).await?;
start(socket, scope).await
}
/// Render a hive-wide stop/start response: one `<verb>: <name>` line per
/// touched container, then surface any aggregated per-target failure as a
/// non-zero exit. `verb` is the past-tense word printed per item