◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/Claude Code
⟐ Claude Code/2026-04-21Intermediate

When Bash Misbehaves in Claude Code on Windows — A Practical Note on CLAUDE_CODE_USE_POWERSHELL_TOOL=1

On Windows, Claude Code's Bash-based shell tool sometimes fails in odd ways. Setting CLAUDE_CODE_USE_POWERSHELL_TOOL=1 routes commands through PowerShell and removes many of the symptoms. Here are the practical trade-offs I've seen after living with the switch.

claude-code132windowspowershelltroubleshooting92shell3

The unexplained failures on Windows

If you've used Claude Code on Windows for any length of time, you've probably seen this pattern. Basic actions — opening a file, searching text, running a quick script — all work. Then something trips: a path gets mangled, a Git command blows up on quoting, line endings turn a straightforward command into a mystery. From the Claude Code side, it starts oscillating ("try this Bash command — error — try a different one — error"), and the transcript bloats.

A surprising fraction of these symptoms trace back to a mismatch between the Windows-side Bash environment (Git Bash, MSYS2, WSL-style wrappers) and the shell behavior that Claude Code's Bash tool assumes. That's where the CLAUDE_CODE_USE_POWERSHELL_TOOL=1 environment variable comes in. When set, Claude Code sends shell commands through PowerShell rather than its POSIX-flavored Bash path.

This article is a pragmatic note from living with the switch on Windows — when to turn it on, what actually changes, and what stays unfixed.

What the variable really does

Claude Code uses a small set of internal "tools" to execute work. The one that runs shell commands defaults to a Bash-oriented implementation — POSIX shell behavior expected. On Linux and macOS this works naturally.

On Windows, many users run Claude Code under a POSIX emulation layer like Git Bash. That layer frequently introduces seams: slashes get mixed into paths, quoting gets interpreted twice, and the final executor oscillates between cmd and PowerShell depending on the environment.

Setting CLAUDE_CODE_USE_POWERSHELL_TOOL=1 rewires the shell execution path to dispatch to PowerShell directly. PowerShell is pre-installed on modern Windows, and it speaks Windows paths, user profiles, and environment variables natively. That alignment removes many Windows-specific quirks.

When the switch pays off

The switch earns its keep in a handful of recurring scenarios.

Paths with spaces or non-ASCII characters

Windows paths like C:\Users\<Name>\OneDrive\Documents routinely contain spaces, and some have non-ASCII characters. Passing these through Git Bash always comes with layered-quoting problems. With PowerShell directly in the loop, Windows-style paths go through cleanly, and most of the quoting anxiety disappears.

Corporate networks — proxies and certificates

On company-managed machines, HTTP proxy and certificate configuration tends to live in the Windows Credential Manager and certificate store. Bash-based tooling often can't find them, producing errors like SSL certificate problem. PowerShell consults the Windows certificate store directly, so many of these failures quietly go away without extra configuration.

Cmdlets that only exist in PowerShell

Cmdlets such as Get-Process, Get-Service, and Get-AppxPackage are PowerShell-only. Bash can't invoke them. With the PowerShell tool active, Claude Code can reach native Windows diagnostics directly.

What changes that you should prepare for

Flipping the switch also means some Bash conventions stop translating cleanly.

Pipes and redirection

command1 | command2 still works, but PowerShell pipes push objects, not text. You'll see Claude Code substituting grep with Select-String, awk with ForEach-Object, and so on. For interactive use it handles most translations well. Pasting large legacy shell scripts and expecting them to run as-is, however, is now risky.

Execution Policy

PowerShell has an Execution Policy that restricts script execution. On corporate hardware this is often set to Restricted, which will reject any .ps1 files Claude Code tries to run. The minimum adjustment is a one-time:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

That scopes the change to your user only — a safer default than a machine-wide change.

Quoting differences

POSIX shells and PowerShell have subtly different quoting rules, especially around $ expansion inside double quotes and the meaning of single quotes. If you've been running every command Claude Code produces without reading it, expect a few surprises. Run shorter commands first and confirm output before chaining into long operations.

How to turn it on (and off)

The switch is an environment variable; it takes effect the next time Claude Code starts.

# PowerShell — current session only
$env:CLAUDE_CODE_USE_POWERSHELL_TOOL = "1"
claude
 
# Persist at the user level
[Environment]::SetEnvironmentVariable("CLAUDE_CODE_USE_POWERSHELL_TOOL", "1", "User")

If you're launching claude from Git Bash, add the export to ~/.bashrc so it's inherited:

# ~/.bashrc
export CLAUDE_CODE_USE_POWERSHELL_TOOL=1

To disable:

# Current session
Remove-Item Env:CLAUDE_CODE_USE_POWERSHELL_TOOL
 
# User-level
[Environment]::SetEnvironmentVariable("CLAUDE_CODE_USE_POWERSHELL_TOOL", $null, "User")

Deciding whether to switch

My rule of thumb: if any of these describe your setup, it's worth a trial.

You mostly work on Windows, and you'd rather not juggle Git Bash and PowerShell at the same time. Your machine is managed by a corporate IT policy with strict proxy and certificate settings. Your project leans on Windows-native tooling (.NET, PowerShell scripts, Windows APIs).

Conversely, if your Claude Code sessions already live inside WSL, you're effectively on Linux already — the switch brings very little benefit.

Windows-specific friction that remains

The variable doesn't remove every Windows idiosyncrasy. A few to keep in mind.

Path length limits

Windows has a default 260-character path limit. Deeply nested node_modules trees will still hit it. This is unrelated to Claude Code; you fix it via LongPathsEnabled in the registry or group policy.

Line endings

core.autocrlf in Git will still translate line endings on checkout. Claude Code isn't the source of the surprise, but you'll feel it through commands it runs. New repositories benefit from a minimal .gitattributes like * text=auto eol=lf.

Commands that need elevation

Anything that requires admin rights — netsh, sfc, Stop-Service, and friends — needs Claude Code itself to be launched elevated. On machines where every elevation prompts UAC, those are tasks you'll probably want to run by hand rather than via Claude Code.

Verifying the switch is actually active

Once you've set the variable, it's easy to confirm the tool is really routing through PowerShell. Ask Claude Code to run a short PowerShell-native command:

$PSVersionTable
Get-Location
[System.Environment]::OSVersion

If these return sensible output, the switch is live. Under the Bash path these would usually surface as "command not found"-style errors, so the contrast is obvious.


If you've had that vague sense that Claude Code is "fighting" your Windows environment, this is one of the cheapest experiments you can run — set the variable, try a short session, revert if you don't like it. For machines I use exclusively on Windows, I leave it on permanently. Between Windows and macOS workstations my Claude Code environments need to differ anyway; making that explicit with a single environment variable turns out to be a surprisingly durable quality-of-life improvement.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⟐ Claude Code2026-05-24
When Claude Code's Sequential Edits Cascade into Failure — Fixing 'old_string not found' and 'not unique' on the Same File
Run several Edits against the same file in one turn and the second or third one suddenly fails with 'not found' or 'not unique'. The cause is order-dependence inside a single context snapshot, and a Read + scoped patches usually rescue it.
⟐ Claude Code2026-05-10
When Claude Code's Read Doesn't Reach the End of a File — Catching the PARTIAL view Notice and Sizing offset/limit
When Read returns only part of a large file, Claude Code says so with a PARTIAL view notice. Here is how to catch it, and how to size offset and limit by byte budget rather than line count, with measurements from my own sandbox.
⟐ Claude Code2026-05-10
Why Claude Code's Glob and Grep Return Zero Results
When Claude Code's Glob or Grep tool returns no matches even though the files clearly exist, the cause is almost always one of four things. Here's how to triage.