[BUG] Write emits .cmd as UTF-8 + LF-only on Windows; cmd.exe (CP932) swallows the LF after a multibyte char, del /F /Q "%VAR%" degenerates to del /F /Q "" and deletes every file in the CWD
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
On a Japanese-locale Windows machine (OEM codepage 932), the Write tool created a .cmd helper as UTF-8 with LF-only line endings. cmd.exe parses batch files using the OEM codepage, so a trailing 。 (U+3002 = E3 80 82) makes its last byte 0x82 look like a CP932 lead byte, which consumes the following 0x0A. The next line — set "IDA=..." — is absorbed into the preceding rem and never executes. With the variables unset, del /F /Q "%WORK%" expands to del /F /Q "", which deletes every file in the current working directory.
The agent's CWD was the repository root, so 1,068 files were permanently deleted in one second (USN journal: FILE_DELETE|CLOSE, no RENAME records → not recycled). Subdirectories survived because del is non-recursive. 123 files were unrecoverable.
Changing only the line endings to CRLF makes the bug disappear. Claude Code's own file-history shows the pre-edit backup was also LF-only, so this is "generated batch files don't follow the platform convention", not "Write corrupted an existing CRLF file".
What Should Happen?
- Write should emit .cmd / .bat files on Windows with CRLF line endings (or preserve the existing file's line endings), since cmd.exe parses batch files with the OEM codepage and LF-only + non-ASCII is not safe under CP932.
- Given the generated file, the batch should only touch the file named by %WORK%. Line 4 (set "WORK=...") should execute, and del /F /Q "%WORK%" should expand to a single specific path.
- Ideally, Write (or the Bash tool before executing a .cmd generated in the same turn) warns when a .cmd/.bat contains non-ASCII while the OEM codepage is not UTF-8.
Error Messages/Logs
--- recorded stdout of the incident run (the batch's own output, 249 B) ---
'""' is not recognized as an internal or external command,
operable program or batch file.
idat exit=9009
--- same bytes, @echo off -> @echo on (byte-length-preserving edit), expanded commands as cmd.exe saw them ---
del /F /Q "" 2>nul
del /F /Q ".i64=.id0WORK:.i64=.id1WORK:.i64=.id2WORK:.i64=.namWORK:.i64=.til" 2>nul
copy /Y "" "" 1>nul
"" -A -S" 0x142A0B5C0 0x142A0B450" -L"" ""
--- tail hexdump of the rem line (line 3 of the minimal repro) ---
... E5 87 BA E3 81 99 EF BC 89 E3 80 82 | 0A
^^ ^^
CP932 lead swallowed LF
--- NTFS USN journal (fsutil usn readjournal), 1,068 records in the same second ---
reason 0x80000200 = FILE_DELETE | CLOSE, parent FRN = repo root directory
RENAME records: 0 (not moved, not recycled)
--- line-ending stats of the generated file ---
CR=0 LF=40 BOM=none encoding=UTF-8
pre-edit backup in .claude/file-history: also CR=0, LF-only
Steps to Reproduce
- Use a Windows machine whose OEM codepage is 932 (Japanese locale; registry HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage OEMCP=932, "Beta: Use Unicode UTF-8" disabled). Any DBCS OEM codepage (949, 936, 950) should behave the same, but 932 is what was tested.
- Save the following 5 lines as
repro.cmd, UTF-8, LF-only, no BOM. Line 3 must end with。(U+3002 = E3 80 82). Do NOT paste this through a chat window or editor that normalizes line endings — verify withFormat-Hex repro.cmdthat there is no 0x0D anywhere (CR=0, LF=4).
@echo off
setlocal
rem 速度が要るときだけ VMRE_IDB_KEEP=1 で持ち越す(そのとき py 側が NEW FUNC 警告を出す)。
set "WORK=C:\Temp\work.i64"
del /F /Q "%WORK%" 2>nul
- Create an isolated directory with dummy files and one subdirectory, and make it the CWD:
mkdir iso; cd iso; 1..3 | % { "x" > "f$_.txt" }; mkdir sub
- Run the batch under codepage 932:
cmd /c "chcp 932 >nul & ..\repro.cmd"
- Observe: f1.txt, f2.txt, f3.txt are all deleted; sub\ survives.
- Control: convert ONLY the line endings of the same file to CRLF (
(Get-Content -Raw ..\repro.cmd) -replace "n","rn" | Set-Content -NoNewline -Encoding utf8 ..\repro_crlf.cmd`), re-create the dummies, run again. Nothing is deleted.
Results (isolated dir, 3 files + 1 subdir):
LF-only -> files left 0/3, subdir 1/1
CRLF -> files left 3/3, subdir 1/1
full original (2,294 B) LF -> 0/3
full original CRLF -> 3/3
Note: the minimal repro was produced by deleting lines from the original only. Rewriting it from scratch shifts the byte offsets and the failure may not appear — the CP932 mis-read is byte-position dependent. Likewise, instrumenting it with an edit that changes byte length (e.g. replacing del /F /Q with echo) hides the bug; use a length-preserving edit such as @echo off -> @echo on if you want to see the expanded commands.
How this file came to exist: on 2026-09-05 the Write tool created and later rewrote a .cmd helper in a Windows project (Claude Code 2.1.224,
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.224
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Cursor
Additional Information
repro_min_crlf.zip
Byte-exact repro files (LF / CRLF control)
Environment (not covered by the form fields)
| item | value |
|---|---|
| Node | v26.7.0 |
| OS | Windows 11 Pro 25H2, build 26200.9168, OSLanguage 1041 |
| Locale | ja-JP; registry ACP=932, OEMCP=932; "Beta: Use Unicode UTF-8" disabled |
| Console codepage at incident | [inferred] 932 — reproduction under chcp 932 matches the recorded stdout; the actual chcp value at the time was not obtained |
| Permission mode | normal (from the session's {"type":"mode"} record; not bypass) |
| Launch path | Claude Code was launched from Cursor's integrated terminal (the only way it is used on this machine). The exact process tree at incident time was not recoverable; the batch itself was invoked through PowerShell (EventLog Microsoft-Windows-PowerShell/Operational, 4104 ScriptBlock, RecordId 1460819) |
Causal chain
- Write produced the file as UTF-8, LF-only, no BOM (CR=0, LF=40). A pre-existing, hand-written
.cmdin the same directory is CRLF + pure ASCII; only the three.cmdfiles Write generated that day are LF + UTF-8. - Read as CP932, there are 11 offsets where a lead byte (0x81–0x9F / 0xE0–0xFC) is immediately followed by 0x0A. The decisive one is a
remline ending in E3 80 82 (U+3002); its final byte 0x82 swallows the LF and the next line (set "IDA=...") is merged into therem. - Recorded stdout (
'""' is not recognized,idat exit=9009) confirms the variable was empty at runtime. - The same merge unsets
%WORK%, sodel /F /Q "%WORK%" 2>nulbecomesdel /F /Q "". Verified with a byte-length-preserving edit (@echo off→@echo on) and reading the echoed, expanded commands. del /F /Q ""deletes every file in the CWD (isolated test: 3/3 gone, subdirectory intact)./Qsuppresses the prompt,/Fforces read-only files,2>nulhides the errors.- The session's CWD was the repository root (
cwdfield in the transcript), so the whole root was wiped; subdirectories survived becausedelis non-recursive.
Scope note
Claude Code's own .claude/file-history pre-edit backup of this file is also LF-only, so this is not Write converting an existing CRLF file — the file was created LF-only in the first place. The report is "generated batch files do not follow the platform convention", not "Write corrupted an existing file".
Suggested fixes
- Write
.cmd/.batwith CRLF on Windows, or preserve the existing file's line endings. - Warn when a
.cmd/.batcontains non-ASCII while the OEM codepage is not UTF-8. - Check line endings and charset before executing a batch file generated in the same turn.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗