[BUG] Windows: hidden cmd.exe re-parse of Bash/PowerShell tool commands pre-creates zero-byte redirect-target junk files in cwd
Environment
- Claude Code version: 2.1.96
- Platform: Windows 10 Home 10.0.19045
- Affected tools: both the Bash tool (Git Bash) and the PowerShell tool reproduce identically
Summary
On Windows, shell tool commands appear to be re-parsed by a hidden cmd.exe layer in addition to the real shell invocation. When that re-parse sees a > in cmd's quote-OFF state, it pre-creates the redirect target as a zero-byte file in the working directory. The actual command still runs correctly with full, intact output — the empty file is the only side effect, so it silently litters repositories (untracked junk in git status with names like 'JP_A1', 0)), tsc, push).
Deterministic reproduction
Via the PowerShell tool:
Write-Output "alpha > 'JP_A1' bravo"
- stdout is correct:
alpha > 'JP_A1' bravo - but a zero-byte file literally named
'JP_A1'(single quotes included in the filename) is created in the cwd.
Via the Bash tool:
echo "alpha > 'JP_B1' bravo"
- stdout is correct, and a zero-byte file named
'JP_B1'is created in the cwd.
Reproduced on 2026-06-09 and again on 2026-06-10 on v2.1.96.
Trigger condition (narrowed by controlled probes)
cmd.exe quote-toggling decides whether the junk file is created:
| Command shape | Result |
|---|---|
| > after an odd number of " chars in the command string (cmd quote-OFF state), e.g. Write-Output "alpha > 'X' bravo" | zero-byte file created |
| Same > single-quoted with no " anywhere before it, e.g. ... \| Select-String -Pattern 'spacing > 0' -Context 2,2 | clean — probed repeatedly, no file |
This is consistent with the command string passing through cmd.exe somewhere (e.g. child_process with shell: true → cmd /d /s /c "<command>"): an embedded " toggles cmd's quote state off and exposes the > to cmd's redirect parsing, and the literal quote characters kept in the created filename match cmd treating ' as an ordinary character. Notably, since the real command's stdout is captured intact and the file stays 0 bytes, the redirect-bearing parse looks like a secondary/pre-flight spawn rather than the main execution path.
Additional data points:
- Sandbox mode on/off makes no difference.
- User hooks were exonerated (reproduces with a hook setup whose handler only posts JSON over HTTP; the file appears at command time, not hook time).
- The Grep and Edit tools do not trigger it — only Bash/PowerShell tool commands.
Impact
- Repos accumulate untracked zero-byte junk at the root; any command that echoes/searches code containing comparisons (
x > 0) inside a double-quoted string drops a file named after the code fragment (we collected ones named0)),'5.5',tsc,push,void). - Teams end up adding compensating infrastructure — we now run a pre-commit hook that auto-deletes untracked zero-byte root files.
- Likely related (but distinct) reports: #17087 (empty 0-byte dotfiles created during Bash execution), #15799 (
NULredirect target created as a literal file on Windows).
Expected behavior
No filesystem side effects from > characters inside command strings. The command should reach the target shell (powershell.exe / bash.exe) without an intermediate cmd.exe parse that performs redirect target creation.
🤖 Generated with Claude Code
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗