From claude-initial-setup
Guide for configuring PreToolUse, PostToolUse, and Stop hooks in Claude Code. Use when the user asks about hooks, wants to run commands before/after tool calls, needs auto-formatting, auto-linting, validation gates, or mentions settings.json hook config.
npx claudepluginhub versoxbt/claude-initial-setup --plugin claude-initial-setupThis skill uses the workspace's default tool permissions.
Claude Code hooks are shell commands that execute automatically in response to tool events. They enable validation, formatting, and guardrails without manual intervention.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Claude Code hooks are shell commands that execute automatically in response to tool events. They enable validation, formatting, and guardrails without manual intervention.
PreToolUse --> Tool Executes --> PostToolUse
|
(session ends)
|
Stop
Hooks live in ~/.claude/settings.json under the hooks key:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"command": "echo 'About to write a file'",
"description": "Log before file writes"
}
],
"PostToolUse": [
{
"matcher": "Edit",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\"",
"description": "Auto-format after editing JS/TS files"
}
],
"Stop": [
{
"command": "echo 'Session ended'",
"description": "Log session end"
}
]
}
}
The matcher field filters which tool triggers the hook. It matches against tool names:
{
"matcher": "Edit",
"command": "..."
}
Common tool names to match:
Write — file creationEdit — file modificationBash — shell command executionRead — file readingGlob — file searchGrep — content searchUse pipe | for multiple matchers:
{
"matcher": "Write|Edit",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\""
}
Omit matcher entirely to match ALL tool calls (useful for Stop hooks).
Hooks receive context via environment variables:
| Variable | Description |
|---|---|
CLAUDE_FILE_PATH | The file path being operated on |
CLAUDE_TOOL_NAME | Name of the tool being called |
CLAUDE_SESSION_ID | Current session identifier |
A PreToolUse hook that exits non-zero blocks the tool from executing:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"command": "echo \"$CLAUDE_FILE_PATH\" | grep -qv '\\.md$' || (echo 'BLOCKED: Do not create markdown files' && exit 1)",
"description": "Block creation of .md files"
}
]
}
}
Run checks or formatting after tool execution without blocking:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "if echo \"$CLAUDE_FILE_PATH\" | grep -q '\\.ts$'; then npx tsc --noEmit \"$CLAUDE_FILE_PATH\" 2>&1 | head -20; fi",
"description": "Type-check TypeScript files after edit"
}
]
}
}
{
"hooks": {
"Stop": [
{
"command": "git diff --cached --name-only | xargs grep -l 'console.log' 2>/dev/null && echo 'WARNING: console.log found in staged files'",
"description": "Audit staged files for console.log before session ends"
}
]
}
}
$CLAUDE_FILE_PATH instead of hardcoding file paths. Hooks should be project-agnostic.| Hook Type | Timing | Can Block? | Use Case |
|---|---|---|---|
| PreToolUse | Before tool | Yes (exit 1) | Validation, gates, warnings |
| PostToolUse | After tool | No | Formatting, type-checking, linting |
| Stop | Session end | No | Final audits, cleanup |
Config location: ~/.claude/settings.json > hooks
Matcher syntax: Tool name string, pipe-separated for multiple
Blocking: Only PreToolUse can block (non-zero exit code)