Paste screenshots directly into CLI tools (like Claude Code) running on WSL2.
When using CLI tools on WSL that accept image paths (like Claude Code), you can't paste images directly from the Windows clipboard. The clipboard contains image data, but WSL applications expect a file path.
This tool bridges that gap by:
- Monitoring the Windows clipboard for images
- Automatically saving them to a WSL-accessible directory
- Copying the WSL file path to the clipboard
- Now you can paste the path directly into your terminal
- Windows 10/11 with WSL2
- PowerShell 5.1+
- A WSL distribution (Ubuntu, Debian, etc.)
cd C:\Users\YourUsername
git clone https://github.com/CairoAC/wsl-screenshot-tool.gitmkdir -p ~/.screenshotsRun PowerShell as Administrator and execute:
powershell -ExecutionPolicy Bypass -File "C:\Users\YourUsername\wsl-screenshot-tool\setup-autostart.ps1"- Take a screenshot with
Win+Shift+S(orPrintScreen) - The tool automatically detects the image in your clipboard
- Saves it to
~/.screenshots/in your WSL home directory - Copies the WSL path to your clipboard
- Paste the path (
Ctrl+V) in your terminal
Example flow:
[Take screenshot] → [Tool saves to ~/.screenshots/screenshot_2024-01-15_14-30-45.png]
→ [Clipboard now contains: /home/user/.screenshots/screenshot_2024-01-15_14-30-45.png]
→ [Paste in terminal]
┌─────────────────────────────────────────────────────────────────┐
│ WINDOWS │
│ ┌──────────────┐ ┌─────────────────┐ ┌───────────────┐ │
│ │ Task │───>│ run-hidden.vbs │───>│ PowerShell │ │
│ │ Scheduler │ │ (hides window) │ │ (main script) │ │
│ └──────────────┘ └─────────────────┘ └───────┬───────┘ │
│ │ │
│ ┌───────────────────────┘ │
│ │ Polls clipboard every 500ms │
│ ▼ │
│ ┌───────────────┐ │
│ │ Clipboard │ │
│ │ (image data) │ │
│ └───────┬───────┘ │
│ │ │
└──────────────────────────────┼──────────────────────────────────┘
│ Save via \\wsl.localhost\...
┌──────────────────────────────┼──────────────────────────────────┐
│ WSL2 │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ ~/.screenshots│ │
│ │ (PNG files) │ │
│ └───────────────┘ │
└─────────────────────────────────────────────────────────────────┘
The core PowerShell script that:
-
Waits for WSL to be ready (
Wait-ForWslReady)- Polls
wsl.exe --statusevery 2 seconds - If WSL isn't running after 3 attempts, starts it automatically
- Times out after 5 minutes (configurable)
- Polls
-
Auto-detects WSL configuration (
Get-SafeWslDistro,Get-SafeWslUsername)- Finds the first non-Docker WSL distribution
- Gets the username via
wsl.exe -e whoami - Validates inputs to prevent path injection
-
Monitors the clipboard (main loop)
- Checks for images every 500ms (configurable)
- Uses SHA256 hash to detect duplicate images (won't save the same image twice)
- Saves images as PNG with timestamp:
screenshot_YYYY-MM-DD_HH-mm-ss.png
-
Auto-recovers from WSL shutdown
- If WSL shuts down due to inactivity, the script detects this
- Automatically restarts WSL and resumes monitoring
- Never exits unless manually stopped
Parameters:
| Parameter | Default | Description |
|---|---|---|
SaveDirectory |
Auto | Custom save path (default: ~/.screenshots) |
WslDistro |
auto |
WSL distribution name (auto-detected) |
PollingIntervalMs |
500 |
How often to check clipboard (ms) |
MaxErrorCount |
10 |
Errors before attempting WSL restart |
WslStartupTimeoutSeconds |
300 |
Max wait time for WSL startup |
Creates a Windows Scheduled Task with:
-
Triggers:
- At user logon (30 second delay)
- At system startup (30 second delay)
-
Settings:
- Runs on battery power
- Doesn't stop when going on batteries
- No execution time limit (runs indefinitely)
- Auto-restart on failure (3 retries, 1 minute interval)
- Doesn't stop on idle
- Ignores new instances if already running
-
Principal:
- Runs as current user
- Interactive logon (required for clipboard access)
- Limited privileges (no admin required)
run-hidden.vbs - Window hider
A VBScript wrapper that launches PowerShell completely hidden. This is necessary because:
- PowerShell's
-WindowStyle Hiddenflag still shows a brief window flash - Task Scheduler cannot truly hide console windows
- VBScript's
WScript.Shell.Runwith windowstyle0provides true invisibility
Removes the scheduled task cleanly:
- Stops the running task
- Unregisters from Task Scheduler
Check if the task exists and its state:
Get-ScheduledTask -TaskName "WSL-Screenshot-Monitor" | Select-Object TaskName, StateManually start it:
Start-ScheduledTask -TaskName "WSL-Screenshot-Monitor"- Check if the process is running:
Get-WmiObject Win32_Process | Where-Object { $_.CommandLine -like '*screenshot-monitor*' }- Run manually to see errors:
powershell -ExecutionPolicy Bypass -File "C:\Users\YourUsername\wsl-screenshot-tool\screenshot-monitor.ps1"- Verify WSL is accessible:
wsl.exe --statusThe script requires an interactive session. If running via Task Scheduler with "Run whether user is logged on or not", clipboard access will fail. The setup script configures this correctly, but if you modified the task, ensure:
- LogonType is set to
Interactive - Task runs as your user account
Windows automatically shuts down WSL after a period of inactivity. The script handles this by:
- Detecting when the save directory becomes inaccessible
- Automatically restarting WSL
- Resuming monitoring
If this happens frequently, you can prevent WSL auto-shutdown by keeping a background process running in WSL, or by modifying .wslconfig:
# %UserProfile%\.wslconfig
[wsl2]
vmIdleTimeout=-1powershell -ExecutionPolicy Bypass -File "C:\Users\YourUsername\wsl-screenshot-tool\remove-autostart.ps1"Then delete the cloned repository and optionally ~/.screenshots in WSL.
- The script validates all WSL usernames and distribution names against strict regex patterns to prevent path injection
- No network access required - everything runs locally
- Runs with limited (non-admin) privileges
- Screenshots are saved with user-only permissions
MIT