AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Find Issues

skill-shiminshen-oss-contribute-find-issues · by shiminshen

Find ripe open-source issues you could actually contribute to — runs across the user's watched-repo list, filters by language/stack/budget, scores each candidate by "is this ripe" signals (no assignee, no linked PR, small scope, recent maintainer activity), and outputs a ranked shortlist with a one-line "why this one". Hands off to /oss-contribute:contribute-upstream once the user picks one.

No reviews yet
0 installs
20 views
0.0% view→install

Install

$ agentstack add skill-shiminshen-oss-contribute-find-issues

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-shiminshen-oss-contribute-find-issues)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Find Issues? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

find-issues

The proactive sibling of contribute-upstream. Use when the user wants to shop for an OSS contribution rather than fix a specific bug they hit. The reactive path is contribute-upstream — when in doubt, suggest that one instead, because the user-brought-bug signal beats any ranking heuristic.

Usage

/oss-contribute:find-issues                                # use profile defaults
/oss-contribute:find-issues --lang typescript              # filter by language
/oss-contribute:find-issues --repo better-auth/better-auth # focus on one repo
/oss-contribute:find-issues --budget 30m | 1h | weekend    # only suggest issues that fit
/oss-contribute:find-issues --refresh                      # ignore any cached results
/oss-contribute:find-issues --trending [daily|weekly]      # discover repos via github.com/trending (default: daily)

Stable preferences live in the shared profile (see "Profile location" below). Args are per-invocation overrides only. Cap at the flags above — if you need more knobs, edit the profile.

Profile location

Read the profile in this order:

  1. $CLAUDE_PLUGIN_DATA/profile.md — when running as an installed plugin (Claude Code sets this env var)
  2. ~/.claude/plugins/data/oss-contribute/profile.md — fallback for direct-installed plugins
  3. ~/.claude/skills/oss-contribute/profile.md — fallback for local-development mode

If none exist, dispatch to the profile skill to set one up before continuing.

Phase 1 — Load (or create) the profile

If the profile is missing, dispatch to the profile skill's interactive setup, then resume.

The profile covers:

  • Watched repos — explicit owner/repo list. No "popular repos" autodiscovery; the user names them.
  • Languages / stacks — e.g. typescript, go, python, plus framework expertise.
  • GitHub account — which logged-in gh account to fork/PR from.
  • Default budget30m, 1h, half-day, weekend.
  • What "ripe" means — heuristic seed for ranking.

Phase 2 — Discover candidates

> Trending mode (--trending): expand the candidate pool with repos from github.com/trending/ before per-repo issue search. See "Trending-mode discovery" below — it adds an extra repo-list-building step that runs before the per-repo subagents fan out. Everything after that is identical to the default path.

Dispatch one general-purpose subagent per repo in a single message. Not one-at-a-time — one message containing N parallel Agent tool calls, where N = number of watched repos. The instructions read sequentially but the calls must be batched; otherwise the model often serialises them.

Each subagent: fetches recent open issues (last 7d, sorted by created), filters to bugs with 0–1 comments, runs the token-based dup-PR search from Phase 3 against each, and returns a compact list (≤5 candidates × ≤3 lines each) with verdict. Aggregate in the main agent. This keeps raw gh search issues JSON out of the main context window.

Per-repo subagent prompt skeleton:

  • Repo: /
  • Profile stack: `` (only for relevance scoring; do not filter by GFI/HW labels — see profile rule)
  • Return: top 5 ripe candidates (no dup PRs by token search, no assignees, ≤1 comment, opened in last 7d), one line each with repo#N — title — why-ripe. If 0 ripe, say "0 ripe in this repo".

Single-query label search (use this, not N separate --label calls)

gh search issues --label is AND, not OR. Do not run one call per label and merge — that's 3× the API round-trips. Use --query with an OR expression so the labels collapse into a single search:

gh search issues --json number,title,labels,assignees,createdAt,updatedAt,url \
  --query 'repo:/ state:open created:>= (label:"good first issue" OR label:"help wanted" OR label:"bug") sort:created-desc' \
  --limit 30

(Drop the created: filter in --repo focus mode, where older reaction-sorted bugs are fair game — the subsystem-stall gate in Phase 3 exists for those.)

Cap the total candidate pool at ~60 across all repos before triage, to keep Phase 3 cheap.

Phase 3 — Triage each candidate

Batch-fetch enrichment via GraphQL (use this, not N separate gh issue view calls)

gh issue view --json is one round-trip per candidate. For 30 candidates that's 30 round-trips. Use one GraphQL call instead:

GitHub has no bulk issues-by-number field — build the query with one aliased issue(number:) field per candidate, all sharing a fragment:

gh api graphql -F owner= -F repo= -f query='
  query($owner:String!,$repo:String!){
    repository(owner:$owner,name:$repo){
      i: issue(number:){...F}
      i: issue(number:){...F}
    }
  }
  fragment F on Issue {
    number title body createdAt updatedAt
    assignees(first:5){nodes{login}}
    labels(first:20){nodes{name}}
    comments(last:3){nodes{author{login} body createdAt}}
    closedByPullRequestsReferences(first:5){nodes{number state}}
    timelineItems(last:10,itemTypes:[CROSS_REFERENCED_EVENT,CONNECTED_EVENT,ASSIGNED_EVENT]){
      nodes{__typename
        ... on CrossReferencedEvent{source{__typename ... on PullRequest{number state title createdAt}}}
        ... on ConnectedEvent{subject{__typename ... on PullRequest{number state title}}}}
    }
  }'

Tolerate partial errors. A number that resolves to a PR (or nothing) returns null for that alias plus an errors entry, and gh exits non-zero — but data for the other aliases still comes back on stdout. Parse the output regardless of exit code; treat the batch as failed only if data itself is absent. The point is one round-trip, not N.

Fallback if GraphQL is unavailable: dispatch the per-issue calls in a single message, one Bash tool call per candidate, batched in parallel. Not sequentially. gh issue view --json has no timelineItems field — pair it with the REST timeline endpoint to get the cross-referenced PRs:

gh issue view  --repo / --json \
  assignees,labels,comments,closedByPullRequestsReferences,body,createdAt,updatedAt
gh api repos///issues//timeline --jq \
  '[.[] | select(.event=="cross-referenced" and .source.issue.pull_request)
    | {number:.source.issue.number, state:.source.issue.state,
       merged:(.source.issue.pull_request.merged_at!=null), title:.source.issue.title}]'

Drop the candidate if any of these is true:

  • It has an assignee.
  • closedByPullRequestsReferences is non-empty, OR the enrichment timelineItems shows a cross-referenced/connected PR that is open or merged. (closedByPullRequestsReferences lists only PRs that closed the issue, so a dup that didn't auto-close it hides from that field but shows in the timeline.) A closed-not-merged cross-ref does not auto-drop — route it through the triage in "Duplicate-PR search" below, which decides.
  • An open PR for the same fix exists (see "Duplicate-PR search" below).
  • The most recent maintainer comment says "we're working on this" / "PR incoming".
  • It's labelled needs: info, wontfix, discussion, rfc, or similar non-actionable.
  • It's older than 6 months with no activity.
  • An AI-bot comment claims it's already fixed. Treat comments from accounts ending in -agent, -bot, [bot], or self-disclosed AI agents as hypotheses, not facts. Verify: (a) the referenced PR exists and is merged via gh pr view, (b) any version number claim matches the actual npm registry (npm view version). Bots fabricate version numbers that sound right. Documented case: vercel/ai#15302 had a kagura-agent comment correctly identifying merged PR #14102 as the fix but fabricating the version (@ai-sdk/google-vertex@4.1.12 — actual latest on npm: 4.0.130). Drop the candidate only after confirming the fix is shipped; if the bot is wrong about shipping, the bug may still be live.
  • Reporter has offered to open the PR themselves (the "reporter-offered-patch" trap). When the issue body contains a ready-to-apply diff plus a self-claim like "Happy to open a PR", "I'll send a PR", "I'll open a PR shortly", or evidence the reporter already built+tested the fix locally — drop. No assignee is set only because the reporter hasn't pushed the button yet. Lifting their analysis + patch and beating them to the PR is rude in the community, reads as credit-stealing to maintainers, and produces a portfolio entry that's visibly someone else's work. Scan the issue body for: a full diff in fenced `diff blocks, a "Proposed fix" section authored by the reporter, or explicit offer phrases. Documented case: amruthpillai/reactive-resume#3077 (2026-05-16, reporter netooran filed a complete two-file diff + said "Happy to open a PR with the patch above. Verified the fix end-to-end") — surfaced only at Phase 1 of contribute-upstream after the scout had already shortlisted it as "ready diff = best candidate". Catch this in find-issues, not later.
  • Subsystem stall. When reaction-sorting surfaces an older bug (3+ months old, high engagement), check for open PRs targeting the same file/subsystem. If ≥3 of them are in REVIEW_REQUIRED state with created == updated (opened then never iterated), the subsystem is review-stalled — the maintainers are merging other areas but leaving this one to rot. Whole-repo merge cadence (50 PRs/7d) can be high while the specific subsystem is dead. Drop. Documented case: vercel/ai#6974 (controller-close race on stream resume, maintainer @lgrammel reproduced 2025-08-29) — 4 separate PRs (#12875, #13209, #13851, #14689) all sat untouched since open-date.
  • Scope/intent ambiguity (feature gone, not bug). For issues filed against a vN.0.0-beta/rc.M of a package mid-rewrite, briefly check whether the missing thing exists in the new code paths. If wholly absent, demote to issue-comment-only. Full criteria + documented case (drizzle-orm#5755) in contribute-upstream Phase 3 step 4.
  • Invitation-only upstream. Drop if the upstream's contributing doc or PR template contains "invitation only" / "do not accept unsolicited" / "closed without review". Full check + documented case (openai/codex) in contribute-upstream Phase 1 step 2. Also drop on invitation-by-fast-close evidence even without the literal phrase — see Phase 2 "Invitation-by-fast-close" tier; documented case earendil-works/pi (2026-05-19).

Duplicate-PR search

Issue-title keywords miss PRs whose title describes the implementation rather than the symptom. Search by tokens extracted from the issue body, not by paraphrases of the title.

Dispatch all token queries in parallel. Send ONE message containing one Bash tool call per token type — not 4–5 sequential calls. Inspect all results together and short-circuit if any returns a PR hit.

The issue's own timeline is the authoritative cross-reference — it catches a PR whose title shares no tokens with the issue (anything that says "fixes #N" or is manually linked), in any state. You already have it from the Phase 3 enrichment timelineItems — don't re-query it here, just act on it. The token searches below are the second net, for PRs that fix the bug without referencing the issue at all:

  1. The issue number itself. "#93700" and bare "93700" — many PR descriptions reference it. This query is mandatory on every candidate, including the Phase-4 re-check — never substitute code-identifier tokens for it.
  2. URL-encoded or other distinctive literals in the issue body — %5F, error codes, magic strings.
  3. Backticked code identifiers from the issue body — function names, file paths, type names (e.g. ` LayoutRoutes , buildUpdateSet ). Also include: import paths, augmented-module names from declare module 'X' { ... } blocks, and interface names being augmented (e.g. Register, Routes`). Module-augmentation bugs are paraphrased away by title-keyword search.
  4. Error message fragments quoted in the body, if any.

Search ALL states, not just opengh search prs --repo / --limit 5 (no --state filter; add --json number,title,state,createdAt to read state). A --state open-only search is the bug that shipped a dead candidate: it silently skips a closed-not-merged PR for the exact fix, which is a louder signal than an open one (see below).

A title-keyword search alone is not enough. Documented failure cases:

  • Issue titled "Layouts for paths that start with underscore (%5F)…" had an open PR titled "fix(typegen): normalize %5F to _…" — caught only by the %5F token search.
  • TanStack/router#7399 ("server entry boilerplate gives type error") had open PR #7357 ("fix(start): import Register from framework package so module augmentation works"). Token search using title-paraphrases server,boilerplate returned nothing; the dup was caught only when the body tokens createServerEntry, Register, requestContext were tried.

Interpreting a non-open hit. gh search prs --json state returns merged as a distinct state, so merged vs. closed-not-merged is readable straight from the search results:

  • Merged → the fix already shipped; the issue just didn't auto-close (no "fixes #N" keyword in the PR body). Drop.

If the PR is closed-and-unmerged, do NOT silently treat the issue as ripe — inspect why it closed with gh pr view --repo / --json state,mergedAt,author,closedAt,comments,reviews,labels:

  • Approach rejected by a maintainer (review comment explaining a different design, or "we don't want this") → the issue is design-sensitive; demote to issue-comment-only or drop. A fresh PR with the same approach will be rejected too.
  • Auto-closed by an anti-AI-PR bot. A bot/github-actions comment like "labeled maybe automated because it appears to have been fully generated by AI" or any "confirm you are a real human / disclose if automated" gate means the repo auto-kills AI-generated PRs. This is an anti-agent policy (same family as immich/transformers/playwright) — it is near-fatal for this flow regardless of issue ripeness. Drop the candidate AND surface the repo as a skip-list addition (anti-AI-PR auto-close). The issue may still be technically ripe for a human, but not for a Claude-driven PR.
  • Abandoned by author (closed with no review, no bot, often by the author themselves) → genuinely re-openable; the issue can stay a candidate, but say so explicitly in the why-line so the user knows a prior attempt exists.

Documented failure case: 2026-06-09 trending hunt ranked vitest-dev/vitest#10491 (negated --project filters) as the #1 pick. A --state open dup-search and a code-identifier-token re-check both missed PR #10492 — opened and auto-closed within ~2h after vitest's bot labeled it maybe automated ("appears to have been fully generated by AI"). Caught only when the user asked "did someone already do this?" Two lessons: search all states (the dup was closed), and act on the enrichment timeline's cross-referenced PRs even when closedByPullRequestsReferences is empty. Bonus: vitest belongs on the skip list (anti-AI-PR auto-close bot).

If a token query or the timeline returns an open or merged PR, or a closed-not-merged PR that falls in the "rejected" or "anti-AI-bot" buckets above, drop the candidate.

For each survivor, score on:

  • Repro quality — does the body have steps + expected vs actual?
  • Scope estimateone-liner / small / medium / large. Drop large from a "weekend"-budget shortlist.
  • Stack match — overlap with the user's languages/frameworks.
  • Repo activity (merge-likelihood) — see below. Boost candidates from repos that actively merge PRs.
  • Maintainer signal — has a maintainer triaged/labelled it?

Repo activity scoring (merge-likelihood)

Issues in repos that don't merge anything are dead ends. Issues in repos that merge weekly are bets worth making. Fetch repo-level signals once per watched repo, in parallel with Phase 2's issue search — not per-candidate.

For each

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.