Use after a GitHub PR is opened, or when the user asks to handle gemini-code-assist review feedback, run the Gemini review loop, fix Gemini comments, or re-request Gemini review. Waits, fixes, pushes, re-asks. Capped at 3 cycles.
How this skill is triggered — by the user, by Claude, or both
Slash command
/gh-gemini-review-loop:gh-gemini-review-loopThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill to run the full GitHub PR loop: after PR creation, wait for `gemini-code-assist` to finish reviewing, fetch unresolved actionable review threads, acknowledge the requested fixes, implement clear fixes, verify them, commit and push to the PR branch, and ask Gemini Code Assist to re-review the latest revision.
Use this skill to run the full GitHub PR loop: after PR creation, wait for gemini-code-assist to finish reviewing, fetch unresolved actionable review threads, acknowledge the requested fixes, implement clear fixes, verify them, commit and push to the PR branch, and ask Gemini Code Assist to re-review the latest revision.
Prefer thread-aware review data over flat PR comments. GitHub review threads preserve isResolved, isOutdated, file paths, line anchors, and diff hunks, which are necessary for reliable automation.
Each Gemini review thread is in one of these states. The fetch script tags each thread accordingly, and the stop logic consumes the tag:
RESOLVED — Gemini or the maintainer has explicitly resolved the thread. Skip.OUTDATED — The line anchor has moved out from under the thread (the code Gemini commented on no longer exists at that position). Auto-resolved by the script. Skip.ADDRESSED_BY_REPLY — Unresolved, but the current user (or another maintainer) has posted a substantive reply (≥30 chars, not a bot, not a token "ack"). Treated as a human decision to defer/wontfix; the loop does not try to fix this thread again. The script auto-resolves these on the next pass via GraphQL (see "GitHub Write Safety" below). Opt out with --no-resolve-addressed-by-reply.UNRESOLVED — Actionable. Drives the next fix attempt.A thread can transition UNRESOLVED → ADDRESSED_BY_REPLY → RESOLVED (reply + auto-resolve), or UNRESOLVED → fixed in code → OUTDATED → RESOLVED (line moves out, auto-resolved).
A cycle is one @gemini-code-assist please review re-review request posted by the agent after Gemini's initial review.
repos/.../pulls/comments/{id}/replies do NOT count as a cycle.@gemini-code-assist does not consume a cycle. The script auto-detects the agent's GitHub login via gh api user; override with --agent-login NAME or opt out with --no-agent-filter.Gemini prefixes inline review comments with a markdown image whose alt text is the severity (critical / high / medium / low). The script parses this and orders actionable threads critical → high → medium → low → unknown, so high-severity findings are reported and fixed first. The severity tag also appears in the per-thread markdown header, e.g. ## 1. src/auth.py:42 [high].
Pass --post-receipt to leave a one-comment audit trail on the PR after the loop runs: cycles used, threads resolved (outdated + addressed-by-reply), threads still pending, and severity breakdown of remaining actionable threads. Use --dry-run --post-receipt to preview the receipt without posting.
For richer visibility while the loop is in flight, use --sticky-receipt instead. It maintains one comment per PR that the script edits in place across loop invocations. State persists in ~/.config/gh-gemini-review-loop/state.json (override with GGRL_STATE_DIR env var).
RUNNING, stores its id locally.--receipt-status {running,done,stopped}. Default is RUNNING for sticky receipts.--receipt-status done (or stopped) so the user sees the loop has finished.When --sticky-receipt is appropriate: long-running interactive loops where the user is watching the PR tab, not the chat. Always paired with --receipt-status running at cycle start, done at clean exit, stopped at stop-condition.
When the one-shot --post-receipt is appropriate: scripted/batch contexts where each invocation is independent and you want a fresh audit comment per run.
While the loop is running, the agent MUST emit one-line status updates to the user-facing chat at each phase transition. The format is [loop] cycle N/3 — <phase>. This is the cheapest user visibility — no code path, just instructions to the agent.
Required narration points:
| Phase | Narration line |
|---|---|
| Before script fetch | [loop] cycle N/3 — fetching threads from PR #<num>... |
| After fetch, before fixes | [loop] cycle N/3 — <K> actionable thread(s) (severity: <breakdown>). Fixing. |
| After fix attempt, before verify | [loop] cycle N/3 — fixes applied. Verifying. |
| After verify | [loop] cycle N/3 — verified (<test summary>). |
| Before push | [loop] cycle N/3 — committing and pushing <commit-sha>... |
| After push, before re-review | [loop] cycle N/3 — pushed. Requesting Gemini re-review (cycle N consumed). |
| Stop condition triggered | [loop] STOP — <stop-condition>: <one-line explanation>. |
| Loop complete (all clean) | [loop] DONE — 0 actionable threads remaining. Cycles used: N/3. |
Skip narration only when running in pure non-interactive batch mode (e.g. gh pr create chained into a script that captures output for later — but in Claude Code interactive sessions, never skip).
Rationale: in interactive Claude Code sessions, the user is watching the chat. Silent loops feel broken even when they're working. One line per phase is the right cadence — enough to show progress without burying signal.
When the user explicitly wants visibility outside the chat (e.g. they'll step away from the terminal, or other reviewers will look at the PR while the loop runs), pair the chat narration with --sticky-receipt. See Sticky receipt above.
When the user phrases the request differently, dispatch to the right flag combination. This table is authoritative; if a phrasing isn't here, fall back to defaults.
| User intent | Phrasing examples | Pass to script |
|---|---|---|
| Default loop | "run the gemini loop" / "handle gemini feedback" / "yeet this PR" | (no extra flags) |
| High-severity only | "only fix high severity" / "skip the nits" / "just the important stuff" | --min-severity high |
| Medium and above | "skip low-priority comments" | --min-severity medium |
| Critical only | "just the critical findings" | --min-severity critical |
| Strict severity filter | "only what Gemini flagged as high — ignore unmarked" | --min-severity high --drop-unknown-severity |
| Audit-only | "summarize Gemini comments" / "read-only review" / "show me what's pending" | --dry-run --post-receipt --no-resolve-outdated --no-resolve-addressed-by-reply |
| More cycles | "be persistent" / "do 4 cycles" | --max-rereview-requests 4 |
| Fewer cycles | "one cycle only" / "don't loop, just fix once" | --max-rereview-requests 1 |
| Specific PR | "handle PR https://github.com/..." | --pr <URL> |
| Different bot login | "handle review comments from google-gemini-code-assist" | --author google-gemini-code-assist |
| Post status without acting | "leave a status comment without touching anything" | --post-receipt --no-resolve-outdated --no-resolve-addressed-by-reply |
| Live status comment | "show me a live status comment on the PR" / "I want background visibility" | --sticky-receipt --receipt-status running per cycle; --sticky-receipt --receipt-status done at the final invocation |
| History investigation | "show me all Gemini threads ever, including resolved" | --include-resolved --include-outdated --include-addressed-by-reply --no-resolve-outdated --no-resolve-addressed-by-reply |
If the user explicitly opts out of any default behavior (e.g. "don't auto-resolve anything"), respect it for the rest of the session via --no-resolve-outdated --no-resolve-addressed-by-reply.
This skill does NOT support multi-bot loops (CodeRabbit, Copilot, etc.). It is opinionated for gemini-code-assist only. If the user asks for a different bot, change --author, but severity parsing and addressed-by-reply heuristics are calibrated for Gemini's output format.
Stop the loop and report status instead of pushing or asking Gemini again when any condition is true:
UNRESOLVED actionable Gemini threads after stale-thread cleanup.UNRESOLVED threads are informational, duplicate, contradictory, or require a human product/design/security decision.If a thread was deliberately deferred via a substantive reply (state ADDRESSED_BY_REPLY), treat it as condition 3 (human decision), not condition 5 (no progress). The loop must not re-try the same fix on the same thread cycle after cycle.
Do not run more than 3 fix/re-review cycles per PR. If the loop stops because the cap is reached, summarize the latest unresolved actionable comments and leave the PR for a human decision.
The skill is meant to auto-trigger after gh pr create. If the agent forgets — e.g., the workflow that created the PR ended the turn at the PR URL without chaining into this skill — the loop must be invoked retroactively at the next opportunity:
gemini-code-assist is not a configured reviewer on the repo.If the agent pushes new commits to a PR branch after the loop has already stopped:
UNRESOLVED or ADDRESSED_BY_REPLY threads, automatically resume the loop (subject to the 3-cycle cap).Doc-only commits (README, CLAUDE.md, comments) never resume the loop on their own.
Trigger the loop by default after PR creation.
Resolve the PR.
gh auth statusgh pr view --json number,url,headRefName,baseRefNameWait for Gemini to finish its first review.
scripts/fetch_gemini_threads.py --wait from this skill.Check loop status and clean stale threads.
@gemini-code-assist to review again.--no-resolve-outdated.Fetch Gemini review threads.
gemini-code-assist.Acknowledge what needs to be fixed.
Classify comments.
Implement fixes.
Verify.
Commit, push, and request re-review.
fix: address Gemini Code Assist review.@gemini-code-assist please review the latest changes.From any repository with a GitHub PR:
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py"
By default this resolves unresolved outdated Gemini threads AND addressed-by-reply threads (unresolved threads where a non-bot maintainer posted a substantive reply, >=30 chars) before printing current feedback, unless the PR has already reached the 3 re-review request cap.
Useful options:
# Wait for Gemini review activity to appear and settle
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" --wait
# Read-only fetch (no GraphQL mutations)
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" \
--no-resolve-outdated --no-resolve-addressed-by-reply
# Dry-run all resolutions (logs intended writes to stderr without calling GraphQL)
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" --dry-run
# Specific PR URL
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" --pr https://github.com/OWNER/REPO/pull/123
# JSON for automation
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" --format json
# Include outdated, resolved, or addressed-by-reply threads while investigating history
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" \
--no-resolve-outdated --include-outdated --include-resolved --include-addressed-by-reply
# Use a different bot login
python3 "$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py" --author google-gemini-code-assist
The script emits warning: ... hit page limit ... to stderr if any GraphQL page maxes out (review threads, reviews, PR comments, or comments within a thread), indicating older items may be silently missing.
This skill's default full loop includes committing, pushing, asking Gemini for re-review, and resolving outdated Gemini threads after PR creation or when the user asks for the Gemini loop.
Resolution policy:
scripts/fetch_gemini_threads.py via is_addressed_by_reply and resolved through the same GraphQL mutation as outdated threads. This prevents the same thread from re-tripping the loop forever after a deliberate deferral. Skip if the user has said "don't resolve" earlier in the session (pass --no-resolve-addressed-by-reply).For any uncertain run, prefer --dry-run first: the script logs [dry-run] would resolve <kind> <thread-id> to stderr without calling GraphQL. Useful when debugging the reply-detection heuristic against a real PR.
Stop before publishing if the fixes are ambiguous, tests expose a regression, local unrelated changes make it unsafe to commit cleanly, or the PR has already reached the 3 re-review request cap.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub orenashkenazy/gh-gemini-review-loop --plugin gh-gemini-review-loop