[BUG] /code-review --comment silently degrades to terminal printing when the forked agent lacks t he posting tools (repro on 2.1.237, after #84093 closed)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
/code-review <level> <pr-number> --comment is documented to post each finding as an inline comment on the PR's diff. In my run it printed the findings to the terminal instead, posted nothing to GitHub, and raised no error. The parent session's own explanation, verbatim:
In this session the forked agent had neither ReportFindings nor the GitHub inline-comment tool available to it, so it fell back to printing. The transport was missing, not the feature. Notably I do have ReportFindings in this session while the subagent did not.
So the flag's behaviour depends on which tools reach the forked review agent, and when the transport is missing it degrades silently: the run completes, the findings look delivered, and nothing is on the PR. Anything downstream that trusts the flag - a human who walks away expecting review threads, or an agent workflow that gates a merge on the posted record - discovers the gap only by independently re-querying the PR.
This is the same tool-absence class as #84093, which was closed COMPLETED after a maintainer could not reproduce on 2.1.233. I hit it on 2.1.237, through the --comment path. It is distinct from #84474, which is about the workflow-backed review posting through the GitHub MCP server and reporting success; here the forked agent had no posting transport at all and said so.
What Should Happen?
Either of these, and ideally both:
- The forked review agent always receives the tools the invocation's flags require -
ReportFindings, and whatever--commentposts throug
h.
- When the transport is missing, the run fails loudly instead of degrading: a clear "could not post inline comments: tool X unavailable" in
the result, not a normal-looking finding list in the terminal.
Error Messages/Logs
Steps to Reproduce
- Interactive session in a repo with an open PR (mine: a solo-maintainer repo, PR with an 8-finding diff).
- Run
/code-review high <pr-number> --comment. - The review runs and reports 8 findings with
file:linepointers - in the terminal only. gh api repos/<owner>/<repo>/pulls/<pr-number>/commentsreturns[]: nothing was posted, no error was raised.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.237 (Claude Code)
Platform
Other
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
- Platform: Linux (openSUSE Tumbleweed)
- Version: 2.1.237
- Interactive Ghostty terminal session (not
-p, not claude-code-action) - The exact command I typed:
/code-review high 78 --comment
3 Comments
Follow-up runs since I filed this, on 2.1.238 and 2.1.239. The short version: the tool absence is still there on 2.1.239, but the silent data loss is intermittent, because whether findings reach the PR depends on the agent improvising a fallback. That splits this report into two claims of different strength, and I think only one of them is really about
--comment.The three runs
| Version | PR | Findings |
ReportFindings/ inline-comment tool | Landed on the PR? ||---|---|---|---|---|
| 2.1.237 | groupifico#78 | 8 | agent reported both absent | No. Terminal only, no error |
| 2.1.238 | groupifico#82 | 8 | not established — see the correction below | Yes, all 8 |
| 2.1.239 | groupifico#146 | 2 | agent reported both absent | Yes, both — via
gh api|On 2.1.239 the forked agent said so itself, unprompted, in its result: that neither
ReportFindingsnor the inline-comment MCP tool was available to it, so it usedgh apiinstead. The findings landed at the right file and line, and the workaround was disclosed rather than hidden.Evidence from the 2.1.239 transcript
Not the agent's self-report this time. Its own transcript, at
~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl, records the whole exchange.1. The skill instructs the agent to use the tool:
2. The agent requests both tools by exact name, as deferred tools:
3. The harness answers that neither exists:
That same record carries
"version":"2.1.239".4. The agent then works around it, which is where the earlier "so I'll post via
gh api" line comes from. Across the entire run the tool invocations wereBash×22,Write×2,ToolSearch×2.ReportFindingswas never invoked, because it was never available to invoke.So this is not a case of the tool failing, being mis-called, or timing out. The agent asked the harness for the exact tool its own instructions name, and the harness said it does not exist. On 2.1.239.
A correction to my own reasoning, before anyone leans on it
I had drafted a "does not reproduce on 2.1.238" comment and did not post it. Good, because its central inference was wrong. It concluded "the transport was present and used" from the fact that all 8 findings appeared on the PR.
That inference does not hold. The 2.1.239 run posted its findings with the transport absent, by shelling out to
gh api. So a successful--commentrun is not evidence that the tools were provisioned, and the 2.1.238 row above has to stay unknown rather than be counted as a clean version. I never verified the tool list on that run, only the outcome.What I think this means for the report
Ask 1 — always give the forked agent the tools its flags require — is unaddressed and is the durable fix. The absence reproduces two versions on from the original, and it is the actual defect. Everything else is downstream of it.
Ask 2 — fail loudly instead of degrading — matters more than I realised, not less. I had assumed a fix would either provision the tools or make their absence loud. There is a third behaviour in the wild: the agent notices the gap and routes around it. That is the best outcome of the three, but it is a model improvising, not a guarantee, and it is exactly why the silent path must be closed. The same conditions produced total data loss on 2.1.237 and a clean result on 2.1.239, and nothing in the output of a successful run tells you which of those you were one coin-flip away from.
So: please don't close this on a non-reproduction of the symptom. The symptom is intermittent by nature. The provisioning gap underneath it is what to test for, and it is still present.
One fix the report itself needs
Step 4 of my repro has a false-positive path, and I walked into it myself on the 2.1.238 run.
GET /pulls/{n}/commentspages at 30. That PR already carried 28 inline comments from an unrelated discussion, so the unpaginated read returned 30 rows and showed only 2 of the 8 findings — indistinguishable from this bug.gh api --paginateshowed all 8.Anyone verifying this on a PR that already has inline discussion should paginate, or they will confirm the bug when it did not happen. Worth knowing if #84093 or #84474 were ever checked that way. The 2.1.239 run had zero prior inline comments, so it was not exposed to this.
Environment
-pand not claude-code-actionIf you inspect PR #146
The two finding comments have been edited since they were posted: I prefixed each with an AI-authorship disclaimer line and an
RF{n}id, because the tool posts under my account with no marker of its own and I want agent-written prose on my PRs labelled as such. The analysis's text below those added lines is untouched. Flagging it so the added lines are not read as something the tool emitted.Corroborating this on 2.1.246, through the plain
/code-reviewpath — no--comment, no PR target, no flags. So the tool-absence half of this is not specific to the posting transport, and it has survived from 2.1.237 to 2.1.246.I reached your quoted observation independently before finding this issue, which is why I'm adding to it rather than filing again.
What happened
/code-review against main nowin a local git repo. The skill forked a sidechain agent whose own prompt instructs it:The forked agent could not resolve the tool — not in its loaded schema, and not in its deferred registry:
It then said so in its final report and fell back to prose:
Meanwhile the parent session had
ReportFindingsin its eagerly-loaded schema at that same moment — same session, same process. Same asymmetry you quoted.The review itself was fine: it read the diff, verified findings, and reported two real ones. Nothing was lost here only because the skill prompt carries a fallback — "also restate the findings in your final reply [...] so they stay visible in sessions that do not render tool output". What is lost is the structured output the host UI renders, and anything keyed off it.
Ruled out locally
Different machine from the original report, and none of the usual suspects apply:
allowedTools,disallowedTools, ordisableToolsin~/.claude/settings.jsonor the project's.claude/settings.local.json~/.claude/agents/and no<project>/.claude/agents/— no custom agent definition narrowing the setEvidence is in the sidechain transcript at
~/.claude/projects/<project>/<session-id>/subagents/agent-<agent-id>.jsonl— theToolSearchcalls and their results are recorded verbatim.Possible mechanism — cf. #84125
#84125 reports the same shape for a different tool: present in the parent, absent from every subagent's tool set and its deferred registry, in interactive sessions, while the same dispatch under
claude -pdoes receive it. If that pruning is what's biting here too, then this issue and #84125 are one bug with two symptoms, and the--commentdegradation is a third.That's testable: run the same
/code-reviewunderclaude -pand see whether the forked agent getsReportFindings. Happy to run it and report back if it would help.Suggestion
Whatever the mechanism, the forked review agent's prompt should not instruct it to call a tool the fork isn't granted. Either grant it, or make the prompt conditional on what the fork actually has — right now the instruction and the tool set disagree, and only the skill's prose fallback keeps the run usable.
Ran the
claude -ptest I offered above. It confirms the #84125 mechanism: this is interactive-only tool pruning, not anything specific to/code-review.Same machine, same repo, same version (2.1.246), same skill, same fork. The only variable is session mode.
Interactive — fork cannot resolve the tool
Two further keyword queries, same result. The agent fell back to prose and said the tool was unavailable.
Headless (
claude -p "/code-review HEAD~1") — fork has it in its loaded schemaNo
ToolSearchcall at all — the fork never needed to look, becauseReportFindingswas already in its tool set. Its full tool list for the run was['Bash', 'ReportFindings'].What this means
The tool is granted to the forked review agent under
-pand withheld from it in an interactive session, on the same build. That is exactly the asymmetry #84125 describes forLSP:So #84125 is very likely not an LSP bug but a general subagent tool-pruning bug in interactive sessions, and this issue is a second symptom of it — with the
--commentdegradation in the original report as a third. Worth linking the two rather than fixing them separately.The forked prompt telling the agent to call a tool the fork isn't granted is still worth fixing on its own, since that's what turns the pruning into a silent degradation rather than a clear error.
Reproduction is two commands in any git repo with a commit to review, comparing the
subagents/*.jsonltranscripts of each: