When to use
| Skill | Usage | Output |
|---|---|---|
/issue-triage |
Sort, analyze, comment on issues | Action tables + deep analysis + posted comments |
/repo-recap |
General recap to share with the team | Markdown summary (PRs + issues + releases) |
Triggers :
- Manually:
/issue-triageor/issue-triage allor/issue-triage 42 57 - Proactively: when >10 open issues without triage, or stale issue >30d detected
Language
- Check the argument passed to the skill
- If
enorenglish→ tables and summary in English - If
fr,french, or no argument → French (default) - Note: GitHub comments (Phase 3) ALWAYS remain in English (international audience)
3-phase workflow: automatic audit → opt-in deep analysis → comments with mandatory validation.
Preconditions
git rev-parse --is-inside-work-tree
gh auth status
If one fails, stop and explain what is missing.
Phase 1 — Audit (always executed)
Data Gathering (commands in parallel)
# Identité du repo
gh repo view --json nameWithOwner -q .nameWithOwner
# Issues ouvertes avec métadonnées complètes
gh issue list --state open --limit 100 \
--json number,title,author,createdAt,updatedAt,labels,assignees,body,comments
# PRs ouvertes (pour cross-référence)
gh pr list --state open --limit 50 --json number,title,body
# Issues fermées récemment (pour détection doublons)
gh issue list --state closed --limit 20 \
--json number,title,labels,closedAt
# Collaborateurs (pour protéger les issues des mainteneurs)
gh api "repos/{owner}/{repo}/collaborators" --jq '.[].login'
Collaborators fallback : if gh api .../collaborators fails (403/404):
gh pr list --state merged --limit 10 --json author --jq '.[].author.login' | sort -u
If still ambiguous, ask the user via AskUserQuestion.
Note : author is an object {login: "..."} — always extract .author.login.
Analysis — 6 dimensions
1. Categorization (existing labels > title/body inference):
- Bug : keywords
crash,error,fail,broken,regression,wrong,unexpected - Feature :
add,implement,support,new,feat: - Enhancement :
improve,optimize,better,enhance,refactor - Question/Support :
how,why,help,unclear,docs,documentation - Duplicate Candidate : see dimension 3 below
2. Cross-ref PRs :
- Scan
bodyof each open PR forfixes #N,closes #N,resolves #N(case-insensitive, regex) - Build a map:
issue_number -> [PR numbers] - An issue linked to a merged PR → recommend closing
3. Duplicate detection :
- Normalize titles: lowercase, strip prefixes (
bug:,feat:,[bug],[feature], etc.) - Jaccard on title words : if score > 60% between two issues → duplicate candidate
- Keywords body overlap > 50% → signal reinforcement
- Also compare with recent closed issues (last 20)
- A false positive can be confirmed/discarded in Phase 2
4. Risk classification :
- Red : keywords
CVE,vulnerability,injection,auth bypass,security,exploit,unsafe,credentials,leak,RCE,XSS - Yellow :
breaking change,migration,deprecation,remove API,breaking,incompatible - Green : everything else
5. Staleness :
-
30d without activity (updatedAt) → Stale
-
90d without activity → Very Stale
- Calculate from the current date
6. Action recommendations :
Accept & Prioritize: clear, reproducible issue, in scopeLabel needed: issue without labelComment needed: missing info, insufficient bodyLinked to PR: an open PR references this issueDuplicate candidate: duplicate candidate identified (specify with#N)Close candidate: stale + no recent activity, or out of scope (never if author is a collaborator)PR merged → close: linked PR is merged, issue still open
Output — 5 tables
## Issues ouvertes ({count})
### Critiques (risque rouge)
| # | Titre | Auteur | Âge | Labels | Action |
| - | ----- | ------ | --- | ------ | ------ |
### Liées à une PR
| # | Titre | Auteur | PR(s) liée(s) | Status PR | Action |
| - | ----- | ------ | ------------- | --------- | ------ |
### Actives
| # | Titre | Auteur | Catégorie | Âge | Labels | Action |
| - | ----- | ------ | --------- | --- | ------ | ------ |
### Doublons candidats
| # | Titre | Doublon de | Similarité | Action |
| - | ----- | ---------- | ---------- | ------ |
### Stale
| # | Titre | Auteur | Dernière activité | Action |
| - | ----- | ------ | ----------------- | ------ |
### Résumé
- Total : {N} issues ouvertes
- Critiques : {N} (risque sécurité ou breaking)
- Liées à PR : {N}
- Doublons candidats : {N}
- Stale (>30j) : {N} | Very Stale (>90j) : {N}
- Sans labels : {N}
- Quick wins (à fermer ou labeler rapidement) : {liste}
0 issues → display Aucune issue ouverte. and finish.
Note : Âge = days since createdAt, format {N}j. If >30d, display in bold.
Automatic copy
After displaying the triage table, copy to clipboard:
pbcopy <<'EOF'
{tableau de triage complet}
EOF
Confirm: Tableau copié dans le presse-papier. (FR) / Triage table copied to clipboard. (EN)
Phase 2 — Deep Analysis (opt-in)
Issue selection
If argument passed :
"all"→ all open issues- Numbers (
"42 57") → only these issues - No argument → suggest via
AskUserQuestion
If no argument, display:
question: "Quelles issues voulez-vous analyser en profondeur ?"
header: "Deep Analysis"
multiSelect: true
options:
- label: "Toutes ({N} issues)"
description: "Analyse approfondie de toutes les issues avec agents en parallèle"
- label: "Critiques uniquement"
description: "Focus sur les {M} issues à risque rouge/jaune"
- label: "Doublons candidats"
description: "Confirmer ou écarter les {K} doublons détectés"
- label: "Stale uniquement"
description: "Décision close/keep sur les {J} issues stale"
- label: "Passer"
description: "Terminer ici — juste l'audit"
If "Skip" → end of workflow.
Analysis execution
For each selected issue, launch an agent via Task tool in parallel :
subagent_type: general-purpose
model: sonnet
prompt: |
Analyze GitHub issue #{num}: "{title}" by @{author}
**Metadata**: Created {createdAt}, last updated {updatedAt}, labels: {labels}
**Body**:
{body}
**Existing comments** ({comments_count} total, showing last 5):
{last_5_comments}
**Context**:
- Linked PRs: {linked_prs or "none"}
- Duplicate candidate of: {duplicate_of or "none"}
- Risk classification: {risk_color}
Analyze this issue and return a structured report:
### Scope Assessment
What is this issue actually asking for? Is it clearly defined?
### Missing Information
What's needed to act on this? (reproduction steps, version, environment, etc.)
### Risk & Impact
Security risk? Breaking change? Who's affected?
### Effort Estimate
XS (<1h) / S (1-4h) / M (1-2d) / L (3-5d) / XL (>1 week)
### Priority
P0 (critical, act now) / P1 (high, this sprint) / P2 (medium, backlog) / P3 (low, someday)
### Recommended Action
One of: Accept & Prioritize, Request More Info, Mark Duplicate (#N), Close (Stale), Close (Out of Scope), Link to Existing PR
### Draft Comment
Draft a GitHub comment in English using the appropriate template from templates/issue-comment.md.
Be specific, helpful, and constructive.
If issue has >50 comments, summarize only the last 5.
Aggregate all reports. Display a summary after all analyses.
Phase 3 — Actions (mandatory validation)
Possible action types
- Comment :
gh issue comment {num} --body-file - - Label :
gh issue edit {num} --add-label "{label}"(skip if label already present) - Close :
gh issue close {num} --reason "not planned"(never without validation)
Draft generation
For each analyzed issue, generate the actions (comment + labels + closure if applicable) using templates/issue-comment.md.
Rules :
- Comment language: English (international audience)
- Tone: professional, constructive, factual
- Never re-label an issue that already has this label
- Never propose "close" for an issue from a collaborator
- Always display the draft BEFORE any
gh issue comment
Display and validation
Display ALL drafts in the format:
---
### Draft — Issue #{num}: {title}
**Actions proposées** : {Commentaire | Label: "bug" | Fermeture}
**Commentaire** :
{commentaire complet}
---
Then request validation via AskUserQuestion :
question: "Ces actions sont prêtes. Lesquelles voulez-vous exécuter ?"
header: "Exécuter"
multiSelect: true
options:
- label: "Toutes ({N} actions)"
description: "Commenter + labeler + fermer selon les drafts"
- label: "Issue #{x} — {title_truncated}"
description: "Exécuter uniquement les actions pour cette issue"
- label: "Aucune"
description: "Annuler — ne rien faire"
(Generate one option per issue + "All" + "None")
Execution
For each validated action, execute in order: comment → label → close.
# Commenter
gh issue comment {num} --body-file - <<'COMMENT_EOF'
{commentaire}
COMMENT_EOF
# Labeler (si applicable)
gh issue edit {num} --add-label "{label}"
# Fermer (si applicable)
gh issue close {num} --reason "not planned"
Confirm each action: Commentaire posté sur issue #{num}: {title}
If "None" → Aucune action exécutée. Workflow terminé.
Edge case handling
| Situation | Behavior |
|---|---|
| 0 open issues | Aucune issue ouverte. + finish |
| Issue without body | Categorize by title, recommend Comment needed |
| >50 comments | Summarize only the last 5 |
| Duplicate false positive | Phase 2 confirms/rules out — do not act on suspicion alone |
| Labels already present | Do not re-label, report "label already applied" |
| Outcome from a collaborator | Never close candidate automatic |
| GitHub API rate limit | Reduce --limit, notify the user |
| Merged PR linked to open issue | Recommend closing the issue |
| Issue with no activity >90d | Very Stale — propose closing with a kind message |
| Duplicate confirmed in Phase 2 | Post comment + close in favor of the original issue |
Notes
- Always derive owner/repo via
gh repo view, never hardcode - Use
ghCLI (notcurlGitHub API) except for the list of collaborators updatedAtcan be null on some issues → treat ascreatedAt- Never post or close without explicit user validation in the chat
- Drafted comments must be visible BEFORE any
gh issue comment - Jaccard similarity = |word intersection| / |word union| (exclude stop words: a, the, is, in, of, for, to, with, on, at, by)