C.W.K.
Stream
Lesson 08 of 13 · published

Hooks — Deterministic Lifecycle Control

~22 min · hooks, automation, pre-tool-use, post-tool-use

Level 0🌱 Novice
0 XP0/70 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Where the AI's promises meet your guarantees

Hooks are user-defined commands, HTTP endpoints, or LLM prompts that fire at lifecycle events: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PermissionRequest, Stop, plus a dozen more. They give you deterministic control where the model's compliance is statistical.

The two events that change every team's life: PreToolUse can block a tool call (exit code 2 + stderr message → tool cancelled, model sees the reason). PostToolUse runs after success — perfect for auto-format, type-check, run-affected-tests.

Hook types: command shells out (JSON on stdin, exit code controls flow), http POSTs to a URL (Slack notifications, audit logs), prompt asks Claude itself for a decision (great for permission gates that need judgment).

Code

Auto-format on every Edit / Write·json
// .claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "description": "Format and type-check TypeScript on save",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'F=$FILEPATH; if [[ $F == *.ts || $F == *.tsx ]]; then npx prettier --write \"$F\" && npx tsc --noEmit; fi'"
          }
        ]
      }
    ]
  }
}
Block writes to protected paths·bash
#!/bin/bash
# .claude/hooks/protect-files.sh
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED=(".env" ".env.production" "secrets/" ".pem" "id_rsa")

for p in "${PROTECTED[@]}"; do
  if [[ "$FILE" == *"$p"* ]]; then
    echo "Blocked: $FILE matches protected pattern '$p'" >&2
    exit 2
  fi
done
exit 0

# Wired in settings.json:
# "PreToolUse": [{"matcher":"Edit|Write","hooks":[{"type":"command",
#  "command":"bash .claude/hooks/protect-files.sh"}]}]

External links

Exercise

Add a PostToolUse hook that runs your project's formatter on every Edit / Write. Test it by asking Claude to make a deliberately ugly edit and watch the file get auto-cleaned. Bonus: add a PreToolUse hook that blocks writes to .env.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.