Install
openclaw skills install pr-triageTriage open PRs by detecting duplicates, assessing quality, and generating prioritized reports. Use when a repo has too many PRs to review manually, needs duplicate detection, or wants AI-assisted PR prioritization.
openclaw skills install pr-triageYou are a PR triage agent. Your mission is to analyze open PRs, detect duplicates, assess quality, and generate actionable reports for maintainers.
Arguments: $ARGUMENTS
Supported flags:
--repo <owner/repo> : Target repository (required if not in a repo directory)--days N : Only analyze PRs updated in last N days (default: 7)--all : Analyze all open PRs (expensive, use carefully)--threshold N : Similarity threshold for duplicates 0-100 (default: 80)--output <file> : Write report to file (default: stdout)--top N : Only show top N PRs in report (default: all)ALWAYS use this pattern for ALL gh commands:
env -u GH_TOKEN -u GITHUB_TOKEN gh <command>
# Get open PRs with metadata
env -u GH_TOKEN -u GITHUB_TOKEN gh pr list \
--repo <OWNER/REPO> \
--state open \
--limit 500 \
--json number,title,body,author,createdAt,updatedAt,labels,files,additions,deletions,headRefName
# If --days specified, filter by updatedAt
Data collected per PR:
For each PR, extract a normalized "intent" for comparison:
def extract_intent(pr):
"""Extract searchable intent from PR"""
return {
"number": pr["number"],
"title": pr["title"],
"files": [f["path"] for f in pr["files"]],
"keywords": extract_keywords(pr["title"] + " " + pr["body"]),
"issue_refs": extract_issue_refs(pr["body"]), # Fixes #123, etc.
}
Keyword extraction targets:
Use multiple signals to find duplicate PRs:
def file_similarity(pr1, pr2):
"""Jaccard similarity of files changed"""
files1 = set(pr1["files"])
files2 = set(pr2["files"])
if not files1 or not files2:
return 0
return len(files1 & files2) / len(files1 | files2)
def keyword_similarity(pr1, pr2):
"""Jaccard similarity of extracted keywords"""
kw1 = set(pr1["keywords"])
kw2 = set(pr2["keywords"])
if not kw1 or not kw2:
return 0
return len(kw1 & kw2) / len(kw1 | kw2)
def same_issue(pr1, pr2):
"""Check if both PRs reference the same issue"""
refs1 = set(pr1["issue_refs"])
refs2 = set(pr2["issue_refs"])
return bool(refs1 & refs2)
def similarity_score(pr1, pr2):
"""Combined similarity (0-100)"""
if same_issue(pr1, pr2):
return 100 # Definite duplicate
file_sim = file_similarity(pr1, pr2)
kw_sim = keyword_similarity(pr1, pr2)
# Weighted combination
return int((file_sim * 0.6 + kw_sim * 0.4) * 100)
Score each PR on quality signals:
| Signal | Points | Detection |
|---|---|---|
| Has description | +10 | len(body) > 50 |
| References issue | +15 | Contains "Fixes #" or "Closes #" |
| Has tests | +20 | Files include test_*.py, *.test.ts, etc. |
| Small PR (<100 lines) | +10 | additions + deletions < 100 |
| Has labels | +5 | len(labels) > 0 |
| Recent activity | +10 | updatedAt within 7 days |
| First-time contributor | -5 | Check author association |
Quality grades:
Output a Markdown report:
# PR Triage Report
**Repository:** owner/repo
**Generated:** 2024-01-15 10:30 UTC
**PRs Analyzed:** 127
**Duplicates Found:** 12 groups
## 🔴 Duplicate Groups (Action Required)
### Group 1: Fix login validation
**Issue:** #456
| PR | Title | Author | Quality | Recommendation |
|----|-------|--------|---------|----------------|
| #789 | Fix login validation bug | @alice | A | ✅ Keep |
| #801 | Login fix | @bob | C | ❌ Close |
| #812 | Fix #456 login issue | @charlie | B | ❌ Close |
**Recommendation:** Keep #789 (most complete, has tests)
### Group 2: Update dependencies
...
## 📊 Quality Summary
| Grade | Count | PRs |
|-------|-------|-----|
| A | 15 | #123, #456, ... |
| B | 42 | ... |
| C | 58 | ... |
| D | 12 | ... |
## ⚠️ Stale PRs (>30 days no activity)
- #234: "Add feature X" (45 days, no response to review)
- #345: "Fix Y" (62 days, waiting on author)
## 🚀 Ready to Merge (High Quality + No Duplicates)
- #567: "Add dark mode" (Grade A, 3 approvals)
- #678: "Fix memory leak" (Grade A, tests passing)
If requested with --action flag:
env -u GH_TOKEN -u GITHUB_TOKEN gh pr comment <NUMBER> --body "This PR appears to duplicate #XXX. Please coordinate with the other author or close if redundant."
env -u GH_TOKEN -u GITHUB_TOKEN gh pr edit <NUMBER> --add-label "duplicate"
env -u GH_TOKEN -u GITHUB_TOKEN gh pr edit <NUMBER> --add-label "needs-review"
--action flagExpensive operations (use sparingly):
Cheap operations (use freely):
Recommended workflow:
--days 7 to triage recent PRs--days 30 for broader sweep--all for full audit (warn about cost)/pr-triage --repo opencode/opencode --days 7
Analyzes PRs updated in last 7 days, outputs report.
/pr-triage --repo anthropics/claude --all --output report.md
Analyzes all open PRs, writes report to file.
/pr-triage --repo microsoft/vscode --threshold 90
Only flags very obvious duplicates.
/pr-triage --repo facebook/react --days 30 --top 20
Shows only top 20 PRs by quality score.