Skip to content

feat(api): forward pasted images through the claude CLI transport#159

Merged
BunsDev merged 1 commit into
mainfrom
feat/claude-cli-image-input
Jul 14, 2026
Merged

feat(api): forward pasted images through the claude CLI transport#159
BunsDev merged 1 commit into
mainfrom
feat/claude-cli-image-input

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

  • The Claude CLI transport (keyless path) now forwards pasted images to the claude binary as standard Anthropic image blocks, so image prompts work the same as on the direct API path.

Context

  • Related issue/user request: recovered from local work on main. Previously the CLI transport declared image_input: false and dropped pasted images silently.
  • Scope: crates/api/src/providers/claude_cli.rs only — image extraction from the latest user message, the stdin envelope shape, and the capability flag.
  • Non-goals: PDF/audio/video inputs; re-sending images from earlier turns (a resumed session already has them; a flattened restart has lost all non-text content). The recovered diff also made four helpers pub(crate) for a nonexistent "opencode CLI provider" — dropped as out of scope (providers are Claude and Codex only).

Changes

  • last_user_images(): image blocks from the latest user message.
  • stdin_line(prompt, images): images serialized in the Anthropic wire shape, placed before the text block (matching anthropic.rs); image-only prompts omit the empty text block.
  • spawn_turn(...) threads images through both the resume and fresh-session paths.
  • Capability image_input: true for the CLI transport.
  • Tests: envelope ordering, image-only prompts, latest-message-only extraction.

Validation

  • git diff --check — clean
  • cargo fmt --all--check clean
  • cargo check --workspace — clean
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo test --workspace — not run in full; see targeted
  • Targeted/manual checks: cargo test --package claurst-api -- claude_cli (12 passed, incl. 3 new image tests)
  • Not run: full workspace suite — CI runs it; the change is confined to one provider file with targeted coverage.

PR Readiness

  • Diff is limited to the intended files.
  • Generated files were not edited by hand.
  • User-facing docs/help were updated or are not needed.
  • No secrets, credentials, local paths, or unrelated logs are included.
  • Remaining risks or follow-up work are listed above.

Image blocks from the latest user message ride the stream-json stdin
envelope in the same Anthropic wire shape the direct API path uses,
placed before the text block. Image-only prompts omit the empty text
block. Earlier turns' images are not re-sent: a resumed session already
has them and a flattened restart lost the non-text content. Capability
image_input flips to true for the CLI transport.
Copilot AI review requested due to automatic review settings July 14, 2026 09:43
@BunsDev BunsDev added the enhancement New feature or request label Jul 14, 2026
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Jul 14, 2026 9:43am

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Claude CLI transport (the keyless path that shells out to the claude binary) to forward pasted images from the latest user message as standard Anthropic image content blocks, making image prompts behave consistently with the direct API transport.

Changes:

  • Add last_user_images() to extract image blocks from the latest user message only.
  • Update stdin stream-json envelope generation to include image blocks (before text) and to omit the text block for image-only prompts.
  • Thread images through the CLI spawn paths and advertise image_input: true in provider capabilities, with targeted tests for ordering and extraction rules.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +119 to +124
.map(|message| match &message.content {
MessageContent::Blocks(blocks) => blocks
.iter()
.filter(|block| matches!(block, ContentBlock::Image { .. }))
.cloned()
.collect(),
Comment on lines +196 to +199
let mut content: Vec<Value> = images
.iter()
.filter_map(|block| serde_json::to_value(block).ok())
.collect();
@BunsDev
BunsDev merged commit e570752 into main Jul 14, 2026
5 checks passed
@BunsDev
BunsDev deleted the feat/claude-cli-image-input branch July 14, 2026 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants