SkillAgentSearch skills...

github-triage

Triages a repository's open GitHub issues and pull requests via the gh CLI. Optionally reviews and merges ready PRs — incrementally merging passing automated/bot PRs and maintainer-approved ones, and spawning review subagents for never-reviewed ones — then closes already-resolved issues with comment…

Install / Use

npx skills add trailofbits/skills --skill github-triage

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

96/100

Category

Automation

Supported Platforms

Universal

Our assessment of github-triage

github-triage scores 96/100 on our quality scale, 181st of 1,990 Automation skills we index (top 10%).

Its SKILL.md is 23 KB long, well organised into 25 sections with 9 code examples: a thorough specification that gives an agent plenty to work with.

With 7,225 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
16/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 4 days ago, so github-triage is actively maintained.
  • It is released under the CC-BY-SA-4.0 license; check its terms before commercial use.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.

Automated pattern scan on 2026-09-28. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

github-triage compared with similar skills

All 4 of these similar skills score higher than github-triage; compare them before choosing.

SkillScoreStarsUpdatedFormat
github-triage (this skill)by trailofbits967.2k4d agoSKILL.md
Agent-Reachby Panniantong10085.8k12d agoCLAUDE.md
rufloby ruvnet10073.4ktodayCLAUDE.md
Scraplingby D4Vinci10084.1ktodayMCP Server
algorithmic-artby anthropics100177.9k5d agoSKILL.md

Frequently asked questions

How do I install github-triage?
Run npx skills add trailofbits/skills --skill github-triage. The install tabs above show the steps for each supported agent.
Which AI agents does github-triage work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is github-triage safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is CC-BY-SA-4.0-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is github-triage still maintained?
The repository was last updated 4 days ago, so github-triage is actively maintained.

name: github-triage description: "Triages a repository's open GitHub issues and pull requests via the gh CLI. Optionally reviews and merges ready PRs — incrementally merging passing automated/bot PRs and maintainer-approved ones, and spawning review subagents for never-reviewed ones — then closes already-resolved issues with comments citing the resolving PR or commit, cross-links issues with their pending fix PRs, and assigns local-only priority and change-size estimates for everything outstanding. Use when triaging, grooming, or reviewing a repository's open issues and PRs." disable-model-invocation: true allowed-tools: Bash Read Grep Agent AskUserQuestion Write

GitHub Triage

Triage a repository's open GitHub issues and pull requests. Optionally clear ready PRs first (merge passing bot PRs and maintainer-approved PRs, review never-reviewed ones), then close issues that are already resolved (with a comment citing the PR or commit that resolved them), make sure issues and the pending PRs that fix them reference each other, and assign a local-only priority and change-size estimate to every issue that is still outstanding.

When to Use

  • When the user runs /github-triage to groom or review a repository's open issues and pull requests.
  • When an issue backlog has drifted: resolved work left open, fixes landed without closing their issues, or PRs in flight that never linked their issue.
  • When ready PRs have piled up (passing dependency bumps, approved-and-green PRs) or PRs are sitting unreviewed.

When NOT to Use

  • Do not invoke automatically. This skill performs irreversible GitHub writes (merging PRs, closing issues, posting comments) and runs only on explicit invocation.
  • Do not use to apply priority/effort labels on GitHub. Priority and size are presented locally only and are never posted (see Safety Rules).
  • Do not use as a substitute for a human's final merge decision — every merge is proposed for explicit approval, never performed autonomously.

Core Principles

  1. Writes are gated. Compute the full triage first, present every proposed write — merges included — for review, and execute nothing until the user approves.
  2. Evidence before closing. Never close an issue without a concrete, cited reason (a merged PR or a commit on the default branch). When evidence is weak or ambiguous, leave the issue outstanding and flag it for review.
  3. Priority and size stay local. They are an internal planning aid for the user, never written to GitHub.

Workflow

Phase 0: Select the target repository

gh auth status                       # confirm gh is authenticated
git rev-parse --is-inside-work-tree  # is PWD a git repository?
git remote -v                        # enumerate remotes

Determine the set of distinct GitHub-hosted repositories among the remotes. A remote is GitHub-hosted when its URL host is github.com, in any of these forms:

  • https://github.com/OWNER/REPO(.git)
  • git@github.com:OWNER/REPO(.git)
  • ssh://git@github.com/OWNER/REPO(.git)

Normalize each to OWNER/REPO and de-duplicate (a fork setup may have origin and upstream pointing at different GitHub repos; multiple remotes pointing at the same OWNER/REPO count once).

Selection rule:

| Situation | Action | |-----------|--------| | Exactly one distinct GitHub repo | Use it as the default — do not prompt. | | Not a git repo, or zero GitHub remotes | Ask the user for the OWNER/REPO to triage. | | More than one distinct GitHub repo | Use AskUserQuestion to let the user pick which OWNER/REPO. |

GitHub Enterprise hosts cannot be auto-detected reliably. If the user works on a GHE instance, ask for OWNER/REPO and have them set GH_HOST / use gh's configured host. Confirm the resolved repo back to the user before continuing.

Store the result as REPO="OWNER/REPO" and pass -R "$REPO" to every gh call. Validate it against ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ before use, so a malformed or hostile remote URL never flows into a command.

Phase 1: Gather issues and context

# Open issues (gh issue list excludes PRs by default)
gh issue list -R "$REPO" --state open --limit 1000 \
  --json number,title,body,labels,assignees,comments,reactionGroups,createdAt,updatedAt,url

# Open PRs — candidates for "pending fix" (issue phase) and PR triage (Phase 2)
gh pr list -R "$REPO" --state open --limit 1000 \
  --json number,title,body,author,isDraft,reviewDecision,latestReviews,\
mergeable,mergeStateStatus,statusCheckRollup,labels,createdAt,headRefName,url,closingIssuesReferences

# Recently merged PRs — candidates for "already resolved"
gh pr list -R "$REPO" --state merged --limit 300 \
  --json number,title,body,mergedAt,url,closingIssuesReferences

closingIssuesReferences lists the issues a PR is linked to close — populated by any of GitHub's closing keywords (close/closes/closed, fix/fixes/fixed, resolve/resolves/resolved) in the PR body, or by a manual UI link. It is the strongest available signal. For issues it does not cover, also search commit messages on the default branch. Resolve the default branch authoritatively from the selected repo (not from local origin/HEAD, which may be unset or point at the wrong remote):

default_branch=$(gh repo view "$REPO" --json defaultBranchRef --jq .defaultBranchRef.name)
# Anchor the issue number so #12 does not match #120, #123, …
git log --oneline "origin/$default_branch" \
  | grep -iE "(close|fix|resolve)[sd]? +#<N>([^0-9]|$)"

Phase 2: Triage open pull requests (optional)

Handle PRs before issues: merging ready PRs here means the "already resolved" check in the issue phase sees the work those merges just landed.

If there are no open PRs, skip this phase. Otherwise summarize the open PRs and ask the user whether to handle PRs now (AskUserQuestion: handle PRs / skip to issues). If they skip, go straight to issue classification.

Classify each open PR from its review, CI, and merge state. The field shapes below are what gh pr ... --json actually returns — rely on them, not on intuition:

  • Ready to merge = mergeable == "MERGEABLE" and mergeStateStatus == "CLEAN" and CI is not blocking (below). CLEAN is GitHub's server-side "no conflicts, not behind, not draft, required checks green" verdict — any other mergeStateStatus (BEHIND, UNSTABLE, BLOCKED, DIRTY, DRAFT, …) is not ready. Treat mergeable == "UNKNOWN" (GitHub recomputes mergeability lazily, especially right after another merge) as not ready — re-poll briefly or skip; never merge on it.
  • CI not blocking — scan statusCheckRollup (keyed on __typename) and reject the PR only on a real problem: a hard failure (a CheckRun whose conclusion is FAILURE/CANCELLED/TIMED_OUT/ACTION_REQUIRED/STARTUP_FAILURE/STALE, or a StatusContext whose state is FAILURE/ERROR), or anything still running (a CheckRun status of QUEUED/IN_PROGRESS/WAITING/PENDING, or a StatusContext state of PENDING/EXPECTED — wait, do not merge yet). SUCCESS, NEUTRAL, and SKIPPED are fine and must not block (e.g. a CodeQL run that reports NEUTRAL on a dependency bump — a green Dependabot PR is CLEAN with a NEUTRAL CodeQL check). An empty rollup is no CI — a distinct state, never treated as ready. mergeStateStatus == "CLEAN" already reflects required-check status; use the rollup to catch failing/pending non-required checks.
  • Bot/automated = author.is_bot == true. Match the auto-merge allowlist against author.login after normalizing away gh's rendering — strip a leading app/ and a trailing [bot] (gh returns Dependabot as app/dependabot in some versions and dependabot[bot] in others; normalize both to dependabot). Allowlisted by default: dependabot, renovate, plus any the user names. A passing PR from a non-allowlisted bot is reported, never offered for merge.
  • Maintainer-approved = latestReviews has an entry with state == "APPROVED" whose authorAssociation is OWNER/MEMBER/COLLABORATOR and whose author.login is not the PR author. Do not use reviewDecision == "APPROVED" alone: it is branch-protection-driven and is null on repos with no required-review rule, so it both over-trusts (cannot confirm write access) and misses genuine approvals.
  • Never reviewed = latestReviews has no APPROVED/CHANGES_REQUESTED entry from anyone other than the PR author (a fork "review disabled" bot comment is not review).

| Category | Condition | Offered action | |----------|-----------|----------------| | Mergeable bot PR | allowlisted bot + ready + not draft | Offer incremental, in-order merge | | Approved & ready | maintainer-approved + ready + not draft | Prompt to merge | | Never reviewed | non-bot + only the author has reviewed (or no reviews) + not draft | Offer to spawn a review subagent | | Needs work | draft, hard CI failure, pending CI, conflicts, behind, changes requested, or a bot PR that is not ready | Report only — no action offered |

("ready" already subsumes CI-not-blocking. Review subagents are for human-authored PRs — a bot's dependency bump that is not ready is reported as Needs work, not reviewed.)

Present the categorized PRs and offer the applicable actions via AskUserQuestion.

Incremental, in-order merge (bot PRs and approved-ready PRs): confirm the merge set and the merge method first (merging is irreversible), then merge one at a time, oldest first. Choose a method the repo allows and fail closed if it does not:

gh repo view "$REPO" --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed   # positional repo, not -R

For each PR in order, re-verify immediately before merging (state drifts after each merge — a landed PR can leave the next BEHIND, conflicting, or recomputing), merge synchronously, then confirm it landed before advancing:

gh pr view <N> -R "$REPO" --json isDraft,reviewDecision,mergeable,mergeStateStatus,statusCheckRollup
# proceed only if still ready: not draft, mergeable == MERGEABLE, mergeStateStatus == CLEAN, CI not blocking
gh pr merge <N> -R "$REPO" --<method>     # never --auto, never --admin
gh pr view <N> -R "$REPO" --json state    # expect "MERGED" before moving to the next PR

Stop and report if a PR is no longer ready (including mergeable == "UNKNOWN"), if the merge did not land, or if any required check is not green — never force, --admin, --auto, or skip a check. For bot PRs, surface the dependency and version jump (e.g. major bumps) in the gate so the user can decide with context.

Review subagents (never-reviewed PRs): when the user opts in, spawn one Agent per PR — all in a single assistant message so they run in parallel. Each subagent reviews one PR's diff and returns a structured review; write each to github-pr-<number>-review.md in the working directory (overwriting any prior file for that PR). Reviews are read-only and never posted to GitHub. See references/reviewing-prs.md for the subagent prompt, review rubric, and file format.

After any merges, re-fetch the merged-PR list (the Phase 1 --state merged query) so the issue phase can detect issues those merges resolved.

Phase 3: Classify each open issue

Sort every open issue into exactly one bucket.

Bucket A — Already resolved (the work landed, the issue was left open). Requires concrete evidence; prefer corroboration over a single weak signal:

  • A merged PR lists the issue in closingIssuesReferences, or its title/body references #N alongside a closing keyword. (Strongest.)
  • A commit on the default branch references #N with a closing keyword.
  • The behavior the issue asks for **demonstrably exists in the current code

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars7.2k
CategoryAutomation
Updated4d ago
Forks615

Languages

Python

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions