Claude Code can't add trailing newline
Bug Description Claude Code can't write files with a newline at the end even if explictly instructed to do so.
Environment Info
- Platform: macos
- Terminal: kitty
- Version: 0.2.19
- Feedback ID: b67373c4-f119-4d1c-8e62-8119531505c2
Transcript:
- User asks to create SAMPLE.md with a newline at the end
- Claude creates file but without trailing newline
- Hex dump confirms missing newline (ends with "2e" which is ".")
- Multiple attempts to add the newline using Replace tool fail
- Command verification with tail -c 1 SAMPLE.md | xxd -p shows "2e" after each attempt
I've tried a few prompts to get this to work, but it just got itself into a loop using hexdump to check if it succeeded or not and then trying various ways, but failing.
Yes please add a config option for automatic trailing newlines. Also Claude tries to gaslight you about it lol:
The Edit and Replace tools in Claude Code automatically add a trailing newline to files by default. This behavior is built into the tools and cannot be configured.
If you notice any files missing trailing newlines, please let me know and I can help fix them.
Then:
You're absolutely right. Even when using the Replace tool, the file didn't get a trailing newline. I've manually added one with the echo command, and now confirmed it has a proper trailing newline (0a is the newline character).
I was mistaken about the automatic behavior of the Edit and Replace tools. Thank you for pointing that out.
+1 Also affected by this issue on Linux.
The missing EOF newline causes problems when concatenating files with cat. For example:
- File A:
foo - File B:
bar cat A Boutputs:foobarinstead of expected:
foo
bar
This breaks POSIX compliance and many Unix tool assumptions.
What are you practising to enforce "newline fixing" on commit? (to "fix" newlines removed by Claude...?)
Some "search" findings:
Git Hooks Solutions
pre-commit-hooks
The pre-commit-hooks repository includes an end-of-file-fixer hook that will add (or normalize to exactly) one newline at EOF for each staged file (https://github.com/pre-commit/pre-commit-hooks).
pre-commit framework
You can integrate this via the pre-commit framework by listing the hook in .pre-commit-config.yaml:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: end-of-file-fixer
Pre-commit automatically installs and runs it on each commit, merging seamlessly with other hooks (pre-commit.com).
Custom Git hook script
For maximum control, a custom pre-commit hook in .git/hooks/pre-commit can:
-
Enumerate staged files:
git diff --cached --name-only --diff-filter=ACM. -
Filter by glob patterns using
caseorgrep -E: e.g., exclude*.mdor include onlysrc/**/*.js. -
Append a newline if missing:
if [ "$(tail -c1 "$file")" != "" ]; then printf '\n' >> "$file" git add "$file" fi
This pattern is commonly shared on StackOverflow and offers full flexibility (stackoverflow.com]).
This issue cannot be fixed purely with git hooks as the problem continues to exist outside of git-controlled directories.
Just adding that this problem exists beyond Claude executing commands to update files while working. For instance, Claude also consistently strips newlines from CLAUDE.md files when using # command prefix.
Ok, is there a flag finally or better, configuration setting made for making claude code to respect Linux standard of new lines at the end of file finally?
(or ability to configure for claude "post processing hook" to run over each touched by claude file so we could make hook for that ?)
Is this issue still valid?
I've had this issue forever so I've used this custom hook:
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read file_path; dos2unix -e -q \"$file_path\" 2>/dev/null || true; }"
}
]
}
]
},
But today I've tried to generate some files with Claude Code without it and... it worked? But no mention in CC Changelog and this issue is still Open. Weird...
I had recently some generations that missed newline, and I stopped tracking when/what/why happens, as it's flaky...
Still surprinsing to me that such problem takes so long to properly resolve and document in documentation how to configure for/by users...