A Claude Code skill that turns GitHub Issues + Projects v2 into a disciplined, AI-assisted backlog — no extra tools, no databases, no webhooks.
Backlogs rot. Items accumulate without acceptance criteria, blockers go unrecorded, priorities drift from execution order, and eventually the backlog stops reflecting reality — so people stop trusting it.
This skill keeps a GitHub backlog honest. Every item is INVEST-validated before it lands in the queue. Blockers are tracked with GitHub's native dependency API, not buried in comments. /execute-backlog-item picks the topmost unblocked work automatically, so "what do I do next?" has a deterministic answer.
Everything stays in GitHub — Issues, Projects v2, Milestones, Labels. No extra tools, no database, no webhooks.
Claude enforces structure; it doesn't set your priorities. Specifically:
- INVEST gate — flags items with vague scope or missing acceptance criteria before they enter the queue
- Dependency inference — reads prose ("depends on X"), surfaces candidates for you to confirm
- Next-item selection — picks the topmost unblocked work; you decide whether to execute it
- Audit —
/validate-backlogis read-only and surfaces problems as ready-to-runghcommands
Run /migrate-backlog, point Claude at the file, and it imports everything into GitHub Issues — skipping done items, inferring dependencies from your own prose, and letting you review before anything is applied.
- Claude Code (CLI or IDE extension)
- GitHub CLI (
gh) authenticated (gh auth login) - A GitHub repository with Issues enabled
- Git
originremote pointing to that repository
Add the marketplace and install the plugin with two Claude Code commands:
/plugin marketplace add gringolito/github-backlog-management-skill
/plugin install github-backlog-management@gringolito
Restart Claude Code if it was already running. All commands below are then available in any repository you open with Claude Code.
If gh auth status reports that you are not logged in, run:
gh auth loginChoose GitHub.com, then Login with a web browser (recommended — it handles all scope grants in one step). If you prefer a token, select Paste an authentication token instead.
This skill calls GitHub's Issues, Projects v2, and Dependencies APIs. Your token must include all four scopes:
| Scope | Required for |
|---|---|
repo |
Create and read Issues, Labels, Milestones, and PRs |
project |
Read and write GitHub Projects v2 |
read:user |
Resolve the authenticated user for metadata |
read:org |
Required when the repo lives under a GitHub organization |
Check your current scopes:
gh auth statusIf project or read:user are missing, add them without re-authenticating:
gh auth refresh --scopes project,read:userNote:
gh auth refreshworks for OAuth (web browser) logins. If you authenticated with a Personal Access Token, generate a new classic PAT on GitHub with the scopes listed above.
This skill runs multi-step workflows that call gh and git many times in sequence. Without a pre-approved allowlist, Claude Code prompts for permission on every call and interrupts the workflow mid-run.
Add one of the blocks below to .claude/settings.json in any repo where you use this skill, or to ~/.claude/settings.json for a global default.
YOLO mode — no prompts during any multi-step command:
{
"permissions": {
"allow": ["Bash(gh *)", "Bash(git *)"]
}
}Safe / read-only mode — /validate-backlog and read queries run silently; write commands still ask for confirmation:
{
"permissions": {
"allow": [
"Bash(gh auth status *)",
"Bash(gh repo view *)",
"Bash(gh issue list *)",
"Bash(gh issue view *)",
"Bash(gh label list *)",
"Bash(gh project list *)",
"Bash(gh project view *)",
"Bash(gh project item-list *)",
"Bash(gh project field-list *)",
"Bash(gh release list *)"
]
}
}Note:
gh apicalls used for reading milestones and issue dependencies are not listed above — the same command prefix covers both reads and writes, so they cannot be cleanly separated by pattern. In safe mode these calls will still prompt; approve them when the command starts withgh api "repos/..."and contains no-X POSTor-X DELETEflag.
| Command | What it does |
|---|---|
/initialize-backlog |
One-time bootstrap: provisions the GitHub Project v2, the full label catalog, and the Issue Forms template. Idempotent — safe to re-run. |
/plan-release |
Creates a Milestone with a due date. Tie-breaks and active-milestone resolution are automatic. |
/add-backlog-item |
Interactively authors a single backlog item. Enforces INVEST, recommends rank and priority, wires up native GitHub dependencies. |
/migrate-backlog |
Bulk-imports an existing BACKLOG.md. Skips Done items. Dependency inference is opt-in — candidates are reviewed before anything is applied. |
/refine-backlog |
Lists all needs-clarification candidates, lets you select which to refine, then loops through them one by one — asking continue/stop after each. |
/refine-backlog-item |
Refines a single needs-clarification item: discovery dialogue, body rewrite, INVEST gate, label/rank/dep re-evaluation, and label removal after a final validation pass. |
/release-status |
Read-only milestone health dashboard — issue counts by Project Status, % complete, blocked items, and unestimated items. Accepts an optional milestone argument; defaults to the active milestone. |
/validate-backlog |
Read-only audit. Emits actionable gh issue edit ... snippets. Never mutates anything. |
/execute-backlog-item |
Picks the topmost unblocked Todo item, respects active milestone scope, skips blocked items, and walks you through to a PR. |
INVEST is a checklist for deciding whether a backlog item is ready to be worked on. An item passes when it is:
| Letter | Criterion | Why it matters |
|---|---|---|
| I | Independent | Can be built and shipped without waiting on another item in the same batch. Avoids invisible coupling that breaks your execution order. |
| N | Negotiable | The what is agreed; the how is still open. If an item already dictates the implementation, you've skipped the design conversation. |
| V | Valuable | Delivers something real to a user or the system. If you can't articulate the value, the item probably isn't ready. |
| E | Estimable | The team can roughly size it. Items that can't be estimated are usually under-specified or secretly multiple items. |
| S | Small | Fits inside a single cycle of work. Large items hide risk and delay feedback. |
| T | Testable | Has acceptance criteria concrete enough to write a test or a manual check against. "Works correctly" doesn't count. |
This skill enforces INVEST at creation time (/add-backlog-item) and during refinement (/refine-backlog-item). Items that don't pass get the needs-clarification label instead of landing in the queue — because a vague item at the top of your backlog is just a polite way of not knowing what you're doing next.
Every issue created by this skill follows a consistent body shape:
### What
### Why
### In Scope
### Out of Scope
### Acceptance Criteria
### INVEST Notes
Every backlog item carries three label groups:
- Type —
type:featuretype:bugtype:securitytype:performancetype:dxtype:tech-debttype:reliabilitytype:compliancetype:spike - Priority —
priority:P0throughpriority:P3 - Effort —
effort:XSeffort:Seffort:Meffort:Leffort:XL
Priority is severity classification. Execution order is the manual Project rank — the two are independent concepts that should stay consistent but are never conflated.
type:external-blocker is a special infrastructure label for lightweight stub issues that represent external constraints (API limitations, vendor issues, regulatory holds, etc.) blocking one or more backlog items. Stubs carry only the type:external-blocker label — no priority, no effort, no rank. They are created by /add-external-blocker, never appear as executable work in /execute-backlog-item, and are excluded from all milestone counts and planning scope. Close a stub with /resolve-external-blocker when the external constraint is lifted.
/initialize-backlog ──► /plan-release ──► /add-backlog-item
/migrate-backlog
│
├──► /refine-backlog ──► /refine-backlog-item
├──► /release-status (read-only)
├──► /validate-backlog (read-only)
└──► /execute-backlog-item
Run /initialize-backlog once. Every other command preflights for the linked Project and stops with a clear error if it is missing.
/initialize-backlog
This provisions the GitHub Project v2, creates all labels, opens a PR with the Issue Forms template, and writes .claude/backlog-project.json. Run it once per repo.
/plan-release
Claude presents three release modes — Maintenance (patch an existing milestone), Regular (you select scope interactively), or Automated (Claude proposes scope from unassigned items). It infers a semver version from the scope and creates a Milestone with a due date.
/add-backlog-item
Claude asks clarifying questions, authors the issue body, recommends a rank in the Project, and links any declared blockers using GitHub's native dependency API.
/migrate-backlog
Point Claude at your existing BACKLOG.md. Done items are skipped. Dependency hints in prose ("depends on", "blocked by") are surfaced for your review before anything is applied.
/refine-backlog
Lists all needs-clarification items sorted by priority, lets you select which ones to work on, then calls /refine-backlog-item for each — asking whether to continue after every iteration.
/refine-backlog-item 42
Refines a single item directly (useful when you know exactly which issue needs attention). Guides a discovery dialogue, rewrites the body, re-evaluates labels and rank, runs a validation gate, and removes needs-clarification only when everything checks out.
/release-status
Produces a Markdown dashboard for the active milestone: issue counts by Project Status (Done / In Progress / Todo), % complete, blocked items (requires GitHub's native dependency API), and open items missing an effort:* label. Pass a milestone title, number, or version string to target a specific release:
/release-status v1.3.0
The output is valid GitHub-Flavored Markdown — paste it directly into a standup document, Slack message, or GitHub comment.
/validate-backlog
A read-only pass that surfaces missing labels, malformed issue bodies, dangling blockers, and cross-Project dependency smells. Outputs copy-pasteable gh commands — never applies fixes itself.
/execute-backlog-item
Picks the topmost unblocked Todo item (active milestone first, unmilestoned fallback), reports which items were skipped and why, and walks you through implementation to a PR.
Issues, improvement suggestions, and pull requests are all welcome.
Found a bug or unexpected behavior?
Open a GitHub Issue describing what command you ran, what you expected, and what actually happened. Include the relevant gh output if you have it.
Have an idea for a new feature or command?
Open an Issue with the type:feature label and describe the problem it solves. The best feature requests explain the workflow gap, not just the proposed solution.
Want to contribute a fix or improvement?
- Fork the repository
- Create a branch
- Make your changes — each command spec lives in
commands/*.md - Verify cross-command invariants still hold (see the consistency greps in CLAUDE.md)
- Open a PR with a clear description of what changed and why
This repository uses Conventional Commits. Commit messages must follow the <type>: <description> format. Common types: feat for new behavior, fix for corrections, docs for README/comment changes, refactor for rewrites that don't change behavior, chore for maintenance. Example: feat: add needs-refinement label to validate-backlog report.
When editing command specs, preserve the existing style: numbered workflow sections with (MANDATORY) / (STRICT) / (RELATIVE) flags, opening prose in the You are an AI agent acting as... form, and the standard preflight block. Label catalog, preflight stop string, and issue body section headings must stay consistent across all command files.
MIT — see LICENSE.
There is a beautiful license called the Beerware License. It was written by Poul-Henning Kamp sometime in the 1990s and it says, more or less: if you think this software is worth it, and we ever meet in person, you can buy me a beer.
It is one of the most honest licenses ever written. It captures exactly the spirit of open source: share freely, ask for nothing, and if someone's work genuinely helped you, buy them a drink and tell them about it.
Sadly, the Beerware License is not OSI-approved. It lacks the formal language needed for corporate legal teams to wave it through, which means — in a cruel twist — the most human license ever written is the one least likely to be used by humans working inside institutions.
So this project is MIT. Lawyers can sleep soundly.
But the spirit is still here. If this skill saved you an afternoon of backlog wrangling, helped you ship something that mattered, or simply made your GitHub a little less of a mess — and if we ever happen to meet in person — you can buy me a beer.