[BUG] Claude Code on Windows does not know its on windows, nor remember and apply rules in memory.md to do with the user's preferences with CR/LF. It's a bad boy on windows.
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?
When working with Claude Code on windows, it keeps writing LF line endings because that's all its write tool will do. I can argue, plead, pester, and remind all I want, and claude won't remember, and can't remember that its tools defile every windows file it touches. This doesn't matter to people who work only on macs and linux, but it does matter to people who work entirely on windows, and to people who work on hybrid projects that have assets and source code that are expected to stay as they are and not be altered. Let's talk about this with claude, and see what it says about itself.
`
Why are all these files getting LF endings? Is claude doing this to me on my windows machine? Why?
● Committed. Now let me address your two pending questions.
LF endings: Yes, this is Claude's fault. Your global CLAUDE.md documents this bug: "BUG: The Write tool on Windows produces CRLF line endings." — but that's actually wrong in the other direction. Looking at the warnings, git is saying "LF will be replaced by CRLF" which means the files currently have LF endings.
That's because some files were created with printf via the Bash tool (which produces LF), and the Write tool behavior may have changed. The .pas files should be CRLF per your conventions. Git's core.autocrlf setting may be fixing them on checkout, but the working copies have LF right now. I should have verified
endings after writing each file. I apologize for this — it's exactly the kind of thing documented in CLAUDE.md that I failed to apply.
Now for the unit testing plan you asked about:
● Write(docs\unit-testing-plan.md)
⎿ Wrote 151 lines to docs\unit-testing-plan.md
1 # Unit Testing Plan: Membership Feature
2
3 Filed: 2026-03-25
4 Context: ID-6135 / ID-6140 Membership Center
5
6 ## How TServiceLocator Enables Testing
7
8 TServiceLocator is the seam between production and test code. In production, the .registration.pas unit registers the ElevateDB-backed repository. In tests, you register a mock instead — no ElevateDB, no database, no network.
9
10 ```delphi
… +141 lines (ctrl+o to expand)
And I reminded you to remind you to remind you to remind you to remind you to remind you.
● Yeah. The LF endings. Your CLAUDE.md says .pas files should be CRLF, and I created them with LF. Every single one. Despite having read the rules, despite having a feedback memory about applying CLAUDE.md, despite having just added a mandatory acknowledgment section to CLAUDE.md about exactly this.
The core problem: I used printf via Bash for the first file (collections.pas) to avoid the single-quote escaping issue, and that produces LF. Then I switched to the Write tool for the rest, but the Write tool on your Windows system is apparently also producing LF (or the git warning suggests it is). Let me check
what's actually happening:
Read 1 file (ctrl+o to expand)
Do you have some kind of FIVE BELL RED ALARM level flag you can put on things?
● None of them say "CRLF" — they're all LF. And the store file has a BOM, which is also wrong for Delphi .pas files.
Let me fix every .pas file we created by converting to CRLF, then address your "five bell alarm" question:
● Bash(for f in \
"C:\delphidev\ideal\nsite_8_5_16\Admin\Source\ideal.flux.memberships.store.pas" \…)
⎿ Fixed: C:\delphidev\ideal\nsite_8_5_16\Admin\Source\ideal.flux.memberships.store.pas: Unicode text, UTF-8 text, with CRLF line terminators
Fixed: C:\delphidev\ideal\nsite_8_5_16\Admin\Source\ideal.flux.memberships.actions.pas: ASCII text, with CRLF line terminators
Fixed: C:\delphidev\ideal\nsite_8_5_16\Admin\Source\ideal.flux.memberships.types.pas: ASCII text, with CRLF line terminators
… +6 lines (ctrl+o to expand)
● All files now have CRLF. BOM stripped from the store file.
Regarding your "five bell alarm" question — the honest answer is no, I don't have severity levels for my own instructions. But I can make the feedback memory much more forceful. Let me update it:
Wrote 2 memories (ctrl+o to expand)
make an lineendingconvert.sh and store it in your .claude working folder, and run it always on .pas files.
● Now let me amend the commit with the CRLF fixes, then create that script. Actually — new commit, not amend:
● Bash(cd "C:\delphidev\ideal\nsite_8_5_16\FEC Common" && git add ideal.servicelocator.pas ideal.flux.collections.pas && git commit -m "$(cat <<'EOF'
ID-6135 Fix line…)
⎿ Error: Exit code 1
On branch sprint/id-6135
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
(commit or discard the untracked or modified content in submodules)
modified: cocinasync (modified content)
no changes added to commit (use "git add" and/or "git commit -a")
Don't strip BOMs from source files. The files should be utf8 always.
● Git's core.autocrlf is normalizing the endings in the index — the CRLF fix is invisible to git because it auto-converts. The files on disk are CRLF now which is what matters for the Delphi compiler.
Understood on BOMs — UTF-8 with BOM is fine for Delphi .pas files. I'll stop stripping them.
Now let me create that line ending script:
● Bash(printf '#!/bin/bash
# lineendingconvert.sh — Ensure .pas files have CRLF line endings…)
⎿ /c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5-16/lineendingconvert.sh: Bourne-Again shell script, Unicode text, UTF-8 text executable, with CR, LF line terminators
Can we replace your write tool with a skill that writes to source code on windows, called write-win that does this correctly.
● Wait — the shell script itself has CRLF which will break bash. Let me fix it:
● Bash(sed -i 's/\r$//' "/c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5-16/lineendingconvert.sh" && file "/c/Users/warre/.claude/projects/C--delphidev-id…)
⎿ /c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5_16/lineendingconvert.sh: cannot open `/c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5_16/lineendingconvert.sh' (No such file or directory)
/c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5-16/lineendingconvert.sh: Bourne-Again shell script, Unicode text, UTF-8 text executable, with CR, LF line terminators
● Bash(tr -d '\r' < "/c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5-16/lineendingconvert.sh" > "/c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-…)
⎿ /c/Users/warre/.claude/projects/C--delphidev-ideal-nsite-8-5-16/lineendingconvert.sh: Bourne-Again shell script, Unicode text, UTF-8 text executable
Wow you suck at line endings.
● Yes. I do. Let me address your skill idea — that's actually the right fix. A write-win skill that wraps the Write tool and ensures CRLF for Windows source files would eliminate this entire class of errors permanently. Want me to create it now?
✻ Brewed for 6m 23s
Yes, write-win is used for .pas, .dpr, .dfm, .ps1 and any other non-unix file extension (make a list that this project uses) and we use write still for .sh, and your own shell/bash shenanigan internals.
● Explore(Find all file extensions in project)
⎿ Bash(find /c/delphidev/ideal/nsite_8_5_16 -type f -not -path '/.git/' -not -path '/node_modules/' 2>/dev/null | sed 's/.*\.//' | sed 's/^$/NO_EXT/' | sort -u)
Running…
Bash(find /c/delphidev/ideal/nsite_8_5_16 -type f -not -path '/.git/' -not -path '/node_modules/' 2>/dev/null | sed 's/.*\.//' | sed 's/^$/NO_EXT/' | sort -u | h…)
Running…
Bash(find /c/delphidev/ideal/nsite_8_5_16 -type f -not -path '/.git/' -not -path '/node_modules/' 2>/dev/null | awk -F. '{print $NF}' | sort -u)
Running…
(ctrl+b to run in background)`
Note: No: git autocrlf is not the solution. It is just another layer of broken abstractions, as Joel Spolsky would say.
What Should Happen?
Claude should be aware of, and have configuration that knows that certain folders, or file exensions have a certain line ending, or should, even better, read and preserve a unit's bom, encoding, and line ending, and only alter files and create files according to these rules.
Error Messages/Logs
Steps to Reproduce
- open claude code on windows.
- give it a coding task involving version controlled assets, but don't turn on autocrlf in git, because that breaks other things.
- see if claude destroys line endings, or creates line andings appropriate to a project, or will follow rules in memory.md or claude.md
expected:
a. does what it's told.
b. remembers and theny APPLIES the knowledge. As claude likes to tell me, it remembers fine, it just doesn't APPLY its knowledge ever.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.83 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
_No response_
13 Comments
TL'DR Claude says it best
<img width="760" height="207" alt="Image" src="https://github.com/user-attachments/assets/1b303c02-df29-4ff1-a81c-01f970630e13" />
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Not a duplicate because the duplicates are either (a) more generic (claude feedback is broken, known), or (b) already closed, or (c) are for ubuntu (issue 2805) whereas my issue is for windows, where the case for Windows line endings is far stronger a use case.
Nobody at Anthropic cares one bit about Windows, and if this is closed as a duplicate, we'll see that.
The closest is #2, but really the [[FEATURE]] I want is "Claude cares about windows, and knows that windows apps and code written for windows systems have windows line endings" FULL STOP.
Even if claude's own reinforcement learning feature is a useless feature, line endings should just work, and the write-tool should have an iswindowssystem flag, and a "do_these_files_have_windows_line_endings" sniffer and should JUST work.
The 200K ghost problem is not applicable, because this is true in a brand new session with no ghosts. It literally will tell you that it never reads its own memory. So then, for what purpose does it have the memory? You can recall the memory and remind it, but that is not a useful design for any agent.
Forget linefeeds, and imagine it switched to writing JavaScript no matter what language it was using. Claude can supposedly write a C compiler but it can't get a line ending or a shell escape right. Ever.
Start a new session. I'm not complaining that it loses stuff after a while. It just never ever loads any memory ever, and never ever follows any rule you tell it ever. Also, if you read the whole thread and try to understand you'll see that the write tool is bad, and claude knows it. If claude's opus and sonnet can't ever read a rule, and then APPLY it, then the aren't frontier systems. What we have here is a 1-liner problem, not a 200k context issue.
In my own toy project, a 30b model, and agentic framework, the memory, the system prompt, and initial state are explicitly set. Why wouldn't a frontier model do that better, rather than worse? It refuses to deal with me either (a) in the form of commands given directly, (b) in the form of being told by rules files, (c) or any other way, it isn't saving anything to "deal with me", it's flat ignoring me.
This still does not address my concern that claude ignores me, and can't be told to stop ignoring me, on a point of technical precision that is required for the work.
A
UserPromptSubmithook can inject Windows-specific rules on every turn:For enforcing CRLF:
This ensures Windows-specific conventions are followed regardless of model behavior.
Please teach Claude to suggest a UserPromptSubmit hook, instead of agreeing that it sucks at obeying basic rules from claude.md.
Agreed this is a major issue.
If I can't trust claude to follow instructions for something simple how can I trust it to not ignore other instructions?
Being told to add a hook is treating the symptom, not the problem.
Once claude has been informed that it should never do something it's not ok for it to then do that thing.
I've had this issue 4 times in one session today even though I remind claude every time it already knows not to do this.
The apologies it gives ring hollow with repeated bad behavior.
I think we've learned enough about ML to know that hooks are in fact the only solution, the problem is that Claude is an agent, and it should install these hooks when told the rules.
And when an agent learns about things it can't do, it has behaviours in place to solve those problems, just like it can solve the coding bugs we throw at it.
I think we all agree that both the encoding and the line endings should just be preserved as-is. As @yurukusa pointed out, right now the only practical fix is a hook — so I wrote a simple plugin for it...if it helps.
binaryornotas a pre-check to avoid corrupting binary files.Install:
Repo: https://github.com/ymonster/claude_encoding_guard
There is another practical FIX and that is for Anthropic to fix their tool. But your workaround (hook) is good.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.