Auto-format generated Code with Claude Code Hooks
How to set up a PostToolUse hook in Claude Code to automatically run prettier after every file edit or write operation.
Claude Code is great at editing files, but it doesn’t automatically format them. If your project uses prettier, you’ll end up running it manually after every edit. That gets old fast.
The fix: a PostToolUse hook that runs prettier automatically after every Write or Edit operation - but only if the repo actually has prettier installed.
The official docs show a one-liner for this, but it pipes every edit into npx prettier --write. In a repo without prettier, npx will offer to download it mid-session - not what you want from a background formatter. The setup below guards against that: no prettier in the project, no formatting.
For the full hooks reference, see the Claude Code hooks documentation.
The Setup
Two files needed: a hook configuration and a bash script.
1. Add the hook to your settings
Edit ~/.claude/settings.json and add the hooks configuration:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/prettier-formatter.sh",
"async": true
}
]
}
]
}
}
The async: true option lets the hook run in the background - Claude Code won’t wait for prettier to finish before continuing. This keeps things snappy since formatting doesn’t block the next operation.
2. Create the formatter script
Create ~/.claude/hooks/prettier-formatter.sh:
#!/bin/bash
set -e
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
# Skip if no file path
[ -z "$file_path" ] || [ "$file_path" = "null" ] && exit 0
# Only format supported file types
echo "$file_path" | grep -qE '\.(js|jsx|ts|tsx|json|css|scss|html|md|yaml|yml|svelte)$' || exit 0
project_dir="${CLAUDE_PROJECT_DIR:-.}"
# Check if prettier is in package.json
if [ -f "$project_dir/package.json" ]; then
grep -qE '"prettier"' "$project_dir/package.json" || exit 0
else
exit 0
fi
# Run prettier if available
if [ -f "$project_dir/node_modules/.bin/prettier" ]; then
"$project_dir/node_modules/.bin/prettier" --write "$file_path" 2>/dev/null || true
fi
exit 0
Make it executable:
chmod +x ~/.claude/hooks/prettier-formatter.sh
How It Works
The script receives JSON input from Claude Code containing details about the tool that just ran. It extracts the file path, then:
- Checks if the file type is something prettier handles
- Looks for prettier in the project’s
package.json - Runs the local prettier binary if it exists
If any check fails, it exits silently. No prettier in the repo? No problem - the hook just does nothing.
Verify It’s Working
Run /hooks in Claude Code to see your registered hooks. Then edit a file in a project with prettier installed - it should format automatically.
Alternatives and Recent Updates
A few things have changed since this post was written:
- Share hooks with your team: instead of
~/.claude/settings.json, put the hook config in.claude/settings.jsonat the project root and commit it. Everyone on the team gets identical formatting behaviour with no per-user setup. FileChangedhooks: newer versions of Claude Code can watch specific files and fire when they change on disk - no matter what wrote them, including Bash commands. If you need coverage beyond theWriteandEdittools, that’s the event to reach for.- Consecutive edits are safe: a formatter rewriting a file between two of Claude’s edits to the same file used to trigger
File content has changederrors. Fixed in Claude Code v2.1.90 - worth knowing if you’re on an older version.