claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Claude Code can't add trailing newline

Open steinerkelvin opened this issue 10 months ago • 6 comments

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:

  1. User asks to create SAMPLE.md with a newline at the end
  2. Claude creates file but without trailing newline
  3. Hex dump confirms missing newline (ends with "2e" which is ".")
  4. Multiple attempts to add the newline using Replace tool fail
  5. Command verification with tail -c 1 SAMPLE.md | xxd -p shows "2e" after each attempt

steinerkelvin avatar Feb 27 '25 10:02 steinerkelvin

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.

brandonbloom avatar Mar 08 '25 22:03 brandonbloom

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.

techjanitor avatar Mar 17 '25 23:03 techjanitor

+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 B outputs: foobar instead of expected:
foo
bar

This breaks POSIX compliance and many Unix tool assumptions.

gwpl avatar Jun 15 '25 16:06 gwpl

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:

  1. Enumerate staged files: git diff --cached --name-only --diff-filter=ACM.

  2. Filter by glob patterns using case or grep -E: e.g., exclude *.md or include only src/**/*.js.

  3. 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]).

gwpl avatar Jun 23 '25 19:06 gwpl

This issue cannot be fixed purely with git hooks as the problem continues to exist outside of git-controlled directories.

norm avatar Jun 27 '25 16:06 norm

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.

brandonbloom avatar Jun 28 '25 19:06 brandonbloom

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 ?)

gwpl avatar Aug 18 '25 18:08 gwpl

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

morsik avatar Nov 18 '25 08:11 morsik

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

gwpl avatar Nov 18 '25 11:11 gwpl