hyperhive/hive-forge
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-26 20:57:44 +02:00
..
src docs(hive-forge): add the missing # Errors section on fetch_combined_in 2026-07-26 19:48:23 +02:00
Cargo.toml feat(#2529): bump reqwest 0.12 -> 0.13 2026-07-16 17:03:38 +02:00
README.md docs: add missing readmes for hive-c0re, hive-forge, hivectl 2026-07-26 20:57:44 +02:00

hive-forge

Typed CLI wrapper around the in-cluster Forgejo's REST API. Replaces the prior bash script (hive-forge-tools.nix) so that agents and operators get the same error handling, exit codes, and JSON shapes regardless of how the bash mood was that day — this is the only supported path to the forge from inside an agent container; never curl it directly.

Single binary, one verb subcommand per forge operation (issues, PRs, comments, labels, reviews, CI status, attachments, triage). Reads credentials from the environment: HIVE_FORGE_URL (base URL), HIVE_FORGE_REPO (default repo), HYPERHIVE_STATE_DIR (state dir — forge-token lives here). The global -f/--forge <label> flag retargets a dashboard-provisioned external forge account instead, reading forge-<label>-token + forge-<label>.json from the state dir rather than the internal-forge pair.

When to use it

Reach for this crate when you're adding a new forge verb or changing how an existing one behaves — it's the single place issue/PR/comment/ CI logic lives for every agent and hivectl. If you're instead adding a tool an agent's claude session calls, that's hive-agent-mcp wrapping a shellout to this binary, not new logic here.

Shape

  • verbs/ — one module per subcommand, each exposing a clap-derived Args struct and a run(&Client, Args) -> Result<()> fn. Splitting one verb per module keeps each handler small and avoids the bash script's monolithic case statement. Notable ones:
    • lint.rslint <subcommand> triage queries (unassigned, no-reviewer, stale-branches, assignments), always JSON-able via the global --json flag.
    • pr_status.rs — the merge-readiness verdict command (pr-status --pr <n> / --sha <commit>); its exit code IS the verdict, not just a report.
    • comment.rs / comments.rs — post (refuses on unread thread activity) / read (marks forge's own notification read as a side effect) — see notify.rs for why that's safe to rely on.
  • client.rs — the app-level Forgejo client wrapper. Identity is the per-agent token under ${HYPERHIVE_STATE_DIR}/forge-token. REST calls go through the typed forgejo_api::sync::Forgejo client (Client::api); a minimal raw reqwest client remains for the few web-router routes Forgejo doesn't serve under /api/v1/ (attachment downloads, Actions artifact/log routes).
  • notify.rs — the read-before-comment guard, backed by forge's own notification read-state rather than a local mirror (which would drift across container restarts). "Is there unread activity here?" is just "does forge still have an unread notification for this thread?" — forge is the single source of truth.
  • body.rs — body-input resolution shared by every verb that posts a body: exactly one source between --body, --body-file, and piped stdin (matches the old bash resolve_body helper); passing both --body and --body-file is a clear error.

Full verb reference (with worked examples): docs/tools/forge.md.