StepGleam logoStepGleam
Coding guide

Set up Claude Code hooks for formatting, tests and protected files

Add PostToolUse hooks that format and test after edits, a PreToolUse hook that blocks protected files, and a notification for long runs.

~30 minIntermediate 82/100 6 steps Updated Oct 26, 2026
Claude CodeGit
Set up Claude Code hooks for formatting, tests and protected files — illustration for this Coding guide

Tools used

  • Claude CodeRuns the hooks at each lifecycle event
  • GitShares the project settings with the team
Step navigator0/6 done
0 of 6 steps done
What you'll get

A committed .claude/settings.json with hooks that run every time, whatever the model decides.

Who this is for

Claude Code users who keep reminding it to format, test, or stay out of certain files.

Read this first

Before you start

Developers on r/ClaudeAI call hooks the feature most people skip. The setups they share are the same four: run tests after edits, format after edits, block certain files, and notify when a run finishes. Claude Code's docs give the exact config.

Step-by-step instructions

Step 1 of 6 · Coding

Use hooks for anything that must always happen

Instructions in CLAUDE.md are advisory; hooks are deterministic. One user on blocking a folder: "a hook that exits with an error when Claude tries to write there will stop it reliably. Much cleaner than hoping your instructions hold."

Set up Claude Code hooks for formatting, tests and protected files — guide thumbnail
Step 2 of 6 · Coding

Auto-format after every edit

In .claude/settings.json, add a PostToolUse hook with matcher Edit|Write that runs Prettier on the edited file; the docs' command is jq -r '.tool_input.file_path' | xargs npx prettier --write. One user's reason: "Claude's style drifts in long sessions."

Step 3 of 6 · Coding

Run tests after edits so Claude sees failures

Add a fast test command as another post-edit hook. "Claude makes a change, tests run automatically, Claude sees the output and adjusts. It closes the feedback loop."

Step 4 of 6 · Coding

Block protected files with a PreToolUse hook

Add a script in .claude/hooks/ that reads the file path from stdin and exits with code 2 for patterns such as .env, package-lock.json or .git/, and register it as a PreToolUse hook on Edit|Write. Exit 2 blocks the action and sends your message back to Claude. "Only pre tool use can actually stop Claude."

Why this works

A blocked edit is explained to Claude so it can adjust.

Step 5 of 6 · Coding

Get notified when a long task finishes

Add a Notification hook (or one on Stop) that fires a desktop notification. One user includes the exit status "so I know immediately if it finished clean or hit an error."

Step 6 of 6 · Coding

Check with /hooks and commit the project settings

Run /hooks to confirm each hook is listed under the right event. .claude/settings.json can be committed so the team shares it; .claude/settings.local.json stays personal.

End of guide · Reviewed Oct 26, 2026

Pro tips2
  • You can ask Claude to write the hook for you, e.g. "Write a hook that runs eslint after every file edit."
  • Edit|Write hooks miss files changed through Bash; the docs suggest a Stop hook that scans the tree if that matters.
Common mistakes3
  • Putting a must-always rule in CLAUDE.md instead of a hook.
  • Running a slow full test suite on every edit.
  • Using a catch-all matcher on a permission hook, which approves everything.
FAQ2
Where do hooks live?
~/.claude/settings.json for every project, .claude/settings.json for one project.
What does exit code 2 do?
It blocks the action and passes your stderr message to Claude.