<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 上条碧人</title>
    <description>The latest articles on DEV Community by 上条碧人 (@kamijo_aoto).</description>
    <link>https://dev.to/kamijo_aoto</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4203592%2F70c440db-ecde-4a97-a9a3-a93a889b3869.jpg</url>
      <title>DEV Community: 上条碧人</title>
      <link>https://dev.to/kamijo_aoto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kamijo_aoto"/>
    <language>en</language>
    <item>
      <title>Claude Code on Windows breaks without errors: 15 traps I reproduced</title>
      <dc:creator>上条碧人</dc:creator>
      <pubDate>Sat, 24 Oct 2026 00:53:19 +0000</pubDate>
      <link>https://dev.to/kamijo_aoto/claude-code-on-windows-breaks-without-errors-15-traps-i-reproduced-d6</link>
      <guid>https://dev.to/kamijo_aoto/claude-code-on-windows-breaks-without-errors-15-traps-i-reproduced-d6</guid>
      <description>&lt;p&gt;Running Claude Code unattended on Windows 11 with Windows PowerShell 5.1, I kept hitting failures that produced &lt;strong&gt;no error&lt;/strong&gt; — just a wrong result. I re-triggered every one of them on my machine (Windows PowerShell 5.1.26100, Python 3.13.7, Claude Code 2.1.304, October 2026).&lt;/p&gt;

&lt;p&gt;My machine runs Japanese Windows. For the traps that depend on code pages, I also re-ran the checks with the English defaults (ANSI 1252, OEM 437). Only #9 stopped breaking. The rest either broke the same way, broke differently (noted below), or do not depend on the language setting at all.&lt;/p&gt;

&lt;p&gt;To see which of #1–#14 happen on your own machine, run the free script (MIT, also a Claude Code plugin): &lt;a href="https://github.com/cart231-ffly-b/claude-code-windows-traps" rel="noopener noreferrer"&gt;https://github.com/cart231-ffly-b/claude-code-windows-traps&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The map
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;What breaks&lt;/th&gt;
&lt;th&gt;Where you hit it&lt;/th&gt;
&lt;th&gt;What I saw&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exit 2&lt;/code&gt; becomes &lt;code&gt;1&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;calling a script with &lt;code&gt;powershell -Command&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-File=2 -Command=1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;an argument is silently dropped&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-File&lt;/code&gt; with &lt;code&gt;-Path a b&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;count=1&lt;/code&gt;, exit code 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;an array becomes one string&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-File&lt;/code&gt; with &lt;code&gt;-Path a,b&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;first=a,b&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;non-ASCII arrives as &lt;code&gt;??&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;piping text into a native program&lt;/td&gt;
&lt;td&gt;bytes &lt;code&gt;3f3f&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;captured output is mojibake&lt;/td&gt;
&lt;td&gt;reading UTF-8 output with the default console encoding&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;café—&lt;/code&gt; read as &lt;code&gt;caf├⌐ΓÇö&lt;/code&gt; (cp437)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Python crashes only when redirected&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;python x.py &amp;gt; out.txt&lt;/code&gt; printing &lt;code&gt;✓&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;UnicodeEncodeError, exit 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PYTHONIOENCODING&lt;/code&gt; has no effect&lt;/td&gt;
&lt;td&gt;&lt;code&gt;python -I&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exit 1 with &lt;code&gt;-I&lt;/code&gt;, 0 without&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;an em dash becomes a syntax error&lt;/td&gt;
&lt;td&gt;non-ASCII &lt;code&gt;.ps1&lt;/code&gt; saved without BOM&lt;/td&gt;
&lt;td&gt;"string is missing the terminator"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;a &lt;code&gt;.cmd&lt;/code&gt; runs its comments (CJK Windows only)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.cmd&lt;/code&gt; saved with LF&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;cp932=broken cp65001=ok&lt;/code&gt;; fine on 437/1252&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;a one-liner is a syntax error&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;powershell -Command "foreach ($i ...)"&lt;/code&gt; from PowerShell&lt;/td&gt;
&lt;td&gt;exit 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-Include&lt;/code&gt; is ignored&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Get-ChildItem -LiteralPath ... -Include *.ps1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the &lt;code&gt;.md&lt;/code&gt; came back too&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;letters vanish into newlines&lt;/td&gt;
&lt;td&gt;Markdown backticks inside &lt;code&gt;"..."&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;`n&lt;/code&gt; became a newline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;a growing file shows 0 bytes&lt;/td&gt;
&lt;td&gt;listing a log under &lt;code&gt;AppData&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;listed 0, actual 5,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;claude -p&lt;/code&gt; gets no prompt&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--allowedTools Read "prompt"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Input must be provided ...&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;a slow safety hook lets the write through&lt;/td&gt;
&lt;td&gt;a PreToolUse hook that answers after its timeout&lt;/td&gt;
&lt;td&gt;the file was written, 3 times out of 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Three habits that cover most of them
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure what the screen won't show.&lt;/strong&gt; Exit codes, bytes, real file sizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASCII instruction + UTF-8 file.&lt;/strong&gt; Keep non-ASCII text out of pipes, arguments and &lt;code&gt;"..."&lt;/code&gt;. Tell Claude: &lt;code&gt;Read the file C:\work\prompt.md and do exactly what it says.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run it the way it will really run&lt;/strong&gt; — through the scheduler, with &lt;code&gt;-File&lt;/code&gt; — once, before you trust it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Each trap
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;-Command&lt;/code&gt; turns exit code 2 into 1.&lt;/strong&gt; A script that only does &lt;code&gt;exit 2&lt;/code&gt; returned 2 with &lt;code&gt;-File&lt;/code&gt; and 1 with &lt;code&gt;-Command&lt;/code&gt;. Codes 0 and 1 pass through unchanged, so nothing looks wrong until you start using 2 or higher — Task Scheduler's "Last Run Result" shows 1 too. Use &lt;code&gt;-File&lt;/code&gt;, or append &lt;code&gt;; exit $LASTEXITCODE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2–3. &lt;code&gt;-File&lt;/code&gt; passes arguments as plain strings.&lt;/strong&gt; &lt;code&gt;-Path a b&lt;/code&gt; silently dropped &lt;code&gt;b&lt;/code&gt; (exit code 0). Add &lt;code&gt;[CmdletBinding()]&lt;/code&gt; and the same call stops with "A positional parameter cannot be found" — stopping is safer. &lt;code&gt;-Path a,b&lt;/code&gt; stays one string &lt;code&gt;a,b&lt;/code&gt;; split it yourself with &lt;code&gt;-split ','&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Piped non-ASCII text arrives as &lt;code&gt;??&lt;/code&gt;.&lt;/strong&gt; Windows PowerShell 5.1 encodes text sent to native programs with &lt;code&gt;$OutputEncoding&lt;/code&gt;, which defaults to us-ascii. &lt;code&gt;café—&lt;/code&gt; piped to Python arrived as &lt;code&gt;caf??&lt;/code&gt;. Prompts piped into &lt;code&gt;claude -p&lt;/code&gt; get damaged the same way. Put long prompts in a UTF-8 file and send an ASCII instruction instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Captured output turns into mojibake.&lt;/strong&gt; The reverse direction breaks too: UTF-8 output read with the default console encoding became unrelated characters — &lt;code&gt;café—&lt;/code&gt; came back as &lt;code&gt;caf├⌐ΓÇö&lt;/code&gt; under cp437 (the US default). Set &lt;code&gt;[Console]::OutputEncoding&lt;/code&gt; to UTF-8 on the reading side, and align the sending side as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Python crashes only when redirected.&lt;/strong&gt; On screen, Windows Python prints anything. Redirected to a file, it encodes with the ANSI code page and crashes on any character outside it. With cp1252, &lt;code&gt;—&lt;/code&gt; and &lt;code&gt;é&lt;/code&gt; were fine, but &lt;code&gt;✓&lt;/code&gt; (U+2713) crashed with exit 1 — and AI-written scripts love printing ✓ and →. This is one reason scripts "work by hand but fail under the scheduler". &lt;code&gt;PYTHONIOENCODING=utf-8&lt;/code&gt; fixes it. (Python 3.15, released October 9, makes UTF-8 the default, so on 3.15 or later this is not expected. I tested on 3.13; with &lt;code&gt;-X utf8&lt;/code&gt;, the 3.15 default, the same script did not crash.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. &lt;code&gt;python -I&lt;/code&gt; ignores &lt;code&gt;PYTHONIOENCODING&lt;/code&gt;.&lt;/strong&gt; With &lt;code&gt;-I&lt;/code&gt; (isolated mode) the crash stayed (exit 1 with &lt;code&gt;-I&lt;/code&gt;, 0 without). Drop &lt;code&gt;-I&lt;/code&gt;, or call &lt;code&gt;sys.stdout.reconfigure(encoding="utf-8")&lt;/code&gt; inside the script. This one is also not expected on Python 3.15 or later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. A BOM-less non-ASCII &lt;code&gt;.ps1&lt;/code&gt;.&lt;/strong&gt; PowerShell 5.1 reads BOM-less files with the ANSI code page. On English Windows that is worse than mojibake: the UTF-8 bytes of &lt;code&gt;—&lt;/code&gt; end in 0x94, which cp1252 reads as &lt;code&gt;”&lt;/code&gt; — and PowerShell treats curly quotes as real quotes. &lt;code&gt;Write-Output "a—b"&lt;/code&gt; saved without BOM, read as cp1252, fails to parse ("The string is missing the terminator"). Save such files as UTF-8 with BOM, or keep &lt;code&gt;.ps1&lt;/code&gt; files ASCII-only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. (Japanese, Chinese and Korean Windows only) A &lt;code&gt;.cmd&lt;/code&gt; with LF line endings runs its comments.&lt;/strong&gt; AI file tools usually write LF. A &lt;code&gt;.cmd&lt;/code&gt; with non-ASCII &lt;code&gt;rem&lt;/code&gt; comments, saved with LF, made cmd.exe try to execute the comment text. The same file broke under code page 932 and ran to the end under 65001 (UTF-8). Under 437 and 1252, a file with accented Latin comments ran fine. If your users include CJK Windows, save &lt;code&gt;.cmd&lt;/code&gt; files with CRLF anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. A one-liner becomes a syntax error.&lt;/strong&gt; From PowerShell, &lt;code&gt;powershell -Command "foreach ($i in 1..2) { $i }"&lt;/code&gt; lets the &lt;em&gt;calling&lt;/em&gt; shell expand &lt;code&gt;$i&lt;/code&gt; (to nothing) first. The child receives &lt;code&gt;foreach ( in 1..2)&lt;/code&gt; and exits with 1. Put the logic in a &lt;code&gt;.ps1&lt;/code&gt; and run it with &lt;code&gt;-File&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. &lt;code&gt;-Include&lt;/code&gt; is ignored with &lt;code&gt;-LiteralPath&lt;/code&gt;.&lt;/strong&gt; In a folder with one &lt;code&gt;.ps1&lt;/code&gt; and one &lt;code&gt;.md&lt;/code&gt;, &lt;code&gt;Get-ChildItem -LiteralPath &amp;lt;dir&amp;gt; -Recurse -File -Include *.ps1&lt;/code&gt; returned both. My own health-check script hit this and flagged Markdown and JSON files as broken batch files — my test fixtures only contained scripts, so the tests never showed it. Filter extensions with &lt;code&gt;Where-Object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12. Backticks inside &lt;code&gt;"..."&lt;/code&gt;.&lt;/strong&gt; Inside a double-quoted PowerShell string the backtick is an escape character: Markdown like &lt;code&gt;`night-shift`&lt;/code&gt; turns &lt;code&gt;`n&lt;/code&gt; into a newline and the letter disappears. Use single-quoted here-strings for text that contains backticks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;13. A file being written shows 0 bytes.&lt;/strong&gt; A log being written by a background process listed as 0 bytes in &lt;code&gt;Get-ChildItem&lt;/code&gt;; opened, it held 5,000,000 bytes. On my machine this happened every time under &lt;code&gt;AppData&lt;/code&gt; and not under my home folder; I have not confirmed why. Open the file before concluding it is empty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14. &lt;code&gt;claude -p&lt;/code&gt; swallows the prompt.&lt;/strong&gt; &lt;code&gt;claude -p --allowedTools Read "say hi"&lt;/code&gt; failed with &lt;code&gt;Error: Input must be provided either through stdin or as a prompt argument when using --print&lt;/code&gt;. &lt;code&gt;--allowedTools&lt;/code&gt; and &lt;code&gt;--add-dir&lt;/code&gt; take any number of values, so they eat the prompt. Send the prompt on stdin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;15. A safety hook that answers late lets the write through.&lt;/strong&gt; I made a PreToolUse hook that always denies, but waits 15 seconds first, with a 3-second timeout. Claude Code wrote the file anyway — no error, no warning, three runs out of three. With a 60-second timeout it was blocked. The official hooks reference says the same thing: a timed-out PreToolUse hook does not block the call, so don't count on a stalled hook as a gate. The fix is one line: add &lt;code&gt;"onFailure": "block"&lt;/code&gt; to the hook (Claude Code 2.1.295 or later). With it, the same late hook blocked the write, and so did a hook whose script was missing.&lt;/p&gt;




&lt;p&gt;I packaged the fixes as &lt;strong&gt;cc-win-kit&lt;/strong&gt;: a write guard for Claude Code (with &lt;code&gt;onFailure: "block"&lt;/code&gt;), an unattended runner with stop conditions, a doctor that finds these files and fail-open hook settings on your machine, and a script that shows the hook-timeout hole with the real &lt;code&gt;claude -p&lt;/code&gt;. It's $19: &lt;a href="https://payhip.com/b/bRnDJ" rel="noopener noreferrer"&gt;https://payhip.com/b/bRnDJ&lt;/a&gt; (the trap reproduction script itself is the free one above)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: this post was written with AI assistance. Claude Code ran the reproduction scripts on my Windows machine and drafted the text; the results quoted above come from those runs.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>windows</category>
      <category>powershell</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
