[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

Status Open
Reported on v2.1.224
Maintainer reply None cached
Activity 1 comment · opened Sep 5, 2026

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?

  1. 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.
  2. 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.
  3. 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

  1. 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.
  1. 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 with Format-Hex repro.cmd that 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

  1. 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

  1. Run the batch under codepage 932:

cmd /c "chcp 932 >nul & ..\repro.cmd"

  1. Observe: f1.txt, f2.txt, f3.txt are all deleted; sub\ survives.
  1. 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

  1. Write produced the file as UTF-8, LF-only, no BOM (CR=0, LF=40). A pre-existing, hand-written .cmd in the same directory is CRLF + pure ASCII; only the three .cmd files Write generated that day are LF + UTF-8.
  2. 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 rem line ending in E3 80 82 (U+3002); its final byte 0x82 swallows the LF and the next line (set "IDA=...") is merged into the rem.
  3. Recorded stdout ('""' is not recognized, idat exit=9009) confirms the variable was empty at runtime.
  4. The same merge unsets %WORK%, so del /F /Q "%WORK%" 2>nul becomes del /F /Q "". Verified with a byte-length-preserving edit (@echo off → @echo on ) and reading the echoed, expanded commands.
  5. del /F /Q "" deletes every file in the CWD (isolated test: 3/3 gone, subdirectory intact). /Q suppresses the prompt, /F forces read-only files, 2>nul hides the errors.
  6. The session's CWD was the repository root (cwd field in the transcript), so the whole root was wiped; subdirectories survived because del is 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

  1. Write .cmd / .bat with CRLF on Windows, or preserve the existing file's line endings.
  2. Warn when a .cmd / .bat contains non-ASCII while the OEM codepage is not UTF-8.
  3. Check line endings and charset before executing a batch file generated in the same turn.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗