[BUG] PostToolUse hooks modify files but changes are overwritten/don't persist

Resolved 💬 5 comments Opened Oct 20, 2025 by panozzaj Closed Oct 21, 2025

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?

PostToolUse hooks execute successfully but file modifications are immediately reverted. When a hook appends content to a file or modifies it in any way after a Write/Edit operation, the changes don't persist on disk even though the hook reports success.

What Should Happen?

PostToolUse hooks should be able to modify files after Write/Edit/MultiEdit operations complete, and those modifications should persist on disk. This is a documented use case for code formatters and linters.

Error Messages/Logs

No error messages - the hook reports success:

  PostToolUse hook success (blocking):
  FILE_PATH extracted: /Users/anthony/Documents/dev/my-project/test_path_debug.rb
  APPENDED to /Users/anthony/Documents/dev/my-project/test_path_debug.rb

However, checking the file shows the modification didn't persist:

  $ cat test_path_debug.rb
  class PathDebugTest
    def greet
      puts "hello"
    end
  end
  # No "# Hook was here" comment present

Steps to Reproduce

  1. Create .claude/config.json with this hook configuration:
  {
    "hooks": {
      "PostToolUse": [
        {
          "matcher": "^(Edit|MultiEdit|Write)$",
          "hooks": [
            {
              "type": "command",
              "command": "./bin/simple-append-hook.sh"
            }
          ]
        }
      ]
    }
  }
  1. Create ./bin/simple-append-hook.sh:
  #!/bin/bash
  FILE_PATH=$(jq -r '.tool_input.file_path // empty' | head -1)

  echo "FILE_PATH extracted: $FILE_PATH" >&2

  if [ -n "$FILE_PATH" ] && [ -f "$FILE_PATH" ]; then
    echo "# Hook was here" >> "$FILE_PATH"
    echo "APPENDED to $FILE_PATH" >&2
  else
    echo "File not found or empty path: $FILE_PATH" >&2
  fi

  exit 0
  1. Make it executable: chmod +x ./bin/simple-append-hook.sh
  2. Restart Claude Code session
  3. Ask Claude to create any file (e.g., "Create a file test.rb with a simple Ruby class")
  4. Observe the hook output shows success: "APPENDED to test.rb"
  5. Check the file: cat test.rb - the appended comment is missing

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

not sure

Claude Code Version

2.0.24

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

zsh

---

This affects any PostToolUse hook that modifies files, including common documented use cases:

  • Code formatters (prettier, rubocop, black, gofmt) (we tested Rubocop specifically first, then narrowed this down)
  • Linters with auto-fix (eslint --fix)
  • Adding file headers

The hook receives the correct file path, finds the file, executes without errors, and reports success. But modifications are
silently reverted, suggesting the Write tool may flush a buffer or hold a file handle that overwrites changes after the hook
completes.

Related: Blog post describing this pattern as working:
https://writeaheadblogg.ing/posts/claude-hooks-auto-fix-trailing-whitespace/

---

Note from Anthony: Hi maintainers, thank you for looking at this! I went back and forth with Claude Code to debug this, and had it write up this description. Hope this is helpful, happy to answer any questions you might have. Also open to the possibility that wea are doing something wrong. 😄

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗