{"id":50259309,"url":"https://github.com/orenashkenazy/gh-gemini-review-loop","last_synced_at":"2026-05-31T10:00:53.842Z","repository":{"id":358956148,"uuid":"1243392760","full_name":"OrenAshkenazy/gh-gemini-review-loop","owner":"OrenAshkenazy","description":"Opinionated Gemini Code Assist PR review loop for Claude Code. Thread-state-aware, severity-filtered, 3-cycle cap, sticky-receipt visibility. No CI coupling.","archived":false,"fork":false,"pushed_at":"2026-05-27T06:54:57.000Z","size":172,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-27T08:26:25.826Z","etag":null,"topics":["claude-code-plugin","claude-code-skill","claude-skill","code-review","gemini","gemini-code-assist","plugin-marketplace","pull-request"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OrenAshkenazy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-19T09:50:31.000Z","updated_at":"2026-05-27T06:44:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/OrenAshkenazy/gh-gemini-review-loop","commit_stats":null,"previous_names":["orenashkenazy/gh-gemini-review-loop"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/OrenAshkenazy/gh-gemini-review-loop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OrenAshkenazy%2Fgh-gemini-review-loop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OrenAshkenazy%2Fgh-gemini-review-loop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OrenAshkenazy%2Fgh-gemini-review-loop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OrenAshkenazy%2Fgh-gemini-review-loop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OrenAshkenazy","download_url":"https://codeload.github.com/OrenAshkenazy/gh-gemini-review-loop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OrenAshkenazy%2Fgh-gemini-review-loop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33726719,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude-code-plugin","claude-code-skill","claude-skill","code-review","gemini","gemini-code-assist","plugin-marketplace","pull-request"],"created_at":"2026-05-27T08:01:25.572Z","updated_at":"2026-05-31T10:00:53.835Z","avatar_url":"https://github.com/OrenAshkenazy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gh-gemini-review-loop\n\n**Move faster through Gemini Code Assist PR feedback from Claude Code.**\n\n[![CI](https://github.com/OrenAshkenazy/gh-gemini-review-loop/actions/workflows/ci.yml/badge.svg)](https://github.com/OrenAshkenazy/gh-gemini-review-loop/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/OrenAshkenazy/gh-gemini-review-loop?sort=semver)](https://github.com/OrenAshkenazy/gh-gemini-review-loop/releases)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nBuilt for solo builders and small teams who want review feedback handled while they stay in flow. Claude waits for Gemini, reads real GitHub review-thread state, fixes actionable comments, verifies, pushes, and asks Gemini to re-review. It stops after 3 cycles so it cannot spam your PR.\n\n[Gemini Code Assist](https://github.com/apps/gemini-code-assist) gives you review comments. This plugin turns those comments into an interactive fix loop inside Claude Code: no dashboard hopping, no manual comment triage, no heavy process to adopt.\n\n---\n\n## Prerequisites\n\n- **Claude Code** with plugin support enabled.\n- **`gh` CLI** authenticated against the repos you'll run the loop on.\n- **Python 3.10+**.\n- **A repo where `gemini-code-assist` is configured as a reviewer.** This plugin is opinionated for Gemini Code Assist and does not aggregate other review bots.\n\n## Installation\n\nThis repo is a single-plugin Claude Code marketplace. Install in **two slash-commands**.\n\n### Step 1 — Add the marketplace\n\nIn your Claude Code prompt:\n\n```\n/plugin marketplace add OrenAshkenazy/gh-gemini-review-loop\n```\n\n### Step 2 — Install the plugin\n\n```\n/plugin install gh-gemini-review-loop@gh-gemini-review-loop\n```\n\nThat's it. The skill is now available to Claude Code.\n\nTo upgrade later (Claude Code uses `/plugin update` for installed plugins, distinct from `/plugin marketplace add` which only manages catalogs):\n\n```\n/plugin update gh-gemini-review-loop\n```\n\n---\n\n## See It Before You Install\n\n![Terminal demo of gh-gemini-review-loop handling Gemini Code Assist feedback](docs/gh-gemini-review-loop-demo.gif)\n\nThe demo shows the whole happy path: `gh pr create`, Gemini comments appearing, Claude running the loop, the thread-aware fetcher surfacing actionable feedback, fixes, tests, push, and a re-review request.\n\n\n## Use It\n\nFrom a repo with an open GitHub PR, say this to Claude:\n\n\u003e Run the Gemini loop\n\nClaude will:\n\n1. Wait for Gemini Code Assist to finish reviewing.\n2. Fetch unresolved, actionable Gemini review threads.\n3. Ignore stale, resolved, duplicate, or already-addressed threads.\n4. Fix clear issues.\n5. Run relevant checks.\n6. Commit and push to the PR branch.\n7. Ask Gemini to re-review.\n8. Stop once the PR is clean, a human decision is needed, or 3 re-review cycles have been used.\n\nYou can also use more specific prompts:\n\n| Say this to Claude | What happens |\n|---|---|\n| *\"Run the Gemini loop\"* | Full loop with defaults |\n| *\"Only fix high-severity Gemini findings\"* | Skips lower-severity findings |\n| *\"Just audit Gemini comments, don't touch anything\"* | Read-only inspection |\n| *\"One cycle only\"* | Fixes once, then stops |\n| *\"Show a live status comment on the PR\"* | Maintains one edited status comment on the PR |\n| *\"Run the Gemini loop with judge eval at completion\"* | After the loop stops, OpenAI classifies any remaining Gemini findings as fix / reply / ignore / escalate, so you know whether to keep working or stop |\n\nThe skill also triggers naturally when Claude opens a PR and you ask it to keep going, handle review feedback, fix Gemini comments, or request Gemini re-review.\n\n---\n\n## Why This Plugin\n\nRun the full GitHub PR feedback loop with [Gemini Code Assist](https://github.com/apps/gemini-code-assist): wait for Gemini's review, fetch unresolved actionable threads, classify, fix, verify, commit, push, request re-review. Repeat up to a 3-cycle cap.\n\n**Why this is safer than a naive Gemini comment scraper:**\n\n- **Thread-state-aware.** Uses GitHub's `reviewThreads` GraphQL (with `isResolved` / `isOutdated`) instead of the flat REST endpoint, so it actually knows what's actionable vs already-handled.\n- **`ADDRESSED_BY_REPLY` detection.** Maintainer replied *\"wontfix because X\"*? The loop honors that — never re-tries the fix and auto-resolves the thread so it stops re-appearing every cycle.\n- **Severity-aware ordering + filtering.** Parses Gemini's `critical` / `high` / `medium` / `low` priority markers. Sorts fixes by severity. Filter with `--min-severity high` to skip nits.\n- **Hard 3-cycle cap, counted by the agent.** Only the agent's own re-review pings consume cycles (humans pinging Gemini don't burn cycles). Prevents runaway PR spam — a known failure mode of naive loops.\n- **`--dry-run` for every write.** All GraphQL mutations route through one choke point that can log intended writes without executing.\n- **Sticky receipt for background visibility.** `--sticky-receipt` posts one comment per PR that gets edited in place as the loop progresses, so PR watchers see live phase status (`RUNNING` → `DONE`) without comment spam.\n\nSee [`SKILL.md`](plugins/gh-gemini-review-loop/skills/gh-gemini-review-loop/SKILL.md) for the full workflow definition, stop conditions, and all variation phrasings.\n\n---\n\n## Optional: Per-Finding OpenAI Judge\n\nEnd users can opt into an OpenAI-powered judge that labels each Gemini finding as `valid_actionable` / `false_positive` / `needs_human` / `explanation_only` / `duplicate` / `already_addressed`, plus a `severity_override` and `recommended_action`. The label appears next to each finding in the loop output.\n\n- **Default: off.** Nothing is sent to OpenAI until you opt in.\n- **Privacy boundary:** when enabled, finding bodies and diff hunks are sent to the OpenAI API. The judge is read-only. It never resolves threads, posts comments, or pushes.\n- **Cost:** `gpt-4o-mini` is about $0.001 per finding. A typical `on_complete` run is about $0.005 per PR.\n- **Discoverability:** on your first loop with findings, the agent shows a one-time tip: `[loop] Tip: judge eval can give a second opinion on these findings.`\n- **Natural language:** say \"run the Gemini loop with judge eval at completion\" or \"with judge eval on every cycle\". Preference is saved automatically.\n- **Explicit setup:** say \"enable judge eval\" to get a mode prompt with all options.\n- **Requires:** `OPENAI_API_KEY` env var + `pip install openai`. Missing either means the judge skips gracefully and the loop continues unchanged.\n\n### Judge eval TL;DR\n\n1. Set `OPENAI_API_KEY` once (see [Setting your API key](#setting-your-openai_api_key) below).\n2. Say one of these to Claude:\n\n   \u003e *\"Enable judge eval\"* — Claude prompts you to pick a mode and saves it.\n   \u003e\n   \u003e *\"Run the Gemini loop with judge eval at completion\"* — saves and runs in one step.\n\nThat's it. Claude handles the config file.\n\n### Configuring it yourself\n\nPrefer editing a config file over talking to Claude? Edit (or create) `~/.config/gh-gemini-review-loop/preferences.json`:\n\n```json\n{\n  \"judge_mode\": \"on_complete\",\n  \"judge_model\": \"gpt-4o-mini\"\n}\n```\n\n| `judge_mode` value | When the judge runs |\n|---|---|\n| `off` (default) | Never. Nothing is sent to OpenAI |\n| `on_complete` | Once, after the loop finishes — cheapest signal |\n| `on_cycle` | Every fix cycle — more frequent, ~3× the cost |\n\n**To reset:** delete the file. Next run re-creates it with `judge_mode: off`.\n\n### Setting your `OPENAI_API_KEY`\n\nThe judge needs an OpenAI key. The key must be visible to subprocesses that Claude spawns — `~/.zshrc` is **not** enough, since subprocesses don't source it. Use `~/.zshenv` instead.\n\n**macOS (one-time, key stored in Keychain — never sits in a plaintext file):**\n\n```bash\nsecurity add-generic-password -a \"$USER\" -s \"openai-api-key\" -w \"sk-...\"\necho 'export OPENAI_API_KEY=$(security find-generic-password -a \"$USER\" -s \"openai-api-key\" -w 2\u003e/dev/null)' \u003e\u003e ~/.zshenv\n```\n\nRestart Claude Code so the new env propagates.\n\n**Self-hosted endpoints** (Ollama / LiteLLM / LM Studio / enterprise gateway): also set `OPENAI_BASE_URL` and the SDK will use that endpoint. Key-shape validation is bypassed automatically.\n\n### Verify your setup\n\nIf judge eval isn't working, run the doctor — it diagnoses every common failure (missing key, placeholder injected by `~/.claude/settings.json`, wrong Python, SDK not installed) and prints the exact fix:\n\n```bash\npython3 \"$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/judge_doctor.py\" --probe\n```\n\nSee [SKILL.md -\u003e Optional Judge Eval](plugins/gh-gemini-review-loop/skills/gh-gemini-review-loop/SKILL.md) for the full flow and verdict schema.\n\n---\n\n## Configuring the skill\n\nClaude Code skills don't have a settings UI. Configure via three layers, in order of dominance:\n\n1. **Natural-language prompts.** Say what you want; the agent picks the right script flags from [SKILL.md's Variations table](plugins/gh-gemini-review-loop/skills/gh-gemini-review-loop/SKILL.md). This is the idiomatic path.\n2. **`CLAUDE.md` preferences** for persistent per-user or per-repo defaults:\n   ```markdown\n   ## gh-gemini-review-loop preferences\n   - Always pass --min-severity medium (we don't care about Gemini's low nits).\n   - Always pass --post-receipt so we get an audit trail on every PR.\n   - Use --max-rereview-requests 4 for the API repo (we want one extra cycle).\n   ```\n3. **Direct CLI flags** when invoking the script manually. See `--help` for the full list.\n\nFor the optional OpenAI judge, see [Judge eval TL;DR](#judge-eval-tldr) — it has its own prefs file at `~/.config/gh-gemini-review-loop/preferences.json`.\n\n---\n\n## Advanced: Manual Script Invocation\n\nYou'll rarely need this, the skill drives the script for you, but it works for debugging.\n\n`$CLAUDE_PLUGIN_ROOT` is set **only inside Claude Code's plugin runtime** — it isn't exported to your interactive shell, so the variable-form below only works from a Claude session (e.g., a Bash tool call). To run from a plain terminal, locate the cached script path yourself:\n\n```bash\n# From a plain terminal — find the installed path (handles version bumps):\nSCRIPT=$(find ~/.claude/plugins/cache/gh-gemini-review-loop -name fetch_gemini_threads.py 2\u003e/dev/null | sort | tail -1)\n[ -n \"$SCRIPT\" ] \u0026\u0026 python3 \"$SCRIPT\" --wait || echo \"Error: fetch_gemini_threads.py not found — install the plugin first.\" \u003e\u00262\n\n# From inside a Claude Code session (the env var IS populated there):\npython3 \"$CLAUDE_PLUGIN_ROOT/skills/gh-gemini-review-loop/scripts/fetch_gemini_threads.py\" --wait\n\n# Notable flags:\npython3 \"$SCRIPT\" --dry-run                     # log writes without executing\npython3 \"$SCRIPT\" --post-receipt                # one-shot audit comment\npython3 \"$SCRIPT\" --sticky-receipt              # live, edited-in-place comment\npython3 \"$SCRIPT\" --min-severity high           # ignore Gemini's low/medium nits\npython3 \"$SCRIPT\" --drop-unknown-severity       # also ignore unmarked findings\npython3 \"$SCRIPT\" --no-resolve-outdated         # read-only inspection mode\npython3 \"$SCRIPT\" --include-resolved --include-outdated --include-addressed-by-reply   # full history\npython3 \"$SCRIPT\" --max-rereview-requests 4     # raise the 3-cycle cap\npython3 \"$SCRIPT\" --agent-login NAME            # override gh-detected agent login\npython3 \"$SCRIPT\" --author google-gemini-code-assist   # alternate bot login\n```\n\nRun `python3 \"$SCRIPT\" --help` for the complete list.\n\n---\n\n## How It Works\n\nThe script queries GitHub's `pullRequest.reviewThreads` via GraphQL, filters to threads authored by `gemini-code-assist`, partitions them into four states (`RESOLVED` / `OUTDATED` / `ADDRESSED_BY_REPLY` / `UNRESOLVED`), and surfaces only the actionable subset. The agent fixes those, commits, pushes, then posts `@gemini-code-assist please review the latest changes.` once per cycle — counted strictly against the agent's own GitHub login so humans can ping Gemini freely. After 3 such cycles, hard stop. See the [Stopping Conditions](plugins/gh-gemini-review-loop/skills/gh-gemini-review-loop/SKILL.md#stopping-conditions) section in SKILL.md for the full state machine.\n\n---\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n\n---\n\n## What I Want Feedback On\n\n- **Install friction:** where the Claude Code marketplace flow, `gh` auth, or Python dependency expectations feel unclear.\n- **False positives:** whether Gemini findings that survive filtering are usually worth acting on.\n- **Thread state handling:** whether `RESOLVED`, `OUTDATED`, `ADDRESSED_BY_REPLY`, and `UNRESOLVED` match how maintainers think about review comments.\n- **Safety around resolving outdated threads:** whether auto-resolving stale Gemini threads is acceptable by default, or should be more conservative.\n- **Whether judge eval is worth adding:** whether the optional OpenAI judge helps enough to justify the setup, privacy boundary, and small API cost.\n\n---\n\n## Contributing\n\nPRs welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the `release:*` label convention and the auto-release flow.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forenashkenazy%2Fgh-gemini-review-loop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forenashkenazy%2Fgh-gemini-review-loop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forenashkenazy%2Fgh-gemini-review-loop/lists"}