From c7612dcf2b1cf8e24c944d62548914e33c7f3d80 Mon Sep 17 00:00:00 2001 From: atlas Date: Fri, 19 Jun 2026 13:21:54 +0200 Subject: [PATCH] hivectl: shell completions verb + ship zsh/bash/fish completions (#1764) Add a 'hivectl completions ' subcommand (clap_complete) that prints a completion script for bash/zsh/fish/elvish/powershell, generated from hivectl's own clap command tree so it never drifts from the real verbs/flags. The package build installs the bash/zsh/fish scripts via installShellFiles, so an operator gets working completion automatically once hivectl is on their profile with shell completion enabled. Regenerated docs/tools/hivectl-cli.md for the new verb. --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + docs/tools/hivectl-cli.md | 19 +++++++++++++++++++ flake.nix | 18 +++++++++++++++++- hive-c0re/Cargo.toml | 1 + hive-c0re/src/bin/hivectl.rs | 25 +++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f6f6cfd7..1ae04e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,6 +539,15 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.6.1" @@ -1354,6 +1363,7 @@ dependencies = [ "bcrypt", "clap", "clap-markdown", + "clap_complete", "hive-sh4re", "libc", "listenfd", diff --git a/Cargo.toml b/Cargo.toml index bbcbb2f1..3fdc0642 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ axum = { version = "0.8", features = ["ws"] } base64 = "0.22" bcrypt = "0.19" clap = { version = "4", features = ["derive"] } +clap_complete = "4" hive-sh4re = { path = "hive-sh4re" } tower-http = { version = "0.6", features = ["fs"] } rmcp = { version = "1.7", default-features = false, features = [ diff --git a/docs/tools/hivectl-cli.md b/docs/tools/hivectl-cli.md index 8587c403..db24e9a9 100644 --- a/docs/tools/hivectl-cli.md +++ b/docs/tools/hivectl-cli.md @@ -24,6 +24,7 @@ This document contains the help content for the `hivectl` command-line program. * [`hivectl stop`↴](#hivectl-stop) * [`hivectl start`↴](#hivectl-start) * [`hivectl restart`↴](#hivectl-restart) +* [`hivectl completions`↴](#hivectl-completions) ## `hivectl` @@ -41,6 +42,7 @@ Sibling to the `hive-c0re` daemon binary. Covers host-side admin operations that * `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 ` (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 `). 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 `). If the stop phase reports a failure the start phase is skipped so the operator can investigate. Requires the hive-c0re daemon +* `completions` — Generate a shell completion script for `hivectl` and print it to stdout ###### **Options:** @@ -350,6 +352,23 @@ Restart containers hive-wide — `stop` then `start` over the same scope. Bare ` +## `hivectl completions` + +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. + +**Usage:** `hivectl completions ` + +###### **Arguments:** + +* `` — Shell to emit completions for + + Possible values: `bash`, `elvish`, `fish`, `powershell`, `zsh` + + + +
diff --git a/flake.nix b/flake.nix index db3ac654..e511c5b0 100644 --- a/flake.nix +++ b/flake.nix @@ -163,11 +163,27 @@ # to that one check — `nix flake check` still exercises them. default = craneLib.buildPackage { src = cleanSrc; - inherit cargoArtifacts nativeBuildInputs; + inherit cargoArtifacts; + # `installShellFiles` provides `installShellCompletion` for the + # postInstall below; appended (not in the shared set) so it's a + # build input only of this binary derivation. + nativeBuildInputs = nativeBuildInputs ++ [ pkgs.installShellFiles ]; pname = "hyperhive-workspace"; version = "0.1.0"; meta.description = "hyperhive workspace (hive-c0re, hive-ag3nt, hive-root)"; doCheck = false; + # Ship hivectl shell completions in the package (the binary's own + # `completions ` verb is the single source of truth, so they + # never drift from the actual verbs). Lands at + # `$out/share/{zsh/site-functions,bash-completion,fish}/…`; an + # operator gets working completion as soon as hivectl is in their + # system/user profile with the shell's completion enabled. + postInstall = '' + installShellCompletion --cmd hivectl \ + --bash <("$out/bin/hivectl" completions bash) \ + --zsh <("$out/bin/hivectl" completions zsh) \ + --fish <("$out/bin/hivectl" completions fish) + ''; }; # Bundled browser assets — see ./nix/frontend.nix. Output is # $out/{dashboard,agent}/ which the Rust binaries serve via diff --git a/hive-c0re/Cargo.toml b/hive-c0re/Cargo.toml index 867691a4..3cbadf1a 100644 --- a/hive-c0re/Cargo.toml +++ b/hive-c0re/Cargo.toml @@ -12,6 +12,7 @@ base64.workspace = true bcrypt.workspace = true reqwest.workspace = true clap.workspace = true +clap_complete.workspace = true clap-markdown = "0.1" hive-sh4re.workspace = true libc.workspace = true diff --git a/hive-c0re/src/bin/hivectl.rs b/hive-c0re/src/bin/hivectl.rs index 618258c0..38c6c893 100644 --- a/hive-c0re/src/bin/hivectl.rs +++ b/hive-c0re/src/bin/hivectl.rs @@ -157,6 +157,18 @@ enum Cmd { /// hand-maintained command list to drift out of date. #[command(hide = true)] MarkdownDocs, + /// 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. + Completions { + /// Shell to emit completions for. + shell: clap_complete::Shell, + }, } /// Shared scope flags for `hivectl stop` / `hivectl start`. With no flag @@ -441,9 +453,22 @@ async fn main() -> Result<()> { print!("{}", clap_markdown::help_markdown::()); Ok(()) } + Cmd::Completions { shell } => { + generate_completions(shell); + Ok(()) + } } } +/// Emit a shell completion script for `hivectl` to stdout. Walks the clap +/// command tree (the single source of truth — same tree `markdown-docs` +/// renders) so completions never drift from the actual verbs/flags. +fn generate_completions(shell: clap_complete::Shell) { + use clap::CommandFactory as _; + let mut cmd = Cli::command(); + clap_complete::generate(shell, &mut cmd, "hivectl", &mut std::io::stdout()); +} + /// True when `name` matches an existing hyperhive agent — i.e. it has a /// persistent state dir under `/var/lib/hyperhive/agents/`. We use the /// state dir (not the live container list) so kept-state tombstones