[BUG] /diff turn view: an image-only prompt does not start a turn, so its edits are folded into the previous turn or dropped
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?
In the turn tab of /diff, a prompt sent as an image alone (a pasted screenshot with no text) never starts a turn. Two visible results:
| Session | Turn tab shows |
|---|---|
| Prompt "first" → Claude edits a.ts; then a screenshot alone → Claude creates b.ts | One turn, T1 "first", listing both a.ts and b.ts |
| Only prompt is a screenshot alone → Claude edits a.ts | No turns at all (the tab is empty although the git tab shows the edit) |
Root cause — mods/diff/hooks/turns/turn-of/is-prompt-row/is-prompt-row.ts:
export const isPromptRow = (message: SessionMessage) =>
message.role === 'user' &&
(message.toolResults === undefined || message.toolResults.length === 0) &&
message.text !== ''
turnDiffsOf starts a turn at every row isPromptRow accepts. The text !== '' clause was presumably meant to skip non-prompt user rows, but the toolResults check already does that, and it also rejects a real prompt with no text. SessionMessage.text is documented as "its text blocks joined; '' when it has none", and that is what the engine records for an image-only prompt. I checked with a small function-hooks plugin that writes $.session.messages() at turn.complete, driving claude 2.1.274 in print mode (--input-format stream-json) with a user message whose only content block is an image:
{ "role": "user", "text": "", "toolUses": [] }
No toolResults, empty text → not a turn start. The edits in that turn are then attributed to whichever earlier prompt did start a turn, or to nothing when there is none.
What Should Happen?
A user row with no tool results is a prompt whatever its text. An image-only prompt should start its own turn (Turn N, with no quoted preview — pane-state/turn-title-of already draws an empty preview as no subtitle), and its edits should be listed under it.
Error Messages/Logs
Two tests added beside the existing ones in mods/diff/tests/turns/turn-diffs-of.test.ts, on current main (68ac8bb):
(fail) turn-diffs-of > an image-only prompt (empty text, no tool results) starts its own turn
Expected: [[2, ""], [1, "first"]]
Received: [[1, "first"]]
(fail) turn-diffs-of > a session whose only prompt is image-only still lists its edits
Expected: length 1
Received: length 0
Steps to Reproduce
- In a git repo, fullscreen renderer, terminal wide enough for the
/diffpane. - Type a prompt such as
add a comment to README.mdand let Claude edit the file. - Paste a screenshot into the prompt and send it with no text (for example, a screenshot of an error), so Claude makes another edit.
- Open
/diffand switch to the turn tab: there is one turn,T1 "add a comment…", and it lists the second edit too. - Start a fresh session and send a screenshot alone as the first prompt; after Claude's edit, the turn tab lists nothing.
Or run the two tests above: CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude plugin test mods/diff.
Claude Model
Not model-specific
Is this a regression?
No, present since mods/diff was published (isPromptRow is unchanged since d9c456d)
Last Working Version
N/A
Claude Code Version
2.1.274 (Claude Code), mods/diff at main 68ac8bb
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Ghostty / zsh
Additional Information
Proposed fix, on a branch against current main, since PRs from outside accounts are not accepted here:
One commit: drop the text !== '' clause from isPromptRow (docstring updated) and add the two tests above. tsc -p mods/tsconfig.json passes; claude plugin test mods/diff is 144/144 on 2.1.274.
Two notes:
- The mod says it reads turns "as the built-in turn view" does, so the built-in may skip empty-text rows the same way; if so this is the same fix in both places.
- With the fix an image-only turn reads as
Turn Nwith no quote. A"(image)"placeholder would be friendlier, butSessionMessagecarries no attachment information, so that would need the engine to say so — a follow-up, not part of this change.
AI tools used: Claude Code (analysis, the probe plugin, tests and the patch); I reviewed and ran everything.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗