Run a shell command on lifecycle events with hooks

mcp, agents & hooks

// what it does

Hooks run your own shell commands at fixed lifecycle events — PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop, and more — configured under the hooks key in settings.json. Each event holds matchers (a tool-name regex like Write|Edit) and command entries. A PostToolUse hook that runs a formatter after every Write or Edit is the classic example; hooks receive event JSON on stdin.

// shell

$ { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "npm run lint --silent" } ] } ] } }
$ /hooks

// gotcha

Exit code 2 blocks the action and feeds stderr back to Claude; any other non-zero code is a non-blocking error. Unlike CLAUDE.md, hooks execute regardless of what Claude decides, so use one for anything that must always happen. Reference scripts with ${CLAUDE_PROJECT_DIR} so paths resolve from the project root.

// resources