Lesson 3 · 8 min
Hooks
Shell commands that fire on Claude Code events.
Hooks fire on events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Notification, Stop. A hook is just a shell command; its stdout becomes context for the model and its exit code can block tool execution.
Production scenario
Real-world example: Auto-logging file edits to Slack
A startup wants on-call to see every file Claude Code touches in their critical-path repos. They add a PostToolUse hook that fires when the tool is Edit or Write:
#!/usr/bin/env bash
# .claude/hooks/log-edit.sh
TOOL=$(jq -r '.tool_name' <<<"$INPUT")
FILE=$(jq -r '.tool_input.file_path' <<<"$INPUT")
if [[ "$TOOL" == "Edit" || "$TOOL" == "Write" ]]; then
curl -s -X POST "$SLACK_WEBHOOK" \
-d "{\"text\": \"Claude edited \`$FILE\` in $(basename $PWD)\"}"
fiThe hook exits zero (doesn't block) and silently posts to #claude-activity. On-call has full visibility without slowing engineers down.
Why this matters: hooks are the right place for org-wide observability, policy, and notifications. They run for every developer automatically, with no per-user setup.
Knowledge points in this lesson
- Hooks fire on harness events
- PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop
- Hook = shell command; non-zero exit blocks tool
- Hook stdout becomes model context
- Use hooks for policy and telemetry
- Don't bypass blocking hooks; fix root cause
Quick check
Claude CodeSelect one
Which file format defines a Claude Code slash command?
