[BUG] Image paste (Ctrl+V) does not work in native WSL2 terminal on Windows 11

Status Closed — not planned
Maintainer reply None cached
Activity 4 comments · opened May 23, 2026 · closed Oct 12, 2026

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?

When running Claude Code inside a native WSL2 terminal on Windows 11, copying an image from Windows (e.g. Ctrl+C on a file in
File Explorer, or copying an image from a browser) and then pressing Ctrl+V in the Claude Code prompt does not paste the
image. Nothing happens, or only an empty/garbled string is inserted; the image is never attached to the message.

To be explicit: this is reproduced in the native Windows Terminal / wsl.exe shell running a WSL2 distro, not the VS Code
integrated terminal.

Expected: the image is attached to the input as an image, the same way it works in Claude Code on macOS or in the VS Code
integrated terminal.

Actual: the image is not attached. The clipboard image is silently dropped.

Environment:

  • OS: Windows 11
  • Shell: WSL2 (Ubuntu) running in native Windows Terminal / wsl.exe
  • Claude Code: <v2.1.145>
  • Node: <v22.22.11>

Notes / likely cause: WSL2's clipboard interop does not expose image/png to Linux clipboard tools by default. xclip / wl-paste
either aren't installed or can't read the Windows clipboard image bytes. To bridge this, the CLI needs a WSL-specific path
that reads the Windows clipboard via powershell.exe (e.g. Get-Clipboard -Format Image or the
System.Windows.Forms.Clipboard.GetImage() API), saves it to a temp PNG, and attaches that. Other CLIs (e.g. Codex) appear to
do this and image paste works there in the same WSL2 environment.

What Should Happen?

Pressing Ctrl+V in the Claude Code prompt inside a native Windows 11 WSL2 terminal should attach the image currently on the
Windows clipboard to the input — same behavior as paste-image on macOS Terminal, iTerm2, or the VS Code integrated terminal.

Specifically, when running in WSL Claude Code should detect WSL (e.g. via WSL_DISTRO_NAME / /proc/version) and, on image
paste, fall back to invoking powershell.exe to read the Windows clipboard image, write it to a temp PNG inside the WSL
filesystem, and attach that file as an image to the message.

Error Messages/Logs

Steps to Reproduce

Repro:

  1. Windows 11 host, WSL2 distro (e.g. Ubuntu).
  2. Open Windows Terminal (or wsl.exe directly), launch Claude Code inside the WSL distro.
  3. In Windows, copy an image to the clipboard (right-click an image file → Copy, or copy an image from a webpage).
  4. Focus the Claude Code prompt and press Ctrl+V.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

v2.1.145

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

_No response_

View original on GitHub ↗

3 Comments

JamesNguyo · 4 months ago

also facing same issue

DrChr · 3 months ago

Same symptom here on WSL2 + Windows Terminal.

Claude Code 2.1.199, Debian WSL, Windows Terminal 1.24.11321.0.

Alt+V shows “Pasting...” then attaches nothing.

WSL sees the clipboard as image/bmp:

wl-paste --list-types
=> image/bmp

BMP compression is BI_BITFIELDS:

wl-paste --type image/bmp > /tmp/clip.bmp
xxd -l 4 -s 30 /tmp/clip.bmp
=> 03 00 00 00

Manual conversion works:

wl-paste --type image/bmp | convert bmp:- /tmp/clip.png

This looks like #50552: Claude Code receives the WSLg BMP but silently fails converting BI_BITFIELDS BMP to PNG.

VladimirCro · 1 month ago

Still reproduces on 2.1.238 (native install, WSL2 2.3.26.0 / WSLg 1.0.65, Ubuntu, Windows 10.0.26200). Adding a root cause that I think reframes this issue, plus an A/B measurement and a user-side workaround.

The PowerShell path the OP asks for already exists — it is just unreachable.

Extracted from the shipped 2.1.238 binary, the WSL command set is the linux one with two WSL-only suffixes appended (Wt()==="wsl"):

checkImage: xclip -t TARGETS -o | grep image/… || wl-paste -l | grep image/…
            [|| powershell.exe … Clipboard::ContainsImage()]

saveImage:  xclip -selection clipboard -t image/png -o > F
         || wl-paste --type image/png > F
         || xclip -selection clipboard -t image/bmp -o > F
         || wl-paste --type image/bmp > F
            [|| powershell.exe … Clipboard::GetImage() → Save(…, Png) → base64 -d > F]

then in JS: if (F starts with "BM") → BMP→PNG conversion → base64

WSLg bridges the Windows clipboard image to Wayland only, and only as image/bmp (X11 exposes no image target at all — xclip -t TARGETS -o returns just TIMESTAMP TARGETS UTF8_STRING TEXT). So branch 4 succeeds, the || chain short-circuits, and the PowerShell branch — the only one that yields a real PNG — never runs. The subsequent BI_BITFIELDS BMP→PNG conversion then throws, the catch returns null, and the UI reports No image found in clipboard.

So this is not "WSL has no path to the Windows clipboard". It is "the working path is behind a branch that succeeds with an unusable format".

Forensic marker that pins the failing step. saveImage's output file is deleted only on the success path, so its presence localizes the abort, and its first two bytes say why:

$TMPDIR/claude_cli_latest_screenshot.png   2 805 022 B   magic: 42 4d  ("BM")

The file is named .png and contains a BMP. It survives every failed paste.

A/B on one machine, same clipboard image, only difference is whether wl-paste is on PATH:

| | branch taken | output | result |
|---|---|---|---|
| wl-paste present | 4 (wl-paste --type image/bmp) | 3 342 402 B, magic 42 4d | conversion throws → "No image found" |
| wl-paste hidden | 5 (PowerShell) | 81 204 B, magic 89 50, valid PNG 1088x768 RGBA | pastes correctly |

User-side workaround that actually fixes it today: remove wl-clipboard (sudo apt remove wl-clipboard). With wl-paste gone the chain falls through to PowerShell and paste works natively again — no helper scripts. On WSLg, xclip still covers copy (verified: xclip -selection clipboard → Windows clipboard round-trip works), so the only loss is Pillow's ImageGrab.grabclipboard(). Side benefit: 56 KB PNG instead of a 3.3 MB uncompressed BMP per paste.

Suggested fix: on WSL, try the PowerShell branch before the image/bmp branches (or skip the BMP branches entirely when Wt()==="wsl"). That avoids the BI_BITFIELDS decode path rather than trying to make it work, and needs no new dependency. Note that checkImage has the same ordering, but it is harmless there because it only tests for presence.

On the duplicate chain: #77102 was auto-closed as a duplicate of #50552, which is itself closed not_planned/stale, and #36420 was auto-closed against #32185 (a different, VS Code-specific image-processor.node bug). The BMP reports have effectively been closed into a dead end, which may be why this keeps getting re-filed.

Showing cached comments. Read the full discussion on GitHub ↗