[BUG] PostToolUse hooks modify files but changes are overwritten/don't persist
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
- Create .claude/config.json with this hook configuration:
{
"hooks": {
"PostToolUse": [
{
"matcher": "^(Edit|MultiEdit|Write)$",
"hooks": [
{
"type": "command",
"command": "./bin/simple-append-hook.sh"
}
]
}
]
}
}
- 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
- Make it executable:
chmod +x ./bin/simple-append-hook.sh - Restart Claude Code session
- Ask Claude to create any file (e.g., "Create a file test.rb with a simple Ruby class")
- Observe the hook output shows success: "APPENDED to test.rb"
- 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. 😄
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗