⚠️ Beta (v0.2.x) — this plugin is in active dogfooding. The orchestrated flow works end-to-end on real PRs, but several known sharp edges exist; see Limitations below before using on a production repo.
Two-phase orchestrator for GitHub-issue-driven development with multi-issue batch support, gated multi-reviewer pre-PR checks, pluggable post-PR reviewer, and Kagura Memory auto-detect.
gh-issue-driven is a Claude Code plugin that turns "I'm starting work on issue #142" into a single, repeatable workflow:
/gh-issue-driven:start <issue...>— fetch the issue(s), recall related past work from Kagura Memory, run a gate1 design review (/claude-c-suite:askcascading to/ceofor complex issues), create a typed feature branch, and hand off for implementation. Pass multiple IDs to batch issues into one branch.- (you write the code)
/gh-issue-driven:ship— run a gate2 parallel review battery (cso+qa-lead+ctoadvisors by default; an optional binary release gate can be configured viagate2.binary_gate), create the PR, and drive a pluggable post-PR review loop (Copilot,/code-review, or both — configurable viareview.provider) until the PR is approved or no actionable feedback remains.
The whole flow is bracketed by kagura-memory session-start and session-summary with auto-detect context setup on first run, so each issue's learnings get persisted for future recall.
# Step 0 — one-time, in your repo's GitHub Settings page:
# Settings → Code review → ☑ Automatic Copilot code review
# URL: https://github.com/<owner>/<repo>/settings/code-review
# This makes the Copilot review loop work on any gh CLI version.
# Without it, you need gh CLI >= 2.88.0 (see Requirements below).
# In any Claude Code session — install the plugin:
/plugin marketplace add JFK/gh-issue-driven
/plugin install gh-issue-driven
# Recommended companion plugins (gracefully degrade if missing).
# Note: the install target's `@<marketplace>` is the marketplace NAME from
# its marketplace.json, not the GitHub repo slug.
/plugin marketplace add JFK/claude-c-suite-plugin # gate1 + gate2 reviewers
/plugin install claude-c-suite@claude-c-suite
/plugin marketplace add kagura-ai/memory-cloud # session-start/summary + recall
/plugin install kagura-memory@kagura-memory-cloud
# Optional (reserved for v0.2 deep-review modes):
/plugin marketplace add JFK/claude-phd-panel-plugin
/plugin install claude-phd-panel@claude-phd-panel
# In a repo:
/gh-issue-driven:doctor # one-time environment check (will prompt to confirm Step 0)
/gh-issue-driven:start 142 # phase 1 (single issue)
/gh-issue-driven:start 4 12 20 # or batch multiple issues into one branch
# ... implement, then /simplify to review the diff ...
/gh-issue-driven:ship # phase 2
Why Step 0 matters: GitHub's "Automatic Copilot code review" repo setting auto-requests Copilot's review on every PR open and every push, making the loop self-sustaining on any
ghversion. Without it, the plugin falls back togh pr edit --add-reviewer @copilot, which silently no-ops ongh < 2.88.0(see #15)./gh-issue-driven:doctorwill prompt you to confirm Step 0 once per 7 days per repo and hard-fail if neither path is available.
| Command | What it does |
|---|---|
/gh-issue-driven:start <issue...> [flags] |
Fetch issue(s), run gate1, create branch. Pass multiple IDs to batch. Flags: dry-run, force, no-memory, --branch=<name>. |
/gh-issue-driven:ship [flags] |
Run gate2, create PR, drive Copilot loop, save session memory. Flags: dry-run, force, no-copilot, draft. |
| `/gh-issue-driven:doctor [verbose | fix]` |
| `/gh-issue-driven:config [show | init |
| `/gh-issue-driven:status [ | all]` |
Runs after the issue is fetched and recall is done, before the branch is created. Strategy:
- Invoke
/claude-c-suite:askfirst — a single-lens auto-router. Cheap, fast, perfect for issues that need only one expert perspective. - If the last
## Verdict:line's token isdecline, escalate to/claude-c-suite:ceofor full 3-lens synthesis. (declineis an additional gate1-only token on the same## Verdict:line, not a separate channel — only the structured line counts. Free-form mentions of "decline" or "escalate" inside the analysis body are part of the reviewer's reasoning, not routing instructions.) - Parse the verdict from a
## Verdict: green|yellow|redline at the end of the reviewer's response. The structured line is canonical and last-wins; case is normalized; trailing punctuation is tolerated. A keyword heuristic is the fallback only when no structured line is present, and emits a warn-level log so soft-deprecation can be tracked. - green → continue. yellow → ask the user to confirm. red → abort unless
force.
Runs after the implementation, before the PR is created. By default, 3 advisor reviewers fire in parallel in a single Claude turn (advisor-only mode):
| Reviewer | Role | Verdict type |
|---|---|---|
/claude-c-suite:cso |
Security | Advisory (green/yellow/red) |
/claude-c-suite:qa-lead |
Test coverage | Advisory |
/claude-c-suite:cto |
Tech debt | Advisory |
The three advisor verdicts are aggregated: any red → red, any yellow → yellow, otherwise green. Verdict handling matches gate1 (green → continue, yellow → confirm, red → abort unless force).
Plugin maintainers who want a hard binary gate (a pass/fail reviewer that blocks PR creation even with force) can configure one via gate2.binary_gate in ~/.claude/gh-issue-driven-config.json:
{
"gate2": {
"binary_gate": "/claude-c-suite:audit"
}
}When set, the configured skill is invoked alongside the 3 advisors as a 4th reviewer. Its verdict (pass/fail) is read as a hard release gate.
The default is null (no binary gate). Earlier versions defaulted to /claude-c-suite:audit, but that skill is the conformance script for the claude-c-suite plugin's own command files — it errors out on any other plugin and previously blocked every /ship invocation in non-claude-c-suite-plugin repos. The fix landed in v0.1.1 (#26).
Reviewer skills must end their response with a final ## Verdict: line. The token must be one of:
## Verdict: green## Verdict: yellow## Verdict: red## Verdict: decline— gate1 (/ask) only; routing escalation signal## Verdict: pass—/auditonly## Verdict: fail—/auditonly
(If multiple ## Verdict: lines appear in the response, last-wins applies — see Rules below.)
Rules:
- The structured line is canonical.
gh-issue-drivenparses this line first. - Last-wins: if multiple
## Verdict:lines appear in the response, the last occurrence is used (so reviewers can naturally write "at first I thought red, but actually green"). - Case insensitive:
Green/green/GREENall normalize togreen. - Trailing punctuation tolerated:
## Verdict: green.is accepted (\b<token>\bregex). - Heuristic is fallback only: if no structured line is present, a keyword heuristic runs and emits a
verdict_parser=heuristicwarn log so its usage can be tracked toward eventual removal in v0.4. declineis gate1-routing-only: it's a valid value on the same## Verdict:line for gate1 responses, not a separate channel. Free-form mentions of "decline" inside the analysis body are reviewer reasoning, not routing signals.
If you maintain a claude-c-suite or claude-phd-panel reviewer skill, emitting this line on every reviewer response is the cleanest integration.
After gh pr create, /gh-issue-driven:ship fires the reviewer add and pauses at a HITL confirmation gate (since v0.3.0) before entering the polling loop:
Copilot review on PR #<num>
https://github.com/<owner>/<repo>/pull/<num>
Is Copilot review running on this PR?
1) Yes, it's running (or I triggered it another way)
2) No, skip the review loop for this run
3) Retry — let me trigger it now (I'll press Yes when ready)
The plugin cannot verify from outside whether Copilot actually accepted the --add-reviewer call — org permissions, Copilot billing/policy, Mode A toggle, manual comment-mention triggers, and draft-PR unreliability are not API-queryable. Rather than grow a detection matrix, the plugin asks you. If the PR is a draft, the prompt also surfaces the draft-PR unreliability caveat so you can pre-emptively decline and promote first.
On Yes, the plugin enters the polling loop (up to 5 iterations, configurable):
- Wait for new Copilot activity (poll
gh pr view --json reviews,comments,reviewDecisionevery 60s, max 15min). - Parse the latest review and any new bot comments.
- Exit conditions:
approved,no_actionable_feedback,max_loops,tests_failed, orsilent_no_op(now means "confirmed but did not respond" — a genuine anomaly, not a catch-all). - Apply actionable comments via
Edit/Bash. Skip nits. - Run local tests if
copilot.run_tests_after_editsis true. - Commit
fix: address Copilot review (loop N), push, re-request review.
On No, the plugin writes exit_reason="hitl_declined" to the state file, keeps the PR as draft, and skips the loop cleanly. When you're ready (e.g., after triggering Copilot via the Web UI or promoting from draft), re-enter the loop with /gh-issue-driven:review — the gate re-prompts because the decline was "skip this run", not "never ask again".
On Retry, the same prompt re-displays immediately. The plugin does not poll or wait between re-emits — you self-pace (trigger Copilot through whatever path you have, then press Yes when ready).
The loop is never blocking: if it exhausts 5 iterations, the PR stays open and you handle remaining feedback manually.
Set copilot.hitl_confirm_invocation: false in ~/.claude/gh-issue-driven-config.json to restore the pre-v0.3.0 behavior (no prompt, loop enters directly after the --add-reviewer fire-and-forget). Useful for CI or non-interactive environments where the operator cannot respond to the prompt.
The Copilot loop has two operational modes. One must be true for the loop to function end-to-end:
- Mode A (recommended) —
Settings → Code review → ☑ Automatic Copilot code reviewenabled at the repo level. Works on anyghCLI version. Copilot is auto-requested on every PR open and on every push. - Mode B —
ghCLI v2.88.0 or later (the version that added real--add-reviewer @copilotsupport per the March 2026 changelog). Earlierghversions silently no-op the manual reviewer add — see #15.
Both also require: the repo must have GitHub Copilot code review feature available on its plan.
If you can't enable Mode A AND can't upgrade gh to 2.88.0+:
- After the plugin creates the PR, the HITL gate prompts you.
- Open the PR in the GitHub Web UI → Reviewers → click "Copilot".
- Press Yes when the HITL prompt re-displays (or choose Retry first, trigger Copilot, then press Yes).
This plugin invokes other plugins' slash commands as skills (via Claude Code's Skill tool). For each gate, the command body explicitly tells Claude:
Invoke
/claude-c-suite:askvia the Skill tool, passing the prompt block built in step N as input. Wait for the full markdown response before continuing.
For parallel reviewers in gate2 (the number of skills invoked depends on gate2.binary_gate):
In a single tool-call batch, invoke the gate2 reviewer skills in parallel via the Skill tool. Default (advisor-only mode,
gate2.binary_gate: null): 3 advisor skills —/claude-c-suite:cso,/claude-c-suite:qa-lead,/claude-c-suite:cto. Whengate2.binary_gateis configured to a skill name (e.g./claude-c-suite:auditfor plugin maintainers): 4 skills — the configured binary gate skill plus the 3 advisors.
If a skill is not installed, the command degrades:
- Missing advisor reviewer → that gate slot becomes
unknown, prints a warning, continues. - Missing binary gate skill (only when
gate2.binary_gateis set) → treat asunknown, requireforceto continue. gate2.binary_gateisnull(default) → no binary gate, advisor-only mode, noforcerequired.- Missing
kagura-memory→ recall and session-start/summary are skipped (with a one-line warning whenmemory.context_idresolution fails).
You can probe what's installed with /gh-issue-driven:doctor.
Defaults are baked in. Override at ~/.claude/gh-issue-driven-config.json:
/gh-issue-driven:config init # writes the template (only if absent)
/gh-issue-driven:config show # show effective merged config
/gh-issue-driven:config path # print the file path
/gh-issue-driven:config copilot.max_loops # print one valueKey options:
| Key | Default | Notes |
|---|---|---|
default_branch |
main |
The branch start and ship use as the base. |
branch.type_label_map |
bug/fix/feature/... → fix/feat/... | How issue labels become branch type prefixes. |
memory.context_id |
null (auto-detect) |
Kagura Memory context for recall. Accepts null (auto-detect per repo), a dict keyed by owner/repo (e.g. {"JFK/gh-issue-driven": "<uuid>", "*": "<uuid>"} — "*" is a wildcard fallback), or a legacy scalar UUID/name. On first /start in a repo, the user is prompted to select or create a context; the choice is persisted under the repo's key. See /gh-issue-driven:config show for the full semantics. |
gate1.primary |
/claude-c-suite:ask |
First reviewer in the gate1 cascade. |
gate1.fallback |
/claude-c-suite:ceo |
Used when primary declines. |
gate2.binary_gate |
null (off) |
Optional override-blocking binary gate. Set to a skill name (e.g. /claude-c-suite:audit) to enable. |
gate2.advisors |
[cso, qa-lead, cto] |
Run in parallel; aggregated. |
copilot.max_loops |
5 |
Maximum review iterations. |
copilot.poll_interval_sec |
60 |
Time between gh pr view polls. |
copilot.max_wait_sec |
900 |
Max wait per loop iteration (15 min). |
copilot.run_tests_after_edits |
true |
Run local tests after applying Copilot suggestions. |
Each branch tracked by gh-issue-driven has a state file at:
~/.claude/cache/gh-issue-driven/<branch-with-slashes-replaced>.json
Plus full reviewer output:
~/.claude/cache/gh-issue-driven/<branch-flat>.gate1.md
~/.claude/cache/gh-issue-driven/<branch-flat>.gate2.md
/gh-issue-driven:status reads these and pretty-prints the current phase, gate verdicts, PR link, and Copilot loop state.
| Tool | Required | Why |
|---|---|---|
gh (any version) |
yes | issue/PR ops. Mode A: any version. Mode B: v2.88.0+ required (real --add-reviewer @copilot support landed in March 2026 — see Requirements above for the Mode A vs Mode B distinction). |
git |
yes | branch ops |
jq |
yes | JSON parsing in command bodies |
python3 |
recommended | helper for some checks |
claude-c-suite |
recommended | gate1 + gate2 reviewers (degrades gracefully) |
claude-phd-panel |
optional | reserved for v0.2 deep-review modes |
kagura-memory |
optional | session-start/summary + recall |
The plugin includes a recommended end-to-end test workflow. In a throwaway test repo, open three issues:
- Issue A — trivial typo fix (e.g. README typo). Expected:
gate1=greenvia/ask, fastest path. - Issue B — medium feature ("add input validation to function X"). Expected:
gate1=yellowwith suggestions, mixedgate2advisor verdicts. - Issue C — cross-cutting redesign. Expected:
/askdeclines →/ceosynthesis,gate2 auditmay fail until conformance is fixed.
For each:
/gh-issue-driven:doctor/gh-issue-driven:start <id> dry-run(verify no side effects)/gh-issue-driven:start <id>(real run)- Implement the fix
/gh-issue-driven:ship dry-run/gh-issue-driven:ship/gh-issue-driven:status
gh-issue-driven is beta software (v0.2.x). The orchestrated flow works end-to-end on real PRs (the plugin has been used to ship its own PRs against JFK/gh-issue-driven), but the following known sharp edges exist as of v0.2.0. None lose data or corrupt state, but they affect the operator experience:
- Slow Mode A repos can false-positive
silent_no_op(#23) —/gh-issue-driven:shipstep 13 has a 30s bounded wait for the first Copilot signal. On repos where GitHub's "Automatic Copilot code review" auto-review takes longer than 30s (observed up to ~4 min onJFK/gh-issue-driven), the wait expires and the loop is incorrectly skipped withexit_reason=silent_no_op. The state file records the diagnosis correctly; recovery is to re-run/shiponce the Copilot review lands. Architectural fix tracked in #23 (move detection into step 14's polling loop). /gh-issue-driven:doctordoes not validate context_id resolution — the configuredmemory.context_idis resolved at/starttime, but/doctordoes not yet check whether it resolves successfully. Tracked as a follow-up.- No loop state machine tests — the verdict parser and Copilot detection function are fixture-driven tested, but the 5 terminal
exit_reasonstates in step 14's polling loop are not covered by automated tests yet (tracked in #10). claude-c-suite:auditcannot evaluate this plugin via its declared mechanism — the audit skill'sscripts/audit.pydoes not exist ingh-issue-driven's layout. The de-facto baseline islint.yml(which validates frontmatter, JSON syntax, version sync, fixture tests, and inline-jq sync).
For the full list of known issues, see the v0.2.1 and v0.3.0 milestones.
See SECURITY.md. TL;DR: this plugin runs git, gh, and reviewer skills. It never pushes to default branches, never force-pushes, never modifies ~/.claude/settings.json, and never auto-applies Copilot suggestions without scrutiny.
See CONTRIBUTING.md.
CI runs lint.yml on every push and PR — JSON syntax, version sync, name sync, and command frontmatter parseability.
Before cutting any v* tag, maintainers follow the Release checklist (dogfooding gate): patch releases require 1 representative run, minor/major releases require 3 runs across typo / mid-size feature / cross-cutting categories, with evidence attached to the release notes.
MIT © Fumikazu Kiyota
🤖 Built with Claude Code.