[FEATURE] A setting for Edit and Write to write exactly what they're given
Summary
Outside Markdown, Edit and Write strip the trailing spaces and tabs of every line they write
(new_string, content), while Edit matches old_string exactly as given. For precision edits,
please add a setting, such as "preserveTrailingWhitespace": true (or a list of globs), under which
both tools write their input byte for byte, for every file type.
Related: #100296 reports the same stripping as a bug (a whitespace-only new_string becomes a
deletion). This request asks for a way to turn it off, and adds a second corrupting case below.
Current behavior
Measured on Claude Code 2.1.296 (VS Code extension, Windows 11), with the session transcript and a
PreToolUse hook to see what each stage receives:
| Call | .txt | .md |
| -------------------------------------------------------------------- | --------------------------------------- | ------------------ |
| Write, a line ending in three spaces, another in a tab | both stripped | both kept |
| Edit, new_string with a line ending in spaces | stripped | kept |
| Edit, old_string: "A1: readarray -t " → new_string: "A1: read_lines " | file reads A1: read_linesone | A1: read_lines one |
| Edit, new_string differing from old_string only by trailing spaces | refused: "old_string and new_string are exactly the same" | applied |
- Leading and inner whitespace and trailing newlines are kept; only spaces and tabs at line ends go.
old_stringkeeps its trailing whitespace. A PreToolUse hook receives it intact, but receives
new_string already stripped, and the transcript records new_string/content stripped too.
- The Bash tool's
commandkeeps trailing whitespace, so it isn't the model's output that loses it. - The 2.1.89 changelog entry "Fixed Edit/Write tools ... stripping Markdown hard line breaks" (and
#12594's "no longer strip trailing spaces in .md/.mdx files") reads as an exemption for Markdown,
leaving the stripping in place for everything else.
Why it matters
- It corrupts code silently. The asymmetry between
old_string(exact) andnew_string
(stripped) means any edit whose strings end in a space joins two tokens: replacing
readarray -t with read_lines across a codebase produced read_linesFOO in eight shell
scripts. Nothing reported it; the tool said the edit succeeded.
- Some files need trailing whitespace. Test fixtures and golden files, diff and patch text,
heredocs that must match byte for byte, formats where trailing spaces are significant (beyond
Markdown). They can't be written with Edit or Write at all.
- It's invisible. It isn't in the tools' descriptions, so neither the model nor the user
expects it, and both lose time finding out why an edit went wrong.
Proposal
- A setting (in
settings.json, so a project can commit it) that turns the stripping off: Edit and
Write write their input exactly, for every file, or for the files matching given globs.
- Independently of the setting, apply the same rule to
old_stringandnew_string: either strip
neither or treat both alike, so that an edit can never remove whitespace it doesn't put back.
- Mention the behavior (and the setting) in the Edit and Write tool descriptions.
Workaround we use meanwhile
A PreToolUse hook on Edit refuses an old_string that ends in a space or tab in a non-Markdown file,
which catches the corrupting case. Intended trailing whitespace in other files still can't be
written.