[BUG] /diff turn view: an image-only prompt does not start a turn, so its edits are folded into the previous turn or dropped

Status Open
Reported on v2.1.274
Maintainer reply None cached
Activity 1 comment · opened Sep 17, 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?

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

  1. In a git repo, fullscreen renderer, terminal wide enough for the /diff pane.
  2. Type a prompt such as add a comment to README.md and let Claude edit the file.
  3. Paste a screenshot into the prompt and send it with no text (for example, a screenshot of an error), so Claude makes another edit.
  4. Open /diff and switch to the turn tab: there is one turn, T1 "add a comment…", and it lists the second edit too.
  5. 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:

https://github.com/anthropics/claude-code/compare/main...farmer-data:claude-code-1:fix/diff-turn-view-image-only-prompt

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 N with no quote. A "(image)" placeholder would be friendlier, but SessionMessage carries 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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗