// The guide
Claude Code on Windows: no WSL required.
Search for "Claude Code Windows" and half the results tell you to install WSL first. You don't need it. Claude Code runs natively on plain Windows, and so do bash-launched MCP servers — we proved it in CI. Here is the native path, and the traps we hit so you don't have to.
Everything below was verified in July 2026 by running the full stack on native Windows, including a clean GitHub Actions windows-latest machine.
What "native" actually means
Claude Code on Windows does not emulate Linux. Its Bash tool uses Git for Windows — the MINGW64 environment that ships with every Git install. That gives you a real bash, the usual Unix userland, and Windows paths that just work.
That is enough for more than you might think. We took a Python MCP server that had only ever run on macOS and Linux, launched it the same way Claude Code does — bash run.sh — on a GitHub Actions windows-latest runner with Git Bash and uv, and got a full MCP stdio handshake: server booted over stdio, 36 tools registered. No WSL, no container, no shim.
The one real trap for MCP server authors
If your Python MCP server dies instantly on Windows, check your imports first. The killer is this line at module level:
import fcntl
fcntl is POSIX-only. On Windows the import raises at load time, which means your server is dead before it can even say hello over stdio. Claude Code just sees a server that never connected.
The fix is to guard the import and degrade gracefully:
try:
import fcntl
except ImportError:
fcntl = None
Then treat your advisory file locks as best-effort where fcntl is None. Advisory locks were never guarantees anyway; on Windows you simply skip them. In our porting work this was the single change that took the server from dead-on-import to fully working.
The Windows gotchas we hit and fixed
Four more traps, all real, all cheap to avoid once you know them.
1. OpenSSH refuses your private key
Windows OpenSSH checks key file permissions like Unix does, but through ACLs. A private key copied onto the machine usually inherits permissive ACLs, and ssh refuses to use it. Fix the ACLs explicitly:
icacls <key> /inheritance:r /grant:r "%USERNAME%:R"
That strips inherited permissions and grants read access to you alone, which is what OpenSSH wants to see.
2. bash.exe is not on PATH
Git for Windows puts Git\cmd on PATH by default — that gives you git. But bash.exe lives in Git\bin, which is not on PATH. Anything that spawns bash by name needs Git\bin appended to the user PATH. Do that once and bash-launched tooling works everywhere.
3. Never hardcode C:\Program Files
Git can be installed system-wide or per-user. The user-scope install lands in %LOCALAPPDATA%\Programs\Git, not C:\Program Files\Git. Any script that hardcodes the system path breaks on user-scope installs. Resolve the Git root dynamically instead of assuming.
4. The test-suite encoding trap
Windows' default text encoding is cp1252, not UTF-8. A test suite that calls read_text() without an encoding argument passes on macOS and Linux and fails on Windows the moment a file contains a character outside cp1252. The rule is simple: always read_text(encoding="utf-8"), always write_text(encoding="utf-8"). Every occurrence, no exceptions.
So when do you actually need WSL?
If your workflow genuinely depends on Linux — Docker containers with Linux-only images, Linux system calls, tooling with no Windows build — WSL still earns its place. But "I want to run Claude Code and my MCP servers" is not that case. The native path is lighter, starts faster, and has no VM boundary between your assistant and your files.
We hit all of this making Klyr run natively on Windows — Klyr gives Claude Code a persistent memory, and its MCP servers now boot on plain Windows exactly as they do on a Mac. If your assistant should work the same on every machine you own, that is the problem Klyr exists to solve.
New to Claude Code entirely? Start with our non-developer guide first.
FAQ
Do I need WSL to run Claude Code on Windows?
No. Claude Code runs natively on plain Windows. Its Bash tool uses Git for Windows (MINGW64), which ships with every Git install. We verified a bash-launched Python MCP server booting natively in CI on windows-latest, with a full MCP stdio handshake and 36 tools registered.
Why does my Python MCP server crash instantly on Windows?
Most likely a module-level import fcntl. The fcntl module is POSIX-only and the import raises before your server can speak stdio. Guard it with try/except ImportError and treat file locks as best-effort when it is missing.
Why can't scripts find bash.exe on Windows?
Git for Windows only puts Git\cmd on PATH by default. bash.exe lives in Git\bin, which is not on PATH. Append Git\bin to the user PATH and anything that spawns bash by name will work.
Why does Windows OpenSSH refuse my private key?
The key file's ACLs are too permissive. Run icacls <key> /inheritance:r /grant:r "%USERNAME%:R" to strip inherited permissions and grant read access to your user only.
Where is Git installed on Windows?
Either system-wide under C:\Program Files\Git or per-user under %LOCALAPPDATA%\Programs\Git. Never hardcode the system path; resolve the install location dynamically.
Why do my tests fail only on Windows with encoding errors?
Windows' default text encoding is cp1252, not UTF-8. Always pass encoding="utf-8" explicitly to read_text and write_text.