Tech Update / Adventures with Claude Code #11

Hooks – when “please always” isn't enough

Our CLAUDE.md says: “Please run Prettier after every change.” It usually works. Usually.

The problem: CLAUDE.md (part 4) is a request. Claude reads it, understands it and still forgets it now and then, especially in long sessions. For things that must always happen, there are hooks.

A hook is a shell command that Claude Code runs automatically at fixed points. The tool decides, not the model.

⏱️ The most important events

  • PreToolUse: before Claude writes a file or runs a command. Can block.
  • PostToolUse: right afterwards. Ideal for formatting and linting.
  • Stop: when Claude thinks it's done.
  • Notification: when Claude is waiting for you. Perfect for a desktop notification.

🧹 Example 1: format after every change

In .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

The hook receives the details of the tool call as JSON, and jq pulls out the file name. From now on every file is formatted, without anyone having to remember.

🛑 Example 2: hands off the .env

A PreToolUse hook checks the file name. If the script exits with code 2, the call is blocked and Claude gets the error message back as the reason:

#!/bin/bash
file=$(jq -r '.tool_input.file_path // empty')
if [[ "$file" == *".env"* ]]; then
  echo "Access to .env is blocked." >&2
  exit 2
fi
exit 0

A word of caution:

Hooks run with your permissions and without asking. So read other people's hooks as critically as you would their shell scripts. Also: a slow PostToolUse hook slows down every single change. Check only the changed file, not the whole project.

My rule of thumb:

  • Should Claude know it? CLAUDE.md.
  • Must it always happen? Hook.
  • Must it never happen? Permissions (part 7) plus a PreToolUse hook as a second seatbelt.

← Back to overview