[BUG] gitOperation reports PR "created" when a command merely mentions "gh pr create"

Status Open
Reported on v2.1.285
Maintainer reply None cached
Activity 0 comments · opened Sep 30, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

The gitOperation record attached to Bash tool results (tool_response.gitOperation in PostToolUse hook payloads, toolUseResult.gitOperation in transcripts) reports {"pr": {"action": "created", ...}} for commands that only mention gh pr create and happen to print some PR URL. No PR is created.

Judging from the 2.1.285 bundle, the record comes from two independent guesses:

  • action: the regex \bgh\s+pr\s+create\b (and its edit, merge, comment, … siblings) is matched against the raw command string. Text inside quotes, heredocs, SQL string literals and grep patterns all counts. The quote-stripping regex the same module uses elsewhere (/"(?:[^"\\]|\\.)*"|'[^']*'/g) is not applied to the action lookup.
  • url/number: the last PR-shaped URL anywhere in stdout, whatever produced it.

Because the two are never cross-checked, any command that mentions gh pr create and prints an existing PR URL is reported as creating that PR. In practice I hit this with a read-only python3 query containing LIKE '...gh pr create%' that printed a URL from a database. The session was then attributed a PR that a different session had opened.

What Should Happen?

action: "created" should only be reported when the command actually invokes gh pr create (or glab mr create), i.e. matched at a command position after stripping quoted strings and heredoc bodies. The reported URL should be the one that invocation printed. Returning no gitOperation at all when this can't be determined would be better than a wrong one: hook consumers have no way to tell a guessed record from a real one.

Error Messages/Logs

{
  "command": "echo \"reminder: run gh pr create later\"; echo \"unrelated link: https://github.com/acme/widgets/pull/12345 (just mentioned)\"",
  "gitOperation": {
    "pr": { "action": "created", "number": 12345, "url": "https://github.com/acme/widgets/pull/12345" }
  },
  "stdout": "reminder: run gh pr create later\nunrelated link: https://github.com/acme/widgets/pull/12345 (just mentioned)"
}

(Taken from the PostToolUse hook payload for the Bash call below.)

Steps to Reproduce

  1. Configure a PostToolUse hook that logs its stdin payload, e.g. cat >> /tmp/posttooluse.jsonl.
  2. Ask Claude Code to run exactly this Bash command:

``
echo "reminder: run gh pr create later"; echo "unrelated link: https://github.com/acme/widgets/pull/12345 (just mentioned)"
``

  1. Look at tool_response.gitOperation in the logged payload. It says {"pr":{"action":"created","number":12345,"url":"https://github.com/acme/widgets/pull/12345"}}, although no PR was created and gh was never run.

The same PR detection may also drive the session's PR linking (code_change_published). I haven't verified that end to end.

Claude Model

Not model-related (client-side detection)

Is this a regression?

I don't know. gitOperation first appears in my hook logs around early June 2026.

Last Working Version

_No response_

Claude Code Version

2.1.285 (Claude Code)

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Not terminal-related (Bash tool result metadata)

Additional Information

Found while building a hook consumer (aichronicles) that records which PRs a session created. As a workaround it now only accepts the claim when the URL is a whole line of stdout, which is how gh pr create reports its PR. It would be much better if the record itself could be trusted.

View original on GitHub ↗