Why Claude Code Action Only Links the Issue Number, Not the Customer
Because "Fixes #182" is GitHub's own vocabulary, not Claude's. GitHub has recognized a fixed set of closing keywords in a pull request description for years: close, fixes, resolves, and their variants, each followed by an issue number, on the repository's default branch. When Claude Code's GitHub Action turns an issue into a pull request, it writes that same line because it's the only phrasing that actually closes the issue on merge, and closing the issue is the point.
The customer's name drops out for two different reasons, and they compound. Most of the time, nothing handed Claude Code the name to begin with: the action's GitHub App is scoped to contents, issues, and pull requests, so it reads what's in the repo and writes back to the repo, and a person's company, their plan tier, whether this is their third report this month, none of that lives in a GitHub issue by default. On the days someone did write the name into the issue, the second reason takes over: summarizing a diff and remembering which account is watching it are two different jobs, and the PR description is only doing the first one.
Where "Fixes #182" actually comes from
GitHub's linking documentation is specific about this: close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved, each followed by # and a number, are the only strings GitHub parses to auto-close an issue when a PR merges to the default branch. Anything else in the description is just prose, as far as GitHub's parser is concerned.
Claude Code's GitHub Action doesn't add a proprietary version of this feature on top. Per the action's own FAQ, Claude "doesn't create PRs by default. Instead, it pushes commits to a branch and provides a link to a pre-filled PR submission page." Claude writes the description text going into that pre-filled page, and it writes a closing keyword into it for the same reason a human contributor would: it's fixing the issue it was pointed at, and this is how you say that in a way GitHub acts on.
The part of the story the repo can't see
The GitHub App permissions list eleven scopes in total, covering every Claude feature that touches GitHub. The Claude Code GitHub Action itself relies on three of them: Contents, Issues, and Pull requests, all read and write. Read and write access to your CRM, your support tool, or your billing system isn't in that list, and can't be, since it's a GitHub App and those aren't GitHub resources. Whatever Claude Code knows when it opens a PR, it knows because it's in the repo: the issue body, the linked comments, the code itself.
Most issue bodies don't carry a structured customer field either. GitHub issues have a title, a body, labels, and assignees. A reporter's employer sometimes shows up as a line of prose ("we're on the annual plan, this is blocking our rollout"), and just as often doesn't, because the person filing the bug is a support agent relaying it secondhand, or the original wording never got copied over when the ticket became a GitHub issue. Either way, there's no field for Claude to read reliably, so there's nothing reliable to put in the PR.
The renewal that shipped with no name on it
Kellan Ude maintains the API layer at Backline, a six-person uptime-monitoring startup. Three weeks earlier he'd wired up the Claude Code GitHub Action to turn labeled bugs into draft PRs automatically, and it had been working the way the setup guide describes: an issue gets bug and ready-for-agent, the action picks it up, a branch and a pre-filled PR link show up within the hour.
Issue #182 was a broken CSV export, filed by a support teammate who'd pasted in a customer's exact wording: "Denholm Freight says the export has been blank since Tuesday, they're mid-renewal and it's come up twice." Claude Code fixed the export, opened the PR, and the description read: "Fixes #182. The date-range filter was dropping rows when the export window crossed a month boundary. Added a regression test covering the boundary case." Correct, complete, and silent on who'd actually be relieved to see it ship.
Kellan, in the team's Slack: the export fix merged but the PR doesn't say denholm anywhere, i had to go back to the original issue to remember why we cared
Teammate: yeah it just reads the issue and the diff, it's not gonna know a renewal is riding on this one
Nobody had done anything wrong. The support teammate wrote the customer's name in the issue body, which is the right habit. Claude Code just never carried it forward, because summarizing a diff and remembering which account is watching it are two different jobs, and only one of them is written into a GitHub issue in a form an agent can count on.
The obvious fix looks cheap: tell Claude Code to pull any customer name already sitting in the issue body into the PR description. For issue #182 specifically, that would have worked, the name was right there in the second sentence. It's also the first thing most teams try, covered below, and it only closes the gap on issues where a human already wrote the name down before the agent ran. It does nothing for the far more common issue that never names a company at all, because the person filing it is a support agent relaying a case secondhand, or nobody triaging the bug thought a broken export needed a sales rep's context attached.
The workarounds teams try before changing anything structural
None of these require new tooling, which is why they're usually first:
- A PR template field. Add "Customer:" as a line in the pull request template, and hope whoever opens or edits the PR fills it in. Claude Code will follow a template if the prompt tells it to look for one, but it's copying text out of the issue body into a new slot, not looking anything up, so a vague issue still produces a blank field.
- A label convention, like
customer:denholm-freight, applied by whoever triages the issue. This makes the account visible in the tracker's UI, but it's manual at the exact moment someone is least likely to remember, right after filing a bug, and it says nothing about how urgent that account makes the fix. - Editing the PR by hand after the fact. Someone who knows the backstory adds a line before merge. It works once. It's also the same person doing the same lookup every time, which is the definition of not scaling past a few PRs a week.
All three depend on a human noticing the connection and typing it in, every time, before anyone downstream can act on it. Below a handful of customer-linked bugs a month, that's a fine tax to pay. Past that, PRs start shipping clean and the follow-up email to Denholm Freight either happens because someone happened to remember, or it doesn't happen at all.
Where this stops being a Claude Code problem
The fix isn't asking Claude Code to guess harder. It's giving it somewhere to look. Modem watches connected GitHub repos alongside your support tools and keeps a company profile attached to every bug report the moment it comes in, before an issue or a PR exists for it. Denholm Freight's report gets tied to the Denholm Freight account the same way any other conversation from them would, independent of whether the person filing the GitHub issue thought to write the company name down.
From there it's a config line, not custom scripting. Claude Code's --mcp-config flag already accepts arbitrary MCP servers, and Modem's MCP server answers exactly the kind of question a PR description needs: which account is attached to this topic. Point the action at it and the prompt can ask for the customer before it writes the summary, so "Fixes #182" gets a second line: "customer: Denholm Freight, renewal in progress." The Claude Code integration runs the same idea the other direction too, composing task descriptions for Claude Code from the underlying bug reports and topic data so the context arrives already attached rather than something the prompt has to go fetch. We build Modem, so weigh that against your own volume: a handful of customer-linked PRs a month is genuinely fine to handle by hand. The GitHub Action's own triage behavior, covered in our guide to triaging GitHub issues at scale, is still doing real work underneath this; it's just not the layer this particular gap lives in. The wider comparison of ways to close it is in tools that give Claude Code customer context.
The smallest version you can start this week
Skip the human template field and put the instruction in the action's own prompt instead. Add a line to your CLAUDE.md or the workflow's claude_args: when the issue body names a company, add a "customer:" line to the PR description before writing the closing keyword. That's a prompt change, not a new integration, and it would have caught Denholm Freight's issue on its own, since the name was already sitting in the text Claude Code read. It still only surfaces what's already written down. An issue that never mentions a customer gives the prompt nothing to extract, and ships exactly as blank as it always did.
