Stopping Claude Code's GitHub Triage From Missing Duplicate Issues
A Claude Code-powered triage bot almost always processes one issue at a time: the issue body, its comments, and whatever the bot can find by searching your codebase. Nothing in that loop hands it a copy of issue #340, #512, or #781 to compare the new report against. The bot can tell you a report looks real, matches a code path it can find, or fits a label. It usually cannot tell you someone already filed the same complaint three weeks ago, because that earlier issue was never part of what it read.
That gap holds even for the more capable setups people build on Claude Code. A developer ran into exactly this limit and built a standalone triage tool on the Claude Code SDK specifically to give per-issue triage codebase understanding, not just labels. Read the tool's own prompt template, though, and the message it sends to Claude for each issue contains that issue's title, body, and comments, plus permission to search the project's codebase. It does not contain a list of the other open issues to check against. Codebase search answers "does this bug make sense given the code," not "has this been reported before."
What a label taxonomy alone looks at
GitHub's own example of an agentic triage workflow shows what a label-only setup looks like in practice. It reads a new issue and assigns one label from a fixed list: bug, feature, enhancement, documentation, question, help-wanted, or good-first-issue, per GitHub's own workflow examples. It does look at the codebase to write a useful explanatory comment back to the reporter. What it doesn't do is compare the new issue's content against anything else already open. There's no "duplicate" option in that label list, and no step that pulls up similar issues, because the workflow was built to categorize one report, not to relate it to every other report sitting in the tracker.
That's a reasonable design for the job it does. It just means "the bot labeled it bug" tells you nothing about whether it's the fifth bug this month describing the same crash.
What deep codebase context adds, and what it still skips
The Claude Code SDK tool linked above is a real improvement over label-only bots for one specific failure mode: a report that's stale, already fixed, or contradicted by the code as written. Searching the codebase catches those, because the answer lives in the repo the bot is standing inside of.
It does not, as shipped, catch a duplicate the way a person scanning the issue list would. The tool fetches one issue and its comments, runs that through Claude with codebase search enabled, and writes a SHOULD_CLOSE / LABELS / CONFIDENCE recommendation to a markdown file. It processes multiple issues concurrently by design, so three near-identical reports filed the same week can run through triage in parallel, each in its own isolated session, each with no idea the other two exist. Finding that connection depends on comparing two issues' actual text side by side, and nothing in the pipeline does that comparison.
You could extend it to do so, pulling a list of open issue titles into the prompt before triage runs. That's a real fix for a single repo at moderate volume, and it's worth doing if you're running a setup like this one. It's also the kind of change that has to be built and maintained by hand; it isn't a feature the tool ships with.
The same firmware bug, filed three times, labeled correctly three times
Picture a two-person firmware team supporting arm attachments for warehouse robots, shipping updates to field technicians who install them on-site. They split maintenance across a companion-app repo and a firmware repo, and they run a Claude Code-based triage script, close in shape to the one described above, against new issues in the firmware repo: read the issue, search the codebase, suggest a kind label and a confidence level.
In the same week, three field technicians each opened an issue after updating to firmware 4.2:
Issue #188 (technician in Ohio): "Arm calibration drifts within an hour of the update. Recalibrating doesn't stick."
Issue #191 (technician in Texas): "Since 4.2, the gripper offset resets itself. Have to redo calibration every shift."
Issue #196 (technician in Georgia): "Calibration doesn't hold after the firmware push last week. Anyone else seeing this?"
The triage bot ran on all three, independently. Each session searched the calibration module, found the recent change to the offset-persistence logic in 4.2, and correctly labeled each issue bug, firmware, confidence: high. Three accurate, well-reasoned recommendations. What none of the three sessions did was notice the other two existed. One of the maintainers spotted the connection four days later, while scrolling the issue list looking for something else. By then a fourth report had come in, from a technician whose calibration had drifted mid-shift on a live job.
Extending the prompt yourself hits a ceiling
Feeding a list of open issue titles into the triage prompt closes the gap for one repo. It stops closing it once any of the following is true:
- Reports span more than one repo. This team's field-reported bugs sometimes land in the firmware repo and sometimes in the companion-app repo, depending on which team member the technician happens to know. A per-repo issue list never crosses that boundary.
- The earlier report isn't a GitHub issue yet. A technician calls support before anyone files anything, or a note lands in the Slack channel the team uses for field escalations. The triage bot only ever sees GitHub, so a report that hasn't been turned into an issue is invisible to it no matter how good its prompt is.
- The issue list itself gets long. Passing every open issue's title and body into every triage run is fine at a few dozen open issues. It stops being cheap or fast once a repo holds several hundred, which is exactly when duplicate pressure is highest.
Duplicates get expensive at exactly the volume where a compare-against-everything prompt turns too slow and too costly to run on every issue. This is the same wall covered in more general terms in our guide on triaging GitHub issues at scale, and it's a different failure mode than the one covered in whether GitHub itself can catch duplicates before they pile up. That guide is about GitHub's own native suggestion feature, which is repo-scoped in a different way and doesn't touch Claude Code at all.
At that point we'd point you toward Modem. It watches GitHub repos you connect next to Slack, Zendesk, and whatever else your team reports bugs into, and it clusters a report against prior reports of the same underlying problem before either one becomes a separate filed issue. The firmware team's three reports would land as one topic with three linked issues and a running count, regardless of which repo or channel each technician happened to use. The dedupe step runs upstream of triage instead of depending on a per-issue prompt to fetch and compare an ever-growing issue list. We build Modem, so weigh that against the honest alternative. If your reports genuinely stay inside one repo and issue volume is low enough that a manually extended triage prompt keeps up, you don't need to add anything past what's described above.
One prompt change to make before anything else
If you're running a Claude Code triage bot today, add one check before it does anything else: pull the titles of the last 30 to 50 open issues in the same repo and pass them to the model with an explicit instruction, "flag if this looks like any of these," before the codebase search runs. It's a small prompt change, it costs one more API call's worth of context, and it will catch the same-repo, same-week duplicates that currently slip through three parallel, unaware sessions. It won't reach across repos or catch a report that hasn't become a GitHub issue yet, but it closes the gap that's costing you the most right now.
