This repository preserves a WSL2 + Windows Terminal setup. Linux checks cover scripts and documentation; Windows notifications, clipboard integration, and terminal input still need testing on a real WSL2 installation.
For a read-only report on an installation, run bash scripts/doctor.sh from the
cloned repository. It compares installed scripts with the repository copies,
inspects Claude Code and Codex settings, and flags known conflicts. It writes
nothing and does not test Windows GUI behavior.
Install one feature at a time and keep your existing settings. Save a copy of each file you will edit. For example, before changing Claude Code settings:
if [ -f ~/.claude/settings.json ]; then
cp --backup=numbered ~/.claude/settings.json ~/.claude/settings.json.bak
fi
Do the same for a script, shell startup file, keybindings file, or service unit before replacing it. For Windows Terminal and VSCode, save copies through Windows before editing. Record the settings you add so removal does not affect other tools.
Merge JSON objects and append only the required array entries. Do not replace an existing settings file with a small example from a guide. After editing, check JSON:
jq empty ~/.claude/settings.json
For JSON files with comments, use the application’s editor/validator instead of
plain jq. Restart the relevant application and confirm it loads the change.
| Component | Check after installation | Remove or restore |
|---|---|---|
| Statusline | Run the sample payload, then open Claude Code and inspect available fields | Remove this statusLine setting, restore any previous setting/script, and delete the installed script only if unused |
| Notifications | Send a forced test balloon, test foreground suppression, then trigger a hook event | Remove only handlers calling this script; retain the script while Codex or tmux uses it |
| Screenshot paste | Check the user service, paste a screenshot, and repeat after restarting WSL | Disable the service before deleting its unit; remove only the added keybinding and unused binary |
| LSP | Check each selected server’s executable/version, then navigate to a definition with Claude | Disable the selected plugins; remove server binaries only if your editor does not need them |
| Browser routing | Test both the quoted BROWSER executable and xdg-open |
Restore the previous environment setting and HTTP/HTTPS handlers before removing the desktop file |
| Terminal titles | Open a fresh zsh tab and check directory and command titles | Remove the added _wt_* functions, their two add-zsh-hook registrations, and the added environment export; restore previous terminal/agent title settings and start a fresh shell |
| Shift+Enter | Type two lines in Claude Code; Shift+Enter should insert a newline | Remove only the added binding in Windows Terminal or VSCode, or restore the binding you replaced; reopen the terminal |
| CapsLock remap | Check that CapsLock acts as Escape after signing in again | Delete only that mapping in SharpKeys, write to the registry, then sign out and back in |
| Attribution preference | Check the next commit/PR you request from Claude | Restore the previous values, or remove the added fields to use defaults |
| tmux helper | Run the disposable job below and inspect its exit status and log | Let jobs finish; remove the helper if unused, retaining logs/state until no longer needed |
For a tmux smoke check, choose a session name not already in use. From the cloned
repository, with tmux and setsid available:
bash bin/tmux-notify-run setup-check -- /bin/echo 'setup check'
# After the job finishes:
bash bin/tmux-notify-run --status setup-check
cat "${XDG_STATE_HOME:-$HOME/.local/state}/tmux-notify-run/setup-check/job.log"
Expect exit=0 and setup check in the log. A missing notification script does
not fail the job; verify Windows delivery separately. The helper creates files
under the state directory above and can reuse a finished session name, replacing
that job’s state/log, so use a dedicated name for this check.
/mcp in the intended project and request
a small selection from Figma. To remove it, use /mcp to identify its scope,
then claude mcp remove figma-desktop --scope <scope> for that scope. Keep
unrelated servers. Turn off Figma’s local server only if nothing else needs it.
If you enabled mirrored networking only for Figma, restore your previous
.wslconfig and run wsl --shutdown.notify
entry you added, then restart Codex. Keep the shared notification script if
Claude or tmux still uses it.The setup was used daily on WSL2 until the move to Ubuntu + Ghostty, documented on 2026-09-08. No per-guide Windows, WSL, or Claude Code versions were recorded then. These later changes pass the Linux checks but have not been run on WSL2:
| Guide | Changed since 2026-09-08 | Check on WSL2 |
|---|---|---|
| Notifications | Script moved to bin/ with a configurable PowerShell path and --force validation (2026-09-08); text passed base64-encoded and a 12 s exit limit (2026-10-15) |
Forced balloon, foreground suppression, click-to-focus, no tray icon left behind |
| Codex notification | Uses the notification script above | A completed turn whose reply contains ’ |
| tmux helper | Log finished before the status is written (2026-10-15) | One job’s completion balloon |
| Screenshot paste | Pinned, checksum-verified install (2026-10-15) | Paste, then paste again after wsl --shutdown |
| Browser routing | WSL-form paths, a symlink for paths with spaces, and a check for xdg-open’s built-in WSL support (2026-10-23) |
"$BROWSER" and xdg-open with a symlinked Program Files browser |
| Figma Desktop MCP | Mirrored networking requirement (2026-10-15) | /mcp connects with mirrored networking |
After testing a guide on WSL2, add a line below with the date, the guides, and the
Windows, WSL, distro, terminal, and Claude Code versions. bash scripts/doctor.sh
prints most of them.
Requires Bash 4.4+, Python 3.11+, Git, and jq. Checks that need tmux, zsh,
PowerShell 7 (pwsh), or shellcheck are skipped when the tool is missing. From
the cloned repository:
bash scripts/check.sh
The same command runs in GitHub Actions, which
provides every optional tool and sets CHECKS_REQUIRE_ALL=1 so nothing is skipped:
shellcheck for scripts in bin/ and scripts/.notify command runs against a mock notifier.#0d1117 canvas, rendered at width 720.tmux-notify-run on a private tmux server: arguments, working directory,
environment, exit status, complete logs, notifications, --status, and invalid input.scripts/doctor.sh against fixture home directories, including that it writes nothing.The notification tests do not run Windows PowerShell or display a balloon. Passing CI does not certify Windows interoperability, GUI behavior, third-party installers, or configuration loading in a live Claude Code session.
To report a WSL2 issue, use the
issue form
and include the output of bash scripts/doctor.sh.