A hook is a shell command the harness runs automatically when something happens in a session. You do not call it - Claude Code fires it for you on a lifecycle event. Hooks are how you bolt your own automation onto the agent: format a file the moment it is edited, block a risky command before it runs, or log every prompt.
Each hook is tied to an event. The common ones:
| Event | Fires when |
|---|---|
PreToolUse | Before a tool runs - can block it |
PostToolUse | After a tool finishes |
UserPromptSubmit | When you submit a prompt |
Stop | When Claude finishes responding |
SessionStart | When a session begins |
There are more, but these cover most needs.
Hooks live in settings.json under a hooks key. Each event maps to a list
of matchers, and each matcher carries the command to run. A PostToolUse
hook that runs after any Edit looks like this:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{ "type": "command", "command": "prettier --write $CLAUDE_FILE_PATHS" }
]
}
]
}
}
Read it inside out: the event is PostToolUse, the matcher picks which tool
triggers it (here Edit), and each entry under the inner hooks array is a
command with "type": "command" and the shell command to run.
PostToolUse).PreToolUse).UserPromptSubmit).Because a hook is just a shell command, it can do anything your shell can.
Next, add a PostToolUse hook of your own to a project's settings.json.
Your lab setup
This VM comes with Claude Code preinstalled and signed in - just run claude to start.