indrasvat/gh-hound · Archived

gh-hound

Use gh-hound's structured GitHub Actions CI surface for agent workflows: inspect runs, detect failures, watch fail-fast, parse JSON failure triage (job, step, exit_code, log_excerpt), and branch on gh-hound exit codes instead of screen-scraping the TUI.

First seen Jun 15, 2026

Installation

$ npx skills add indrasvat/gh-hound --skill gh-hound

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License MIT
Default branch main
Open issues 1
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 13,760 B
  • docs SUMMARY.md 269 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 10 installs

SKILL.md

gh-hound

Use when inspecting GitHub Actions CI with gh hound — fix loops, PR checks, post-push verification. Always use the pipe surface; never screen-scrape the TUI or parse raw GitHub logs when failed[] is available.

Commands

gh hound runs --no-tui --json                    # current branch's runs
gh hound runs --status failure --no-tui --json   # failure-focused loop
gh hound runs --all --no-tui --json              # all branches
gh hound runs --branch <ref> --no-tui --json     # explicit branch/ref when local branch is wrong
gh hound runs -R owner/repo --no-tui --json      # outside a checkout
gh hound watch --json                            # active run, fail-fast
gh hound watch --group --no-tui                  # whole event group, NDJSON, blocks until the hunt settles
gh hound watch --group --no-tui --timeout 10m    # same, but bound the block (exit 3 + timed_out summary on expiry)
gh hound queue --run <run-id> --no-tui --json    # why is this run pending? concurrency-group blockers
gh hound queue --job <job-id> --no-tui --json    # diagnose a queued job through its parent run
gh hound queue --group <name> --no-tui --json    # inspect one active concurrency group, or report inactive
gh hound queue --groups --no-tui --json          # list active concurrency group summaries
gh hound runs --run <id> --attempt 2 --no-tui --json   # forensics on a re-run
gh hound artifacts --no-tui --json               # latest run's artifacts
gh hound artifacts --run <id> --download <name> --dir <path> --no-tui --json
gh hound approvals --run <id> --no-tui --json    # pending deploy gates (exit 1 = awaiting review)
gh hound approvals --run <id> --approve --env production --comment "lgtm" --no-tui --json
gh hound diff --workflow CI --no-tui --json      # who broke main? last green vs first bad
gh hound flakes --workflow CI --no-tui --json    # flaky or real? scored flake verdict
gh hound caches --no-tui --json                  # cache kennel vs the eviction cap
gh hound caches --delete-key <key> --ref <ref> --no-tui --json
gh hound workflows --no-tui --json               # workflow states (why did my cron stop?)
gh hound workflows --enable <id|path> --no-tui --json   # wake a disabled workflow

Runs are scoped to the current git branch by default. An empty branch-scoped runs[] can be a target mismatch, especially for release, tag-push, or branchless workflows. If the top-level diagnostic.kind is targetmismatch, follow diagnostic.nextcommands[]: widen with --all, pass --branch <ref>, inspect --run <id>, or use watch -R owner/repo --group --run <id> --timeout 10m for a bounded await. Do not conclude CI is absent until you have tried one of those target-correcting commands.

Exit Codes

  • 0: all selected runs green; continue.
  • 1: action needed; inspect runs[].failed[] and fix.
  • 2: API/network/config error; retry or report infrastructure failure, not CI failure.
  • 3: pending/running; wait and re-poll, or use watch.

watch --json is fail-fast: it exits 1 the moment the watched run turns red and includes the failure payload immediately.

watch --group --no-tui is the blocking/await mode: it streams the selected run's whole event group (same headsha + event) as NDJSON — one {type:"run", ts, runid, workflow, status, conclusion} line per state transition, closed by a {type:"summary", …, running, home, lost, timed_out} object — and blocks until the hunt settles. Exit 1 if any run is lost, 0 when the hunt comes home. (Plain watch --json without --group only snapshots the active run and exits 3 while pending — use --group to block.) Events are run-level only — drill into a single run with watch --json for job/step detail. Rehearse with --fake-scenario pack.

For unattended/background agents, bound the block with --timeout <duration> (e.g. --timeout 10m) so a queued or stuck run — or a hung GitHub call (the deadline bounds an in-flight poll too) — can't hang the watcher forever. On expiry the stream closes with a {…, "timedout":true} summary (still carrying live running members). Exit follows the same worst-outcome rule as a clean settle: 1 if any member is already lost, else 3 (still in flight). The timedout marker — not the exit code — is what tells a cut-short hunt from a settled one, so branch on the code as usual and read timed_out to know whether to re-poll. Without --timeout the block is unbounded (unchanged). --timeout requires --group; a negative duration is rejected.

Why Is It Pending? (queue)

If watch exits 3 or a run is pending, ask hound whether GitHub exposes a concurrency-group blocker before rerunning:

gh hound queue --run <run-id> --no-tui --json
gh hound queue --job <job-id> --no-tui --json
gh hound queue --groups --no-tui --json

Branch on decision.action:

  • wait (exit 3): a named concurrency group has live members ahead; do not rerun blindly.
  • inspectgatesor_runner (exit 0): this pending state is not exposed as concurrency; check approvals, runner capacity, or normal watch.
  • normalwatch / listonly / unsupported (exit 0): informational or fallback path.
  • error (exit 2): validation/API/network/auth/render failure.

Rehearse with --fake-scenario queue --run 30433644 (blocked behind deploy-prod, exit 3).

Every queue envelope includes fetchedat. Treat --groups as a summary surface: it can include lastacquiredat, but absent activemember_count means hound did not fetch group members, not that the active group is empty.

JSON Shape

Top level: repo, branch, runs[], optional diagnostic. Each run: id, workflow, runnumber, event, headbranch, headsha, status, conclusion, createdat, html_url, failed[].

diagnostic appears only for actionable empty listings. For targetmismatch, branch on kind, read the human message, and execute one of nextcommands[] instead of silently stopping.

Each failed[] entry: job, step, exitcode, annotations[] (path, line, level, message), logexcerpt.

Artifacts: gh hound artifacts lists {id, name, sizeinbytes, expired, expires_at, digest} for a run (latest on branch when --run omitted); --download <name|id> extracts into <dir>/<artifact-name>/ and reports downloaded.path. Exit 0 success, 2 any error (expired artifacts are refused before download). Add --artifacts to runs for per-run artifact metadata (opt-in: paginated artifact-list calls per run, usually one).

Caches: gh hound caches reports usage (activesizeinbytes, activecount, capbytes — the repo's configured storage limit, 10 GB by default; usage can exceed it because eviction lags) plus caches[] (id, key, ref, sizeinbytes, lastaccessedat, createdat). When CI suddenly slows, check the kennel: usage near capbytes means LRU eviction is thrashing your keys. Evict with --delete-id <id> or --delete-key <key> [--ref <ref>] (reports deleted.deletedcount). Exit 0 deleted or listed, 2 anything else with typed error.kind (not_found when nothing matched). The default runs path never touches the cache API.

Triage degrades per job: when a job log has expired, logexcerpt is empty and exitcode falls back to 1, but job, step, and annotations are always present for every failed job. An empty failed[] on a red run means job details could not be listed — fall back to html_url.

Regression Boundary (diff)

When a workflow is red and the question is which commits turned it, do not bisect — the answer is in run history:

gh hound diff --workflow CI --no-tui --json

Branch on status: located (exit 1) means a regression exists — lastgood/firstbad are full run objects and suspectcommits[] ({sha, author, message}, capped at 50; totalsuspects is the full count) is the blame range, with compareurl for humans. green and inconclusive both exit 0 — read verdict for the hound's one-liner (trail went cold after 1,000 runs. means the page budget ran out; raise HOUNDDIFFMAXPAGES). Exit 2 carries error: {kind, message}. Runs count by their latest attempt: a failure rerun to green is green. A sound loop: diff --json -> if located, inspect first_bad with runs --run <id> --no-tui --json -> fix or rerun.

Rehearse with --fake-scenario regression (deterministic boundary, exit 1).

Flaky or Real? (flakes)

Before burning time on a red run, ask whether the failure is a known squirrel:

gh hound flakes --workflow CI --no-tui --json    # --workflow omitted follows the latest run

Branch on status (always the worst job verdict): flaky (exit 1) — the failure pattern is established, rerun --failed-only is the rational first move; suspect (exit 1) — one wobble on record, look at jobs[].evidence[] before deciding; clean (exit 0) — fresh scent, this failure is worth chasing as real; insufficient_data (exit 0) — under 5 signal runs and no evidence, treat as real. The decision recipe:

  1. runs --json exits 1 -> flakes --workflow <w> --json.
  2. status == "flaky" -> rerun --run <id> --failed-only --no-tui --json -> watch --json.
  3. status == "clean" (or insufficient_data) -> investigate failed[] for real; do not rerun blindly.
  4. status == "suspect" -> read evidence[] (attemptflip beats crossrunflap beats retrymask) and decide.

Scoring is documented and stable: 0.45 per attempt flip + 0.30 per cross-run flap + 0.20 per retry mask, capped at 1.0; >= 0.6 is flaky, any evidence is suspect. samplesize/window/runsscanned size the claim; signalsevaluated lists what was checked (retry masking is only detectable in runs that had a failed attempt — the call budget never blanket-downloads logs). Evidence comes from attempt job conclusions and logs, never annotations (the API only serves annotations for the latest attempt). An underfilled-but-flaky window still exits 1 — trust status, not samplesize.

Rehearse with --fake-scenario flaky (seeded flips + retry mask, exit 1).

Mutations

After diagnosing with runs --json, act without leaving the surface:

gh hound rerun --run <id> --failed-only --debug --no-tui --json   # rerun failures with debug logs
gh hound cancel --run <id> --no-tui --json                        # call a run off

action in the result is one of rerun | rerunfailed | rerunjob | cancel | force_cancel. Exit 0 means accepted; 2 means it did not happen (read error). A sound agent loop: exit 1 from runs -> inspect failed[] -> if transient, rerun --failed-only --debug -> watch --json.

Deployment approvals: a waiting run is gated on environment review. approvals --run <id> lists the gates (exit 1 while any await review, 0 when none); --approve/--reject with no --env reviews everything you can approve, --env <name> (repeatable) targets gates, --comment is optional (a blank one sends reviewed from gh-hound — the API requires the field). Refusals are typed: unknown environment -> validation, not a required reviewer -> permission. Add --approvals to runs for pending_environments on waiting runs (opt-in, one call per waiting run).

Workflow State (workflows)

When a scheduled workflow silently stops, check its state before debugging YAML: GitHub disables crons after 60 days of repo inactivity (disabled_inactivity).

gh hound workflows --no-tui --json     # [{id, name, path, state}]
gh hound workflows --enable ci.yml --no-tui --json

state is an open string; documented values are active, disabledmanually, disabledinactivity, disabledfork, deleted — branch on the ones you know, pass the rest through. Toggle by numeric id or workflow file path only (display names refuse as validation); only active ↔ disabledmanually/disabledinactivity flips are valid. A toggle is exactly one API call and reports the landing state in toggled.state. Exit 0 ok, 2 refused with error: {kind, field?, message} — this verb never exits 1 or 3. A sound loop: empty runs[] on a branch with a schedule -> workflows --json -> if disabledinactivity, --enable <path> -> re-poll runs.

Deterministic Scenarios

For testing agent behavior without live CI:

gh hound runs --no-tui --json --fake-scenario failure   # also: green, pending, empty, api_error, waiting, regression, flaky
gh hound runs --branch release/v1 --no-tui --json --fake-scenario empty   # emits target_mismatch

The JSON schema lives at internal/render/testdata/schema.json in the gh-hound repo; the mutation envelope is under $defs.mutationresult, the approvals envelope under $defs.approvalsresult, the queue verdict under $defs.queueresult, the regression verdict under $defs.diffresult, the caches envelope under $defs.cachesresult, the workflows envelope under $defs.workflowsresult, the pack stream under $defs.watchgroupevent / $defs.watchgroupsummary, and the flake verdict under $defs.flakes_result.

Guardrails

  • Never expose credentials, auth headers, or token-bearing URLs.
  • Prefer --json; use --format md or --format xml only for presentation/export.
  • Treat exit code 1 as CI failure evidence, not a broken gh-hound invocation.