Install any skill in seconds. Free to start, no credit card required.
Get Started Free →3-phase issue backlog management with audit, deep analysis, and validated triage actions. Use when triaging GitHub issues, sorting bug reports, cleaning up stale tickets, or detecting duplicate issues. Args: 'all' to analyze all, issue numbers to focus (e.g. '42 57'), 'en'/'fr' for language, no arg = audit only.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 395% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 367% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 158% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 179% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 216% | 0% |
3-phase workflow for maintainers: automated audit of all open issues, opt-in deep analysis via parallel agents, and validated triage actions (comments, labels, closures).
| Skill | Usage | Output | |-------|-------|--------| | /issue-triage | Sort, analyze, and act on an issue backlog | Triage tables + analysis + executed actions | | /pr-triage | Sort, review, and comment on a PR backlog | Triage table + reviews + posted comments |
Triggers:
/issue-triage or /issue-triage all or /issue-triage 42 57en or english → tables and summary in Englishfr, french, or no argument → French (default)Thresholds used throughout the workflow. Edit to match your project:
| Parameter | Default | Description | |-----------|---------|-------------| | staleness_days | 30 | Days without activity before flagging as stale | | very_stale_days | 90 | Days without activity before flagging as very stale | | jaccard_threshold | 60% | Minimum Jaccard similarity to flag two issues as duplicates | | closed_compare_count | 20 | Number of recent closed issues to compare for duplicate detection | | open_limit | 100 | Maximum open issues to fetch and analyze |
bashgit rev-parse --is-inside-work-tree gh auth status
If either fails, stop and explain what is missing.
bash# Repo identity gh repo view --json nameWithOwner -q .nameWithOwner # Open issues (exclude PRs, limit 100) gh issue list --state open --limit 100 \ --json number,title,author,createdAt,updatedAt,labels,body,comments,assignees,milestone # Recent closed issues (for duplicate detection) gh issue list --state closed --limit 20 \ --json number,title,body,labels,stateReason # Open PRs (bodies for cross-reference detection) gh pr list --state open --limit 50 --json number,title,body # Collaborators (to distinguish reporter types) gh api "repos/{owner}/{repo}/collaborators" --jq '.[].login'
Collaborators fallback: if gh api .../collaborators returns 403/404:
bash# Extract authors from last 10 merged PRs gh pr list --state merged --limit 10 --json author --jq '.[].author.login' | sort -u
If still ambiguous, ask via AskUserQuestion.
Note: comments field in gh issue list --json comments returns the count, not content. For Phase 2, fetch full content separately: gh issue view {num} --json comments.
Run all 6 dimensions for each open issue:
Classify each issue by reading title + first 200 chars of body:
| Category | Label | Criteria | |----------|-------|----------| | Bug | bug | Describes broken behavior, unexpected output, crash | | Feature Request | enhancement | Asks for new functionality | | Question / Support | question | User asking how something works | | Documentation | documentation | Missing or incorrect docs | | Out of Scope | wontfix | Clearly outside project boundaries | | Unclear | needs-info | Body empty, too vague to categorize |
If body is empty → category is always Unclear (never assume).
Scan each open PR body for references to the issue number:
fixes #N, closes #N, resolves #N, fix #N, close #N (case-insensitive, N = issue number)body fields already fetched; do NOT make N additional API callsAlgorithm (self-contained, no external library):
For each open issue, compute Jaccard similarity against all other open issues AND the 20 most recent closed issues.
Step 1: Normalize title + first 300 chars of body:
- Lowercase the full text
- Strip category prefixes: "feat:", "fix:", "bug:", "chore:", "docs:", "test:", "refactor:"
- Remove punctuation: .,!?;:'"()[]{}-_/\@#
Step 2: Tokenize:
- Split on whitespace
- Remove stop words: the a an is in on to for of and or with this that it can not no be
- Remove tokens shorter than 3 characters
Step 3: Compute Jaccard:
tokens_A = set of tokens from issue A
tokens_B = set of tokens from issue B
jaccard = |tokens_A ∩ tokens_B| / |tokens_A ∪ tokens_B|
Step 4: Flag:
- If jaccard >= 0.60: mark as potential duplicate
- Report: "Similar to #N (Jaccard: 0.72)"
- Keep the OLDER issue as canonical; newer = duplicate candidateJaccard is computed at runtime using the fetched data; no API calls beyond Phase 1 gather.
Assign Red / Yellow / Green based on signals in title + body:
| Level | Color | Criteria | |-------|-------|----------| | Critical | Red | Security vulnerability, data loss, regression blocking users, crash in production | | Needs Attention | Yellow | Missing validation, performance degradation, breaking change undocumented, Unclear with no response for >7 days | | Normal | Green | Everything else |
| Status | Criterion | |--------|-----------| | Active | Updated within 30 days | | Stale | No activity 30–90 days | | Very Stale | No activity >90 days |
Use updatedAt field. Staleness does NOT depend on comments count; a commented-on issue with old updatedAt is still stale.
One recommended action per issue:
| Situation | Action | |-----------|--------| | Category = Unclear, body empty | Comment requesting details | | Jaccard >= 0.60 with known issue | Close as duplicate, link original | | Very stale + no assignee | Comment requesting status, suggest close | | Risk = Red | Pin to top of triage, escalate immediately | | Category = OOS | Close with explanation | | PR-linked | No action needed (tracked via PR) | | Normal + labeled | No action needed |
## Open Issues ({count})
### Critical: Immediate Attention (Risk: Red)
| # | Title | Category | Reporter | Days Open | Action |
|---|-------|----------|----------|-----------|--------|
### PR-Linked (tracked in open PRs)
| # | Title | Category | PR | Days Open |
|---|-------|----------|----|-----------|
### Active Issues
| # | Title | Category | Labels | Reporter | Days | Action |
|---|-------|----------|--------|----------|------|--------|
### Duplicate Candidates
| # | Title | Similar To | Jaccard | Action |
|---|-------|------------|---------|--------|
### Stale Issues
| # | Title | Category | Last Activity | Reporter | Action |
|---|-------|----------|---------------|----------|--------|
### Summary
- Total open: {N}
- Critical (Red): {count}
- PR-linked: {count}
- Duplicate candidates: {count}
- Stale (30–90d): {count}
- Very stale (>90d): {count}
- Unlabeled: {count}
- Recommended actions: {comment: N, label: N, close: N}0 issues → display No open issues. and stop.
Protection rules (apply to all phases):
After displaying the triage tables, copy to clipboard using platform-appropriate command:
bashUNAME=$(uname -s) if [ "$UNAME" = "Darwin" ]; then pbcopy <<'EOF' {full triage tables} EOF elif command -v xclip &>/dev/null; then echo "{full triage tables}" | xclip -selection clipboard elif command -v wl-copy &>/dev/null; then echo "{full triage tables}" | wl-copy elif command -v clip.exe &>/dev/null; then echo "{full triage tables}" | clip.exe fi
Confirm: Triage tables copied to clipboard. (EN) / Tableaux copiés dans le presse-papier. (FR)
If argument passed:
"all" → all issues with recommended actions"42 57") → only those issuesAskUserQuestionIf no argument, display:
question: "Which issues do you want to analyze in depth?"
header: "Deep Analysis"
multiSelect: true
options:
- label: "All ({N} issues with recommended actions)"
description: "Launch parallel analysis agents for each actionable issue"
- label: "Critical only ({M} Red issues)"
description: "Focus on high-risk issues requiring immediate action"
- label: "Duplicate candidates ({K} issues)"
description: "Verify Jaccard similarity with full body + comments"
- label: "Stale only ({J} stale issues)"
description: "Decide which stale issues to close vs. revive"
- label: "Skip"
description: "Stop here, audit only"If "Skip" → end workflow.
For each selected issue, launch an analysis agent via Task tool in parallel:
subagent_type: general
model: sonnet
prompt: |
Analyze GitHub issue #{num}: "{title}"
**Metadata**: Category={category}, Risk={risk}, Days open={days}, Labels={labels}
**Reporter**: @{author} ({collaborator? "collaborator" : "external"})
**Assignees**: {assignees or "none"}
**Body**:
{body}
**Comments** (fetch via: gh issue view {num} --json comments):
{comments[].body, truncate at 5000 chars total}
**Duplicate candidates**: {jaccard_results or "none found"}
**Linked PRs**: {pr_refs or "none"}
Tasks:
1. Verify the category assigned in Phase 1 (correct? suggest alternative if not)
2. If duplicate candidate: confirm or deny similarity with rationale
3. If Unclear/needs-info: identify exactly what information is missing
4. Suggest the most appropriate action with exact text if a comment is needed
5. Estimate effort to fix if it's a Bug or Feature Request (XS/S/M/L/XL)
Return structured output:
### Verification
### Duplicate Analysis
### Missing Information
### Recommended Action
### Effort EstimateFallback if parallel agents unavailable: run analysis sequentially, one issue at a time. Notify user: Running sequential analysis (parallel agents not available).
Fetch full comments via:
bashgh issue view {num} --json comments --jq '.comments[].body'
Aggregate all reports. Display a summary after all analyses complete.
For each analyzed issue, generate the appropriate action using the template templates/issue-comment.md.
3 action types:
| Type | Command | When | |------|---------|------| | Comment | gh issue comment {num} --body-file - | Needs info, stale ping, OOS explanation | | Label | gh issue edit {num} --add-label "{label}" | Unlabeled issue with clear category | | Close | gh issue close {num} --reason "not planned" | Duplicate, OOS, very stale |
Rules:
gh label list)"not planned" for OOS/duplicate, "completed" only if a fix was mergedDisplay ALL drafted actions in format:
---
### Draft: Issue #{num}: {title}
**Action**: {Comment / Label / Close + Comment}
**Reason**: {1 sentence}
{full comment text if applicable}
---Then request validation via AskUserQuestion:
question: "These actions are ready. Which ones do you want to execute?"
header: "Execute Triage Actions"
multiSelect: true
options:
- label: "All ({N} actions)"
description: "Execute all drafted triage actions"
- label: "Issue #{x}: {title_truncated} ({action_type})"
description: "Execute only this action"
- label: "None"
description: "Cancel, execute nothing"(Generate one option per issue + "All" + "None")
For each validated action:
bash# Comment gh issue comment {num} --body-file - <<'TRIAGE_EOF' {comment} TRIAGE_EOF # Label gh issue edit {num} --add-label "{label}" # Close with comment gh issue comment {num} --body-file - <<'TRIAGE_EOF' {close comment} TRIAGE_EOF gh issue close {num} --reason "not planned"
Confirm each action: Action executed on issue #{num}: {title}
If "None" → No actions executed. Workflow complete.
| Situation | Behavior | |-----------|----------| | 0 open issues | Display No open issues. + stop | | Body empty | Category = Unclear, action = request details, never assume | | Collaborator as reporter | Protect from auto-close, flag explicitly in table | | Jaccard inconclusive (0.55–0.65) | Flag as "possible duplicate, verify manually" | | Label not in repo | Skip label action, notify user to create the label first | | Issue already closed during workflow | Skip silently, note in summary | | gh api .../collaborators 403/404 | Fallback to last 10 merged PR authors | | Parallel agents unavailable | Run sequential analysis, notify user | | Very large body (>5000 chars) | Truncate to 5000 chars with [truncated] note | | Milestone assigned | Include in table, never close milestoned issues without confirmation |
gh repo view, never hardcodegh CLI (not curl GitHub API) except for collaborators listcomments in gh issue list --json comments = count only; full content requires gh issue view {num} --json commentsgh issue comment or gh issue close*Triaged via Claude Code /issue-triage*| | /issue-triage | /pr-triage | |--|----------------|--------------| | Scope | Issue backlog | PR backlog | | Use when | Catching up on reporter feedback, periodic issue cleanup | Catching up after PR accumulation | | Phases | 3 (audit + deep analysis + actions) | 3 (audit + deep review + comments) | | Agents | Parallel sub-agents per issue | Parallel sub-agents per PR | | Duplicate detection | Jaccard similarity on title+body | File overlap % between PRs | | Actions | Comment / label / close | GitHub review comment | | Validation | AskUserQuestion before executing | AskUserQuestion before posting |
Decision rule: use /issue-triage for issue backlog management, /pr-triage for code review backlog.
Other measured skills in the registry, with their headline benchmark lift.