Help us improve
Share bugs, ideas, or general feedback.
From review-skill
Fetches issues from GitHub or GitLab, filters for main issues (PRD: or feat:), processes them sequentially with parallel sub-agents, and runs find-mismatch after implementation.
npx claudepluginhub utarn/review-skillHow this skill is triggered — by the user, by Claude, or both
Slash command
/review-skill:work-on-issuesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Fetch issues from the configured tracker (GitHub or GitLab), pick up work, implement it, and close completed issues. **Only main issues (titles starting with `PRD:` or `feat:`) are processed as top-level work units — one at a time, sequentially.** Other issues (e.g., `bug:`, `chore:`, unlabeled) are skipped at the top level. Within each main issue, independent subtasks are parallelized across m...
Creates p5.js generative art with seeded randomness, noise fields, and interactive parameter exploration. Use for algorithmic art, flow fields, or particle systems.
Share bugs, ideas, or general feedback.
Fetch issues from the configured tracker (GitHub or GitLab), pick up work, implement it, and close completed issues. Only main issues (titles starting with PRD: or feat:) are processed as top-level work units — one at a time, sequentially. Other issues (e.g., bug:, chore:, unlabeled) are skipped at the top level. Within each main issue, independent subtasks are parallelized across multiple sub agents. Every sub agent automatically runs find-mismatch after implementation — bugs are fixed immediately without prompting for confirmation.
Determine the tracker at session start by checking remotes:
git remote -v
| Remote host | Tracker | CLI | Command prefix |
|---|---|---|---|
github.com | GitHub Issues | gh | gh issue ... |
gitlab.com | GitLab Issues | glab | glab issue ... |
Store the resolved CLI alias (gh or glab) as $TRACKER for the rest of this skill. All commands below use $TRACKER.
GitLab uses different nouns than GitHub:
glab issueglab mr instead of gh prglab issue note / glab mr note instead of gh issue comment / gh pr commentWhen commands are structurally identical, use $TRACKER as a shortcut. When the subcommand differs (note vs comment, mr vs pr), use the platform-specific form.
List open issues — fetch in machine-readable format:
# GitHub — use --json for machine-readable output (NOT -F json, that flag does not exist in gh)
gh issue list --repo <repo> --state open --json number,title,labels
# GitLab — lists open issues by default, no --state flag
glab issue list -O json
For GitLab with label filtering:
glab issue list --label "bug" -O json
Filter for main issues only — from the full list, keep only issues whose title starts with PRD: or feat:. These are the main issues that qualify for top-level processing. All other issues (e.g., bug:, chore:, fix:, or un-prefixed) are filtered out and not presented as pickable work items. Show the user only the filtered main issue list.
Parse & present — summarize each main issue: number, title, labels, brief description. Present the filtered list to the user.
Let the user pick — present the main issue list with these options:
When "onwards" mode is selected, the orchestrator loops: dispatch sub agent for the chosen main issue → complete Phase 2–3 → automatically move to the next main issue → repeat until the list is exhausted. The user can pause or stop between main issues.
Important: Only one main issue is processed at a time. The orchestrator never dispatches multiple main issues in parallel — it picks the next main issue only after the current one is fully closed.
Check issue state — before reading the full issue, verify it's still open. If it's already closed, skip it and move to the next main issue. No point implementing a resolved issue.
# GitHub
gh issue view <number> --repo <repo> --json state
# GitLab
glab issue view <number> -F json | jq -r '.state'
If state is closed / CLOSED, skip to next main issue.
Detect PRD (parent) issues — if a main issue has the PRD label OR its title starts with PRD:, it is a parent issue that tracks sub-issues rather than containing implementation work itself. Skip it — do not dispatch a sub agent for it. Continue to the next main issue in the list. Track the PRD issue number for later auto-close (see PRD Auto-Close below).
# GitHub — check PRD label or title prefix
PRD_BY_LABEL=$(gh issue view <number> --repo <repo> --json labels --jq '.labels[].name' | grep -q "^PRD$" && echo "yes" || echo "no")
PRD_BY_TITLE=$(gh issue view <number> --repo <repo> --json title --jq '.title' | grep -q "^PRD:" && echo "yes" || echo "no")
# GitLab — check PRD label or title prefix
PRD_BY_LABEL=$(glab issue view <number> -F json | jq -r '.labels[].name' | grep -q "^PRD$" && echo "yes" || echo "no")
PRD_BY_TITLE=$(glab issue view <number> -F json | jq -r '.title' | grep -q "^PRD:" && echo "yes" || echo "no")
If the issue is a PRD (by label or title):
PRD_TRACKER list for auto-close checks#<number> [PRD] <title> (parent — skipping, sub-issues will be worked on)Read the full issue — load details and comments:
# GitHub
gh issue view <number> --repo <repo> --comments
# GitLab
glab issue view <number> --comments
For machine-readable output: GitHub uses --json <fields>, GitLab uses -F json.
Assign / label — mark the issue as in-progress if the tracker supports it:
# GitHub
gh issue edit <number> --repo <repo> --add-label "in-progress" --remove-label "needs-triage"
# GitLab
glab issue update <number> --label "in-progress" --unlabel "needs-triage"
When working on a range of main issues, build a dependency graph from their ## Blocked by sections. However, the orchestrator always processes main issues one at a time, sequentially — it never dispatches multiple main issues in parallel. Dependencies are used only to determine the correct ordering (blocked main issues are deferred until their blockers close).
Issue body ## Blocked by section — each main issue's description may contain a ## Blocked by heading followed by links to blocking issues. Parse these to determine which main issues must complete before others can start.
Formal tracker links — convert text-only references into native tracker relationships so the dependency graph shows up in GitLab/GitHub boards and UI.
After fetching issues, parse each issue body for the ## Blocked by section:
# GitHub — get issue body
gh issue view <number> --repo <repo> --json body --jq '.body'
# GitLab — get issue body
glab issue view <number> -F json | jq -r '.description'
Extract issue references from the ## Blocked by section. References may appear as:
#42 — shorthand issue referencehttps://github.com/owner/repo/issues/42 — full URLhttps://gitlab.com/owner/repo/-/issues/42 — full URLBuild a DEPS map in memory (main issues only):
DEPS = {
#42: [], # feat: — no blockers — process next
#43: [42], # feat: — blocked by #42 — defer until #42 closes
#44: [], # feat: — no blockers — process after #42 (sequential, one at a time)
}
After parsing, convert text references into formal tracker relationships so dependencies are visible in the tracker UI.
GitLab — use the REST API to create is_blocked_by links:
# Get project ID (needed for API calls)
PROJECT_ID=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.com/api/v4/projects/$(echo $REPO_PATH | sed 's/\//%2F/g')" | jq '.id')
# Create a formal "is blocked by" link
curl -s --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"target_project_id\": $PROJECT_ID, \"target_issue_iid\": <blocker-number>, \"link_type\": \"is_blocked_by\"}" \
"https://gitlab.com/api/v4/projects/$PROJECT_ID/issues/<blocked-number>/links"
GitHub — use the REST API to create sub-issue links (GitHub's native dependency feature):
# GitHub — link a blocking issue via the sub-issues API
gh api repos/<owner>/<repo>/issues/<blocked-number>/sub_issues \
--method POST \
--field sub_issue_id=$(gh issue view <blocker-number> --repo <repo> --json id --jq '.id') \
--field blocked_by=true
If the tracker API does not support formal links (or the CLI doesn't expose them), the text references in the issue body serve as the fallback — the orchestrator still uses the parsed DEPS map for parallelization regardless.
A PRD issue is identified by its title starting with PRD: (e.g., PRD: User Authentication System). This is a parent/epic issue that aggregates sub-issues. Do not implement PRDs — skip them and work on their sub-issues instead.
One main issue is processed at a time. The orchestrator picks the next unblocked main issue, dispatches a sub agent for it, waits for completion, then moves to the next. This gives each main issue a clean, focused context. Within that main issue, independent subtasks may be parallelized (see Subtask Parallelization below).
Create a worktree — always use a git worktree for issue isolation. Never use git checkout -b — worktrees keep the main working tree clean and allow parallel work. Create one in .claude/worktrees/ with a dedicated branch:
# Ensure the worktrees directory exists
mkdir -p .claude/worktrees
# Create worktree with a new branch
git worktree add .claude/worktrees/issue-<number> -b work-on-issue-<number>
Copy environment files into the worktree — this is mandatory, not optional. Sub agents need .env files to run tests, connect to databases, and access services. A worktree is a separate directory and does not inherit .env files from the main working tree:
# ALWAYS copy .env and .env.* files — do NOT skip even if no .env exists in the main tree
for f in .env .env.*; do [ -f "$f" ] && cp "$f" .claude/worktrees/issue-<number>/; done
# Verify the files were copied (optional but recommended):
ls -la .claude/worktrees/issue-<number>/.env*
Dispatch a sub agent to implement the main issue. Construct the prompt with everything the agent needs:
You are implementing issue #<number>: <title>.
## Issue Description
<paste full issue body and acceptance criteria>
## Working Directory
You are working in a git worktree at `.claude/worktrees/issue-<number>`.
Branch `work-on-issue-<number>` is already checked out in that directory.
All file operations (reads, edits, tests) must target paths inside this worktree.
## Environment Files
`.env` and `.env.*` files have been copied into the worktree directory. You do not need to create them. If tests or services fail due to missing environment variables, check that the `.env` files are present in the worktree root before proceeding.
## Constraints
- Follow the issue description and acceptance criteria exactly
- Do NOT modify files unrelated to this issue
- Run tests, lint, and build after implementation
- Commit with message: "fix: resolve #<number> — <short description>"
## Subtask Parallelization
Before implementing, analyze whether the issue contains independent subtasks that can run in parallel (see Subtask Parallelization section below). If so, dispatch parallel sub agents for non-blocking subtasks.
## Post-Implementation: Find-Mismatch Review (Automatic)
After implementation is complete and tests pass, you MUST run a find-mismatch review on all files you modified or created:
1. **Run the find-mismatch skill** — invoke it via the Skill tool with skill name "find-mismatch"
2. **Scope the review** — review only the files you changed (the diff). Do NOT review the entire codebase.
3. **Automatically accept and fix** — for every real bug found:
- Apply the fix immediately without asking for confirmation
- Do NOT report bugs without fixing them — fix first, report fixes in your output
- If a finding is uncertain or a false positive, skip it (only fix confirmed bugs)
4. **Re-run tests** — after applying all fixes, re-run the test suite to confirm nothing broke
5. **Proceed** — do not stop or wait for approval; continue to commit
This step is mandatory and automatic. Do not skip it, do not ask whether to proceed, and do not present findings without also fixing them.
## Output
Return a summary of: what you implemented, what find-mismatch fixes were applied, what tests you ran, and the commit hash.
Use the Agent tool with subagent_type: "full-stack-engineer" for implementation work. The sub agent starts fresh — no context from other issues or prior conversations. The sub agent prompt includes instructions to automatically run find-mismatch after implementation and fix any bugs found. The sub agent works inside the worktree directory (.claude/worktrees/issue-<number>), not the main working tree.
Red Flags — do NOT do these yourself instead of dispatching:
Verify — after the sub agent returns, run verification yourself. Use verification-before-completion if available. Do NOT trust the sub agent's "all tests pass" claim — run the commands and confirm output. The sub agent's find-mismatch fixes are included in its commit; verify the diff looks correct.
Commit — the sub agent should commit inside the worktree. If it didn't, commit from the worktree directory:
cd .claude/worktrees/issue-<number> && git commit -m "fix: resolve #<number> — <description>"
Create a PR/MR:
# GitHub
gh pr create --repo <repo> --title "Fix #<number>: <title>" --body "Closes #<number>"
# GitLab
glab mr create --title "Fix #<number>: <title>" --description "Closes #<number>"
Auto-merge the PR/MR — merge immediately after creation:
# GitHub
gh pr merge <number> --repo <repo> --squash --delete-branch
# GitLab
glab mr merge <number> --squash --remove-source-branch
Post a summary comment on the issue:
# GitHub
gh issue comment <number> --repo <repo> --body "Implementation complete. PR: <url>"
# GitLab
glab issue note <number> --message "Implementation complete. MR: <url>"
Update labels and close the issue. GitHub PRs with "Closes #" in the body auto-close on merge, but do not rely on that — always explicitly close:
Remove needs-triage, in-progress, and ready-for-agent labels, add ai-agent-closed, then close:
# GitHub — explicitly close the issue (do NOT rely on PR auto-close)
gh issue edit <number> --repo <repo> --remove-label "needs-triage,in-progress,ready-for-agent" --add-label "ai-agent-closed"
gh issue close <number> --repo <repo> --comment "Resolved in PR <number>"
# GitLab — remove old labels, add new label, then close
glab issue update <number> --unlabel "needs-triage,in-progress,ready-for-agent"
glab issue update <number> --label "ai-agent-closed"
glab issue note <number> --message "Resolved in MR <number>"
glab issue close <number>
Clean up worktree and branch:
# Remove the worktree
git worktree remove .claude/worktrees/issue-<number>
# Delete the branch
git branch -d work-on-issue-<number>
After closing a sub-issue, check whether any tracked PRD (parent) issues can be auto-closed. A PRD issue is ready to close when all of its sub-issues are closed.
After closing a sub-issue, check each PRD in PRD_TRACKER:
# GitHub — list sub-issues linked to the PRD (issues referenced in the body or via tracker links)
gh issue view <prd-number> --repo <repo> --json body --jq '.body'
# GitLab
glab issue view <prd-number> -F json | jq -r '.description'
Parse the PRD body for referenced issue numbers (e.g., #42, #43, #44 or /-prefixed links). Then check the state of each:
# GitHub — check state of a referenced issue
gh issue view <sub-issue-number> --repo <repo> --json state --jq '.state'
# GitLab
glab issue view <sub-issue-number> -F json | jq -r '.state'
If all sub-issues are closed, close the PRD:
# GitHub
gh issue edit <prd-number> --repo <repo> --remove-label "needs-triage,in-progress,ready-for-agent" --add-label "ai-agent-closed"
gh issue close <prd-number> --repo <repo> --comment "All sub-issues resolved. Closing PRD."
# GitLab
glab issue update <prd-number> --unlabel "needs-triage,in-progress,ready-for-agent"
glab issue update <prd-number> --label "ai-agent-closed"
glab issue note <prd-number> --message "All sub-issues resolved. Closing PRD."
glab issue close <prd-number>
Remove the PRD from PRD_TRACKER after closing it.
Sub-issue discovery: If the PRD body does not explicitly list sub-issue numbers, discover them by looking for issues that reference the PRD number in their body or title:
# GitHub — search for issues referencing the PRD
gh issue list --repo <repo> --state all --search "#<prd-number>" --json number,title,state
# GitLab — search for issues referencing the PRD
glab issue list --all --search "#<prd-number>" -O json
Before implementing, the sub agent (or orchestrator) should analyze the issue for independent subtasks.
digraph subtask_parallel {
"Analyze issue" [shape=box];
"Multiple subtasks?" [shape=diamond];
"Independent?" [shape=diamond];
"Shared files?" [shape=diamond];
"Sequential" [shape=box];
"Parallel dispatch" [shape=box];
"Analyze issue" -> "Multiple subtasks?";
"Multiple subtasks?" -> "Independent?" [label="yes"];
"Multiple subtasks?" -> "Sequential" [label="no — single task"];
"Independent?" -> "Shared files?" [label="yes"];
"Independent?" -> "Sequential" [label="no — depends on other subtasks"];
"Shared files?" -> "Parallel dispatch" [label="no — different files/dirs"];
"Shared files?" -> "Sequential" [label="yes — would conflict"];
}
Parallelize when:
Keep sequential when:
When the sub agent identifies parallelizable subtasks, it dispatches child agents:
Decompose — break the issue into subtasks with clear boundaries:
Issue #42: "Add user profile page and email notifications"
Subtask A: User profile page (files: src/pages/Profile.tsx, src/api/profile.ts)
Subtask B: Email notifications (files: src/services/email.ts, src/templates/)
→ Independent, no shared files → PARALLEL
Dispatch — use the Agent tool with subagent_type: "full-stack-engineer" for each subtask in a single message (parallel dispatch):
Agent A: "Implement the user profile page for issue #42..."
Agent B: "Implement email notifications for issue #42..."
Constrain each sub agent — specify exact file/directory boundaries to prevent conflicts:
## Your Scope
Files you MAY modify: src/services/email.ts, src/templates/
Files you MUST NOT modify: src/pages/, src/api/profile.ts (another agent is working on these)
## Deliverable
Implement [specific subtask]. Run relevant tests. Return summary of changes.
Integrate — after all parallel sub agents return, verify no conflicts and run the full test suite.
You are implementing a subtask of issue #<number>: <title>.
## Subtask: <specific subtask description>
## Working Directory
You are working in a git worktree at `.claude/worktrees/issue-<number>`.
`.env` and `.env.*` files are already present in the worktree root.
## Scope
- Files you MAY modify: <list>
- Files you MUST NOT modify: <list> (another agent is handling these)
## Requirements
<paste relevant acceptance criteria for this subtask only>
## Post-Implementation: Find-Mismatch Review (Automatic)
After your implementation is complete, you MUST run a find-mismatch review on the files you modified:
1. **Run the find-mismatch skill** — invoke it via the Skill tool with skill name "find-mismatch"
2. **Scope the review** — review only the files within your scope that you changed
3. **Automatically accept and fix** — fix every confirmed bug immediately without asking for confirmation
4. **Re-run tests** — confirm fixes don't break anything
5. **Proceed** — do not stop or wait for approval
## Verification
Run tests relevant to your subtask. Return:
1. What you implemented
2. Find-mismatch fixes applied (if any)
3. Files modified
4. Test results
When the user wants to work through multiple issues:
Fetch the full open list (Phase 1).
Filter for main issues only — keep only issues whose title starts with PRD: or feat:. Discard all others.
Build the dependency graph — parse ## Blocked by sections from all main issue bodies (see Dependency Detection & Formal Linking). Build the DEPS map and PRD_TRACKER list.
Set formal tracker links — convert text-only blocked-by references into native GitLab/GitHub relationships.
Process main issues one at a time (see below).
Between main issues, check with the user before proceeding.
Maintain a summary table:
| Issue | Title | Type | Blocked By | Agent | Status | PR/MR |
|---|---|---|---|---|---|---|
| #12 | feat: Setup DB schema | feat | — | Agent-1 | ✅ Closed | !34 |
| #13 | feat: Add API routes | feat | #12 | Agent-2 | 🔄 In Progress | — |
| #14 | bug: Fix typo | bug | — | — | ⏭ Skipped | — |
| #15 | feat: Add auth middleware | feat | #12, #13 | ⏳ Pending | — |
Non-main issues (rows without PRD: or feat: prefix) appear as "Skipped" in the table.
The orchestrator processes main issues strictly one at a time — never in parallel across issues. The DEPS map determines the order (blocked main issues are deferred), but only one main issue is ever active at a time. Subtask parallelization within that single main issue still applies.
Build DEPS map from main issue bodies → Loop:
1. Find the next main issue with zero unresolved blockers (DEPS[issue] is empty OR all blockers are closed)
2. If no unblocked main issues remain AND unresolved main issues exist → report blockers → break to user
3. If all main issues are closed → done
4. Dispatch a single sub agent for the selected main issue
- Agent gets its own worktree: .claude/worktrees/issue-<number> with branch work-on-issue-<number>
- Within this issue, the sub agent may parallelize independent subtasks (see Subtask Parallelization)
5. Wait for the sub agent to complete
6. Verify, create PR/MR, merge, close issue, clean up branch
7. PRD auto-close check — check if any PRD in PRD_TRACKER has all sub-issues closed
8. Re-evaluate DEPS — main issues whose blockers are now all closed become eligible
9. Go to step 1 (pick next unblocked main issue)
Ordering example:
Main issues only: DEPS = { #12 (feat): [], #13 (feat): [#12], #14 (feat): [#12] }
Step 1: #12 has no blockers → dispatch sub agent for #12
→ #12 completes, merged, closed
Step 2: #13 and #14 now unblocked → pick #13 (lowest number) → dispatch sub agent for #13
→ #13 completes, merged, closed
Step 3: #14 still unblocked → dispatch sub agent for #14
→ #14 completes, merged, closed
All main issues done. Check PRD auto-close.
Why one at a time:
When the user picks "issue X onwards", the orchestrator enters a continuous outer loop — it keeps processing main issues and re-fetching until the tracker is empty or the user stops. New main issues filed during work are automatically picked up in the next refresh.
OUTER LOOP (never stops until tracker is empty or user says stop):
1. Fetch ALL open issues from tracker
2. If no open issues exist → report "All issues resolved" → STOP
3. Filter to MAIN issues only (title starts with PRD: or feat:)
4. If no main issues remain → report "No main issues remaining" → STOP
5. Filter to issues >= starting number (honour "onwards")
6. Build PRD_TRACKER from PRD-titled/labeled issues
7. Parse all main issue bodies → Build DEPS map
8. Set formal tracker links (if not already linked)
INNER LOOP (one main issue at a time):
a. Find the next unblocked main issue (DEPS empty or all blockers closed, lowest number first)
b. Skip closed issues, skip PRDs
c. If no unblocked main issues remain AND unresolved main issues exist → report blockers → break to user
d. If no main issues remain at all → break inner loop
e. Dispatch ONE sub agent for the selected main issue
f. Sub agent: implement (may parallelize subtasks internally), find-mismatch, commit
g. Verify, create PR/MR, merge, close issue, clean up worktree and branch
h. PRD auto-close check
i. Re-evaluate DEPS → back to step (a)
9. Inner loop done → brief user: "Main issues processed. Re-fetching..."
10. Go back to step 1 (OUTER LOOP re-fetches everything)
Loop behavior:
PRD: or feat: are considered. All other issues are ignored at the top level.PRD: or has the PRD label, record it in PRD_TRACKER and skip (PRDs are not implemented, only tracked for auto-close).PRD_TRACKER to see if all its sub-issues are now closed. If they are, close the PRD automatically.>= starting number filter is re-applied on each outer loop refresh, so newly filed main issues with numbers >= the starting issue are included.After each outer loop iteration, re-fetch all open issues:
# GitHub — re-fetch all open issues
gh issue list --repo <repo> --state open --json number,title,labels
# GitLab — re-fetch all open issues
glab issue list -O json
If the result is empty → announce "All issues resolved. No open issues remaining." → exit. If the result contains new issues → announce "Found N new open issues" → continue inner loop.
When the user picks a single main issue (not a range), run it solo — no dependency parsing needed. Subtask parallelization within that single issue still applies.
| Label | Meaning | Default Color |
|---|---|---|
PRD | Parent issue — tracks sub-issues, not implementation work | #0075CA |
in-progress | Currently being worked on | #E4E669 |
ready-for-agent | Issue is ready for autonomous agent implementation | #0E8A16 |
ready-for-review | Implementation done, awaiting merge | #0E8A16 |
blocked | Cannot proceed (needs info, dependency, etc.) | #D93F0B |
ai-agent-closed | Issue closed by AI agent | #5319E7 |
Apply/remove as the issue moves through states.
If a label does not exist, create it before applying:
# GitHub
gh label create "in-progress" --repo <repo> --color "#E4E669" --description "Currently being worked on"
# GitLab
glab label create --name "in-progress" --color "#E4E669" --description "Currently being worked on"
Use the same pattern for PRD (#0075CA), ready-for-agent (#0E8A16), ready-for-review (#0E8A16), blocked (#D93F0B), and ai-agent-closed (#5319E7).
Shortcut: wrap label application in a helper — try to apply, and if the CLI reports "not found", create it first then retry:
# GitHub helper pattern
gh issue edit <number> --repo <repo> --add-label "in-progress" || \
(gh label create "in-progress" --repo <repo> --color "#E4E669" --description "Currently being worked on" && \
gh issue edit <number> --repo <repo> --add-label "in-progress")
# GitLab helper pattern
glab issue update <number> --label "in-progress" || \
(glab label create --name "in-progress" --color "#E4E669" --description "Currently being worked on" && \
glab issue update <number> --label "in-progress")
gh/glab.## Blocked by section — treat the issue as having no blockers (empty DEPS entry). It can be dispatched immediately.PRD:/feat: prefixed issues, the list is empty, report to the user: "No main issues (PRD: or feat:) found in the tracker. All open issues are non-main types (bug:, chore:, etc.)." Ask the user if they want to process specific non-main issues.PRD:/feat: filter only applies to automatic/batch selection, not to explicit user picks.