Skip to content

fix(tui): read clipboard images through Windows interop on WSL - #57470

Open
AlexeyShirshov wants to merge 1 commit into
anomalyco:devfrom
AlexeyShirshov:wsl-image-paste
Open

AlexeyShirshov wants to merge 1 commit into
anomalyco:devfrom
AlexeyShirshov:wsl-image-paste

Conversation

@AlexeyShirshov

@AlexeyShirshov AlexeyShirshov commented Oct 20, 2026 •

Copy link
Copy Markdown

Issue for this PR

Fixes #49895

Type of change

  • Bug fix

What does this PR do?

On WSL the native host clipboard has nothing to read: Windows Terminal owns the selection and OpenTUI's Linux backend has no bridge to it, so read() returned unsupported and Ctrl+V on an image did nothing. When the native read fails and the platform is WSL, createClipboardAdapter now falls back to the Windows clipboard through powershell.exe and returns the image as image/png base64 - the same interop path V1 used.

If the interop is missing or powershell fails, read() throws instead of returning undefined, so the TUI shows an error instead of failing silently. Non-WSL reads and cancelled reads are unchanged, and a working WSLg still answers first, so the fallback only runs when the native read has nothing.

How did you verify your code works?

On WSL2 (kernel 6.18.33.2-microsoft-standard-WSL2, no WSLg runtime dir, so no Wayland/X11 clipboard):

  • Before the change, reading the host clipboard returns unsupported in ~2 ms, hence the silent no-op.
  • With a screenshot on the Windows clipboard, the adapter returns image/png base64 and the TUI attaches it.
  • Empty and text clipboards still return undefined; text paste still goes through the terminal as before.
  • bun test test/clipboard.test.ts and oxlint pass.

There is no automated test for the powershell path: it depends on Windows interop being present. The change was exercised through the clipboard adapter against the real Windows clipboard; I did not drive the whole TUI by hand. The native adapter tests in packages/tui/test/clipboard.test.ts still cover the unchanged read/write behaviour.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #55639

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@AlexeyShirshov
AlexeyShirshov marked this pull request as ready for review October 20, 2026 18:20

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fallback looks correct, but I couldn't check it on real WSL: this sandbox has no Windows interop or Windows clipboard. Instead I put a fake powershell.exe on PATH and called createClipboardAdapter with a stubbed native read. An image comes back as image/png base64 and an empty Windows clipboard returns nothing. A failing or missing powershell.exe now throws, and the prompt's paste queue catches that and shows it, instead of the paste silently doing nothing. Cancelled reads and non-WSL systems are unchanged. bun test test/clipboard.test.ts and the packages/tui typecheck pass.

Public API: unchanged.

One thing worth fixing: WSL detection also matches Docker Desktop containers and devcontainers on Windows, where the error message would be misleading (see the inline comment).

Related: #55639

Comment thread packages/tui/src/clipboard.ts Outdated
].join("; ")

function isWSL() {
return process.platform === "linux" && (Boolean(process.env.WSL_DISTRO_NAME) || release().includes("WSL"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

release().includes("WSL") also matches containers on Docker Desktop and devcontainers on Windows: they run the microsoft-standard-WSL2 kernel but have no Windows interop. There, pressing Ctrl+V with nothing readable on the clipboard now throws "needs powershell.exe interop" where it used to be a silent no-op, and the message is misleading. Checking only what WSL itself sets (WSL_DISTRO_NAME / WSL_INTEROP) covers WSL1 and WSL2 and avoids this, since those variables don't reach containers.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 1052174: detection now only checks the variables WSL sets (WSL_DISTRO_NAME / WSL_INTEROP), so containers on the WSL kernel keep the previous silent no-op instead of throwing a misleading interop error. Verified both paths here: with the variables set the Windows clipboard image comes back as image/png; with them unset the read returns undefined.

The native host clipboard cannot read the Windows selection from WSL, so
pasting a screenshot did nothing. Fall back to powershell.exe and report
interop failures instead of returning undefined.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tui: image paste fails silently on WSL when no clipboard tool is installed (V2)

1 participant