Describe the Bug
When the agent creates a new file on Windows it writes CRLF, even in a repository where every configuration source asks for LF and every existing file already is LF.
Only creations are affected. A replace-style edit to a file that is already LF leaves it LF, which is what makes the workspace stay uniform and the bug easy to miss. It also means the file tools do follow the surrounding evidence when there is a file in front of them, and fall back to CRLF exactly when there is not.
| Operation | Result |
|---|---|
| Agent creates a new file | w/crlf |
| Agent replaces a string in an existing LF file | Stays w/lf |
This is not a cosmetic problem. A file created as CRLF under eol=lf is normalized by git the moment it is staged, so the bytes on disk stop matching the bytes git records. Three things follow. Every such file carries a phantom diff that nobody wrote. Any tooling that fingerprints the working tree by hashing file contents sees the digest change across a commit that changed nothing, and discards results that were still valid. And on a mixed-platform team the file arrives on macOS or Linux with CRLF, where a shell script with CRLF line endings does not run at all.
Steps to Reproduce
Confirmed on 3.15.19 (Windows 11, PowerShell). No hooks or extensions are needed, and no Cursor setting other than files.eol is involved.
- In a git repository on Windows, create
.gitattributescontaining* text=auto eol=lf. - Create a root
.editorconfigcontainingend_of_line = lf. - Create
.vscode/settings.jsoncontaining"files.eol": "\n". - Normalize the existing tree so no CRLF file remains, with
git rm --cached -r .followed bygit reset --hard HEAD. That second command discards uncommitted work, so commit or stash first —git add --renormalize .is the gentler route if you would rather stage the conversion as a commit. Confirm it took:git ls-files --eolshould reportw/lffor every file, andgit ls-files --eol | Select-String -Pattern "w/crlf"should match nothing. - Restart Cursor.
- Ask the agent to create any new text file. → The file is written with CRLF.
- Check it without opening it, since opening it in the editor is itself a write in some configurations:
git ls-files --eol -o --exclude-standard -- <path>. The working-tree column reportsw/crlf. Drop--exclude-standardif the path is gitignored, or the file is filtered out of the answer and the empty result reads like a pass. - For the contrast, ask the agent to replace a string inside a file that is already LF, and check the same way. → It stays
w/lf.
Expected Behavior
- A file the agent creates should be written with the line endings the workspace asks for. The precedence VS Code already implements is the obvious one to follow:
.editorconfigif the EditorConfig extension is active, thenfiles.eol, then the platform default..gitattributesis a reasonable fourth source and the most authoritative of the three files here, since it is the one that already states the policy for everyone else on the project. - Failing that, the documented heuristic should at least be reachable. If the intended behavior really is “look at existing files in the workspace,” then a workspace of 1037 files that are unanimously LF is the easiest possible case for it and it should not be producing CRLF. As it stands the heuristic’s stated input appears not to be consulted on the creation path.
files.eolshould not be silently inapplicable to a whole class of writes. The setting is presented in the UI as the workspace’s line-ending policy. A user who sets it, and a user who is told in a support thread to set it, has no way to discover that agent-created files are exempt.
Operating System
Windows 10/11
Version Information
Version: 3.15.19 (system setup)
VS Code Extension API: 1.128.0
Commit: de07bee81cefe43461ebf4f40c3d2d78d15052a0
Date: 2026-08-11T05:22:54.627Z
Layout: IDE
Build Type: Stable
Release Track: Default
Electron: 40.10.3
Chromium: 144.0.7559.236
Node.js: 24.15.0
V8: 14.4.258.32-electron.0
xterm.js: 6.1.0-beta.291
OS: Windows_NT x64 10.0.26200
For AI issues: which model did you use?
Not model-specific — this is file-writing behavior rather than model behavior. Observed across several models and separate sessions.
For AI issues: add Request ID with privacy disabled
N/A
Additional Information
Workaround:
An afterFileEdit hook can convert the file immediately after the write. Mine asks git what the repository wants for that one path and does nothing unless the answer is lf, so a single hook is safe across every workspace root and a repository that wants CRLF is untouched:
{
"version": 1,
"hooks": {
"afterFileEdit": [
{ "command": "node .cursor/hooks/normalize-eol.js", "matcher": "^(?!Tab).+", "timeout": 30 }
]
}
}
The script reads file_path from the payload, returns immediately if the contents hold no \r or hold a NUL byte, runs git check-attr eol -- <path> from the file’s own directory, and rewrites /\r+\n/g to \n only when the answer is lf. It fails open in every direction, since the worst case is the file keeping the newlines Cursor gave it. Verified working: with the hook registered, a newly created file in the repository above comes out w/lf; with the hook’s matcher deliberately set to something that cannot match, the same creation comes out w/crlf again.
Two notes on that hook, both relevant to Cursor rather than to me. It collapses runs of carriage returns rather than CRLF alone, because the sibling bug where the tools write \r\r\n produces a file that reads as double-spaced and a plain CRLF replacement would leave a stray \r behind. And it cannot be narrowed to creations, which is the case that actually needs it: an afterFileEdit matcher filters by tool type only, per the docs, and creation is distinguishable solely in the payload — edits[0].old_string is empty — which is read after the process has already started. So the cost of this workaround is a Node process on every agent edit, and there is no matcher that would reduce it. Both agent creations and agent replace-edits are reported to the matcher as the same tool type, Write.
Related threads:
The original report, on macOS, acknowledged: “This is a bug on the agent tooling side. When it writes files, it doesn’t respect the files.eol setting.” February 2026.
The Windows re-report, filed because the first thread was closed to comments, acknowledged with the heuristic explanation this report is a counter-example to, and with “there isn’t a good workaround specifically for creating new files.” March 2026.
The nominated tracking thread, which is a different bug in the same area: files rewritten wholesale on startup or update rather than on creation. Marked fixed in 2.5.25 and reported as returning in 2.6.12 and 3.1.10.
The \r\r\n form, which looks like a formatting bug and is the same class of defect.
Does this stop you from using Cursor
No - Cursor works, but with this issue