# hive-forge CLI `hive-forge` is the Forgejo API wrapper available in every agent container (installed via `harness-base.nix`; lives in `/hive-forge` as a proper Rust binary). Use it instead of ad-hoc curl pipelines. ## Credentials and repo defaults - Credentials: `$HYPERHIVE_STATE_DIR/forge-token` - Default repo: `$HIVE_FORGE_REPO` - Per-invocation override: global `-r/--repo` flag ## Verbs **Kind-namespaced commands (preferred):** issue/PR operations are grouped under `issue` and `pr` parent commands — `hive-forge pr close 42`, `hive-forge issue create --title …`, `hive-forge pr status --pr 42`. The `pr ` / `issue ` forms validate the number's kind (e.g. `pr close` refuses an issue number, which the old generic `close` couldn't). Run `hive-forge pr --help` / `hive-forge issue --help` for the full subcommand list (show/create/edit/status/merge/reviews/commits/diff/view/comment/ comments/close/labels/assign/timeline as applicable). The flat forms below (`close 42`, `pr-create …`, `pr-status …`, …) still work as **hidden back-compat aliases** during the transition and are dropped from `--help`; prefer the namespaced form. They'll be removed in a later sweep. ```bash hive-forge pr close 42 # close a PR (kind-validated) hive-forge issue close 42 # close an issue (kind-validated) hive-forge pr status --pr 42 # PR health (mergeable / CI / reviews) hive-forge issue create --title "..." --body "..." # --- flat aliases below remain valid (hidden) --- hive-forge view 42 # title + body + comments (marks thread read) hive-forge comments 42 # list all comments (human-readable; marks thread read) hive-forge comments 42 --tail 10 # last 10 comments (count-then-page; efficient on long threads) hive-forge --json comments 42 # same as above, JSON array (global flag) hive-forge comment 42 --body "..." # post comment (inline body) hive-forge comment 42 --body-file - < # CI-only fast path for an explicit commit sha hive-forge pr-merge 42 # merge (refuses unless mergeable + CI not red + no changes-requested); deletes head branch hive-forge pr-merge 42 --method rebase # rebase-merge instead of a merge commit (no squash option) hive-forge pr-merge 42 --keep-branch --force # keep the head branch; override the readiness gate hive-forge timeline 42 # audit trail: closes, label changes, assignments, commit refs hive-forge attach-issue 42 /path/to/file # upload a file attachment to an issue; prints download URL hive-forge attach-comment 18042 /path/to/file # upload a file attachment to a comment; prints download URL hive-forge attachment-get # download an attachment; prints resolved path to stdout hive-forge artifact-get pr1ma-paper-pdf --run 51 # download a CI run's Actions artifact zip (run number from the run-page URL) hive-forge ci-log --run 51 # print a CI run's job step logs (run number from the run-page URL); --job i / --step i to narrow hive-forge subscription --watch # subscribe to repo notifications hive-forge subscription --unwatch # unsubscribe hive-forge -r internal/knowledge clone # clone with creds auto-injected hive-forge -r internal/knowledge pr-create --agit --topic foo --title "..." # open PR via AGit (no fork) ``` ### Contributing to a read-only repo (`clone` + `pr-create --agit`) Agents are read-only collaborators on some repos (e.g. `internal/knowledge`) and so can't push branches. Forgejo's AGit flow lets a read-only user open a PR by pushing the current `HEAD` to the magic ref `refs/for//`. Two verbs cover the workflow: ``` hive-forge -r internal/knowledge clone # clone with token auto-injected cd knowledge # add / edit / delete any files, then commit normally git add -A && git commit -m "add foo runbook" hive-forge -r internal/knowledge pr-create --agit \ --topic foo-runbook \ # groups pushes into ONE PR; reuse to update it --title "add foo runbook" \ [--body "details"] # PR description (also accepts --body-file) ``` `clone` derives the dest dir from the repo basename (override with a positional arg); `--branch` / `--depth` are passed through. The token is injected into the clone's `origin` remote so `pr-create --agit` (default remote `origin`) can push without re-auth. `pr-create --agit` prints the PR URL. Re-running with the same `--topic` force-updates the existing open PR (the AGit ref is agent-owned scratch). Opens a reviewable PR the operator merges — never commits straight to `main`. `hive-forge --help` prints the full signature for any verb. ### `pr-status` One-stop PR health view (`--pr `): mergeable state, CI checks, requested reviewers + review verdicts, and the last-comment timestamp — the things you need to know whether a PR is ready to merge (CI must pass before merge). `--sha ` is a CI-only fast path for a raw commit. A failing/erroring CI context prints its job link. The process exit code is a **merge-readiness** verdict for `--pr` (0 only when CI is green AND the PR is mergeable AND no review requests changes), so it composes: `hive-forge pr-status --pr 42 && echo ready`. `--sha` mirrors the CI verdict alone. ``` hive-forge pr-status --pr 42 # PR #42: feat(...): ... # state: open (mergeable: yes) # CI: e39a87ea3949: ✅ success (1 context(s)) # ✅ CI / nix flake check (pull_request): success — Successful in 1m50s # reviewers: (none requested) # reviews: ✅ argus: APPROVED # last comment: 2026-06-05T19:13:28+02:00 by argus ``` Note: review verdicts come from *formal* Forgejo reviews (the approve / request-changes API). Reviewers who post their verdict as a plain comment show under `last comment`, not `reviews`. ## Notes - **Read-before-comment guard:** `comment` refuses to post when forge still has an unread notification for the thread (i.e. someone commented since you last read it). This prevents accidentally replying to old activity without seeing the new context. Read the thread with `hive-forge view ` or `hive-forge comments ` (which mark the notification read and clear the block), or pass `--force` to skip the guard. - `comment --body "..."` with backticks in the body: always use `--body-file -` with a HEREDOC to avoid shell escaping issues. - `pr-create --push` also runs `git push forge ` and suppresses the post-push "Create a pull request" hint (we print the canonical URL ourselves). - `attachment-get` saves to `/tmp/forge-attachment-{uuid}` by default and prints the resolved path. Pass `-o -` to stream to stdout. - `artifact-get --run ` downloads a CI Actions artifact. `` is the run number from the run-page URL (`/actions/runs/`, which `pr-status` surfaces as a CI context's target_url). Forgejo 15 serves artifacts only via the web route, not REST, and that route is keyed by the run's internal global id, so the verb translates the run number first. Saves a zip to `/tmp/forge-artifact-.zip` by default; pass `-o -` to stream to stdout. - `ci-log --run [--job i] [--step i]` prints a CI run's job step logs. `` is the run number from the run-page URL (same value `artifact-get` takes; `pr-status` surfaces it as a CI context's target_url). Forgejo exposes no REST endpoint for job logs, so the verb drives the web run-view streamer the run page polls. `--job` selects the job within the run (0-based, default 0); `--step` narrows to one step. `act_runner` garbage-collects completed-run logs, so this is reliable for live + recently-finished runs; when logs are gone the verb says so rather than printing nothing. `--json` dumps the raw run-view response. - Do NOT use raw `curl` for forge access -- the CLI handles auth, error checking, and output formatting.