Aller au contenu principal

Hooks (Claude Code 2.1+)

The project includes automatic hooks in .claude/settings.json:

Available Hook Events

EventTypeDescription
SessionStartcommandTriggered at session startup (matchers: startup, resume, clear, compact)
UserPromptSubmitcommandWhen the user submits a prompt (validation, additional context)
PreToolUsecommand/promptBefore tool execution (matcher: Edit|Write, Bash)
PermissionRequestcommand/promptWhen a permission dialog is shown
PostToolUsecommandAfter successful tool execution
PostToolUseFailurecommandAfter a tool failure
SubagentStartcommandSub-agent startup
SubagentStopcommand/promptEnd of sub-agent execution
Stopcommand/promptWhen Claude finishes responding
StopFailurecommandWhen a turn ends on an API error (rate limit, auth failure) — CLI 2.1.78+
SetupcommandProject initialization (init) and maintenance (maintenance)
NotificationcommandNotifications (permission_prompt, idle_prompt, auth_success, elicitation_dialog)
PreCompactcommandBefore context compaction (matchers: manual, auto)
PostCompactcommandAfter context compaction
SessionEndcommandEnd of session
TeammateIdlecommandWhen a teammate agent becomes idle (Agent Teams)
TaskCreatedcommandWhen a task is created via TaskCreate (CLI 2.1.84+)
TaskCompletedcommandWhen a task is marked completed
WorktreeCreatehttpHook type: "http" invoked on worktree creation, must return hookSpecificOutput.worktreePath (CLI 2.1.84+)
InstructionsLoadedcommandWhen CLAUDE.md and rules are loaded
ElicitationcommandWhen an MCP server requests structured input
ElicitationResultcommandWhen the user responds to an MCP Elicitation
PermissionDeniedcommandAfter a permission denial by the auto mode classifier. Return {retry: true} to retry
CwdChangedcommandWhen the working directory changes
FileChangedcommandWhen a file is modified

Matcher syntax — exact match on hyphenated identifiers (CLI 2.1.195, June 2026)

A matcher with a hyphenated identifier (e.g. an agent code-reviewer, a tool mcp__brave-search) now exact-matches — it previously substring-matched, which could fire unintentionally. To match all tools from a hyphenated MCP server, use an explicit pattern: mcp__brave-search__.*. This repo's own matchers (Edit|Write|Bash|MultiEdit|NotebookEdit + event names) contain no hyphens, so they are unaffected — but a downstream project matching hyphenated agent/MCP names should use the .* form.

Hook Types

TypeDescription
commandExecutes a bash script (deterministic, fast)
promptEvaluated via a Haiku LLM (contextual, intelligent) - for Stop, SubagentStop, PreToolUse
httpSends a JSON POST to a URL (external webhook) - CLI 2.1.70+

Hook Properties

PropertyDescription
asynctrue to run in the background without blocking (CLI 2.1.70+)
onFailure"block" to block, "ignore" to continue
timeoutTimeout in milliseconds
ifActivation condition using permission rules syntax (CLI 2.1.90+)
additionalContextAdditional context string injected into the PreToolUse hook (CLI 2.1.110+)

defer permission (PreToolUse)

PreToolUse hooks can return "defer" as a permission decision. The headless session pauses at the tool call and can resume with -p --resume to re-evaluate the hook. Useful for CI/CD workflows requiring human approval.

MCP transient retry (CLI 2.1.128+)

When a hook interacts with an MCP server, transient connection failures are auto-retried by the runtime. Hook authors do not need to wrap MCP calls in custom retry logic for transient cases (the typical "server momentarily unavailable" pattern). Permanent failures are not retried.

terminalSequence field (CLI 2.1.141+)

Hook JSON output gained a terminalSequence field that emits raw terminal escape sequences — desktop notifications, window-title updates, and the bell — without requiring a controlling terminal. Useful for background or daemonized hooks that want to surface status outside the Claude Code TUI. See the upstream changelog for the exact escape codes accepted.

The exact retry bound and the failure-classification heuristics are tuned upstream and may evolve between releases — refer to the Claude Code changelog for the canonical behavior at the version you target.

Configured Hooks

HookTriggerAction
Session infoSessionStart (startup)Displays project information at startup
Check node_modulesSessionStart (startup)Checks that node_modules exists if package.json is present
Main protectionPreToolUse (Edit/Write)Keeps edits off main/master by auto-creating a feature/auto-<timestamp> branch first; blocks the edit (exit 2) if the branch can't be created, instead of letting it land on main. Disable with ALLOW_MAIN_EDIT=1 (scripts/hooks/main-branch-guard.sh)
Secrets detectionPreToolUse (Write/Edit/MultiEdit)Built-in zero-dependency scan blocks hardcoded provider secrets (AWS/Stripe/GitHub/Slack/Google/PEM) before writing; also runs gitleaks if installed. Placeholders ignored. Disable with SKIP_SECRET_SCAN=1 (scripts/hooks/secret-scan.sh)
Destructive migrationPreToolUse (Write/Edit/MultiEdit)Confirm+backup reminder before destructive DDL (DROP/TRUNCATE) in a migration file — closes the gap the Bash-only destructive guard misses. Disable with SKIP_DESTRUCTIVE_CHECK=1 (scripts/hooks/destructive-migration.sh)
Pre-commit testsPreToolUse (Bash git commit)Runs the stack's test suite (npm/pytest/go) before a commit and blocks (exit 2) on failure; detects/repairs Husky if needed. Disable with SKIP_PRE_COMMIT_TESTS=1 (scripts/hooks/pre-commit-tests.sh)
Local pre-push CIPreToolUse (Bash git push)Lint + type-check + tests before push. Disable with SKIP_PRE_PUSH_CI=1
Pre-deploy buildPreToolUse (Bash deploy)Runs the production build (npm run build / go build) before a deploy command and blocks (exit 2) on failure — including a broken Go build. Disable with SKIP_PRE_DEPLOY_BUILD=1 (scripts/hooks/pre-deploy-build.sh)
Destructive ops guardPreToolUse (Bash)Blocks destructive DB/filesystem ops — DROP/TRUNCATE, an unscoped DELETE FROM (no WHERE), wiping an uploads/media/storage tree, prisma migrate reset. Disable with SKIP_DESTRUCTIVE_CHECK=1 (scripts/hooks/destructive-ops.sh)
Command validatorPreToolUse (Bash)Validates commands against 9 risk categories (fork bombs, pipe-to-shell, disk destruction, privilege escalation, git --no-verify / commit -n gate-bypass, etc.). Disable all with SKIP_COMMAND_VALIDATOR=1, or just the no-verify block with SKIP_NO_VERIFY_CHECK=1
Config protectionPreToolUse (Edit/Write/MultiEdit)Blocks modifying an existing linter/formatter config (.eslintrc*, eslint.config.*, .prettierrc*, biome.json, ruff.toml, .markdownlint.*) so a failing check is fixed in the code, not silenced. Creating a config is allowed; pyproject.toml/tsconfig.json and test fixtures are exempt. Disable with SKIP_CONFIG_PROTECTION=1
Bash-write guardPreToolUse (Bash)The Bash-side complement to the guards above: blocks a Bash write (>, >>, tee, sed -i) whose target is an existing lint/format config, an existing secrets file (.env, *.pem, *.key, credentials, …), or a tracked repo file while on main/master — closing the gap where a write routed through Bash escaped config-protection/secret-scan/main-branch-guard. New files, temp paths and /dev/* pass. Shares the config set via _sensitive-paths.sh. Disable with SKIP_BASH_WRITE_GUARD=1 (or ALLOW_MAIN_EDIT=1 for the on-main case)
Auto-format TS/JSPostToolUse (Edit/Write)Prettier on TS/JS files
Auto-format PythonPostToolUse (Edit/Write)Ruff/Black on .py files
Auto-format GoPostToolUse (Edit/Write)gofmt on .go files
Auto-format RustPostToolUse (Edit/Write)rustfmt on .rs files
Auto-format DartPostToolUse (Edit/Write)dart format on .dart files
Auto-format LuaPostToolUse (Edit/Write)stylua on .lua files
Inline edit errors (output rewriter)PostToolUse (Edit/Write)Runs tsc + eslint on edited TS/JS files and appends errors to the tool result envelope (CLI 2.1.121+). Disable: SKIP_INLINE_EDIT_ERRORS=1. Replaces the former inline tsc + eslint blocks.
Auto-installPostToolUse (Edit package.json)npm/yarn/pnpm/bun install
Auto-sync PythonPostToolUse (Edit pyproject.toml)uv sync or pip install
Auto pub getPostToolUse (Edit pubspec.yaml)flutter/dart pub get
Auto go mod tidyPostToolUse (Edit go.mod)go mod tidy
Auto cargo checkPostToolUse (Edit Cargo.toml)cargo check
Coverage checkPostToolUse (Edit test files)Checks test coverage
Substance gatePostToolUse (Edit/Write/MultiEdit)Advisory: runs scripts/substance-check.sh on the edited test/source file and surfaces hollow tests (no-assertion / always-true / skipped / empty) and implementation stubs (not implemented/NotImplementedError/panic("TODO")) that coverage % misses. Never blocks (exit 0 always). Disable: SKIP_SUBSTANCE_CHECK=1
Setup initSetup (init)Installs dependencies on first run
Setup maintenanceSetup (maintenance)Periodic audit and updates
Notification permissionNotification (permission_prompt)Logs permission requests
Notification idleNotification (idle_prompt)Logs when Claude is waiting for the user
SubagentStopSubagentStopLogs the end of sub-agents
SessionEndSessionEndLogs end of session
PreCompactPreCompactLogs before context compaction
PostCompactPostCompactLogs after context compaction (async)
TeammateIdleTeammateIdleLogs when a teammate becomes idle (async)
TaskCompletedTaskCompletedLogs when a task is completed (async)
InstructionsLoadedInstructionsLoadedLogs instruction loading (async)
ElicitationElicitationLogs MCP Elicitation requests (async)
ElicitationResultElicitationResultLogs MCP Elicitation responses (async)
PermissionDeniedPermissionDeniedLogs permissions denied by auto mode (async, CLI 2.1.111+)
UserPromptSubmitUserPromptSubmitLogs user prompt submissions (async)
Prompt context injectionUserPromptSubmitInjects branch, modified files, LOC diff and /assistant-auto hint if no slash command (disable: SKIP_PROMPT_CONTEXT=1). Also injects a once-per-session vendor-precedence hint when a graduated vendor skill is installed (prefer it over the foundation pointer, vendor-precedence T3; pure-shell helper _vendor-precedence-hint.sh, disable: SKIP_VENDOR_PRECEDENCE=1)
PostToolUseFailurePostToolUseFailureLogs tool failures for debugging (async)
Check .envSessionStartChecks that .env is in .gitignore
Third-party hooks warningSessionStartWarns if custom hooks are detected
CLI version probeSessionStartProbes Claude Code version for the output rewriter (requires 2.1.121+). Writes /tmp/claude-rewriter-supported (1 or 0) consumed by post-edit and bash-output rewriter hooks

Git-native hooks (.husky/)

Distinct from the Claude Code hooks above (which live in .claude/settings.json): these are standard git hooks, wired via core.hooksPath=.husky. They run for every commit — by a human or an agent, in any tool — not only inside Claude Code. scripts/hooks/setup-deps.sh wires core.hooksPath on Setup (idempotent, and it repairs a stale absolute path left by a repo rename); for a manual clone, run git config core.hooksPath .husky once.

HookAction
pre-commitcounts self-healWhen a commit stages a counted artifact (.claude/{commands,agents,skills,rules}/** or tests/*.bats), runs scripts/sync-counts.sh: regenerates the derived count files and git adds them, so a stale count can never reach CI. No-op (and node-free) for any other commit. Blocks only if counts drifted and regeneration is unavailable. Disable with SKIP_COUNTS_SYNC=1.
pre-pushpreflightRuns the foundation's own CI gates locally before a push (scripts/preflight.sh --fast: shellcheck · validate-counts.sh · manifest-hooks-coverage), so failures surface locally instead of post-push. Mirrors ci.yml; scripts/preflight.sh --full adds the complete bats suite. Bypass once with SKIP_PREFLIGHT=1.

scripts/sync-counts.sh mirrors the CI "Counts gate": it regenerates and stages the same derived path set the CI diffs (counts.json, README.md, CLAUDE.md, docs/, website/docs/, the Docusaurus config). --check runs the read-only validate-counts.sh instead (no regeneration, no staging).

Output rewriter (CLI 2.1.121+)

Three coordinated hooks that exploit hookSpecificOutput.updatedToolOutput to tighten Claude's feedback loop on PostToolUse Bash and Edit/Write events.

HookEventRole
check-cli-version.shSessionStartProbes claude --version and writes /tmp/claude-rewriter-supported (1 if >= 2.1.121, 0 otherwise). On unsupported CLI, prints a one-line notice.
bash-output-filter.shPostToolUse (Bash)Trims allowlisted noisy command outputs (npm/pnpm/yarn/bun install/audit/test/build, pytest, go test/build, cargo build/test/check) to actionable lines. Outputs below 30 lines pass through unchanged.
post-edit-typecheck-and-lint.shPostToolUse (Edit\Write)

All three hooks bail out silently if the sentinel reports unsupported, if jq is absent, or if their respective opt-out env var is set. The Bash filter and inline-edit hook share the helpers in _hook-helpers.sh (sourced, not registered).

Migration path: existing projects must run claude-base update -f --all <project> to get the consolidated .claude/settings.json. If only --hook-scripts ran, post-edit-typecheck-and-lint.sh will detect the legacy state at runtime (old npx tsc --noEmit references in .claude/settings.json) and emit a one-line notice once per session.

Hook Environment Variables

VariableUsage
ALLOW_MAIN_EDIT=1Disable main branch protection
SKIP_PRE_COMMIT_TESTS=1Disable pre-commit tests
SKIP_COUNTS_SYNC=1Disable the git pre-commit counts self-heal (.husky/pre-commit)
SKIP_PREFLIGHT=1Skip the git pre-push foundation gates (.husky/pre-pushscripts/preflight.sh)
SKIP_COMMAND_VALIDATOR=1Disable ALL command security validation (every category)
SKIP_NO_VERIFY_CHECK=1Disable ONLY the git --no-verify/-n gate-bypass block (keeps the other 8 categories active)
SKIP_CONFIG_PROTECTION=1Disable the linter/formatter config-protection hook
SKIP_SECRET_SCAN=1Disable the built-in hardcoded-secret scan (scripts/hooks/secret-scan.sh)
SKIP_SUBSTANCE_CHECK=1Disable the substance gate (advisory hollow-test / stub detector)
SKIP_PRE_PUSH_CI=1Disable local pre-push CI check
SKIP_DESTRUCTIVE_CHECK=1Disable destructive operations protection
SKIP_PROMPT_CONTEXT=1Disable repo context injection on free-form prompts
SKIP_VENDOR_PRECEDENCE=1Disable the once-per-session installed-vendor precedence hint
SKIP_BASH_OUTPUT_FILTER=1Disable the Bash output filter (output rewriter)
SKIP_INLINE_EDIT_ERRORS=1Disable the inline edit errors hook (output rewriter)
BASH_OUTPUT_FILTER_VERBOSE=1Keep both filtered and original views in the rewritten output
BASH_OUTPUT_FILTER_THRESHOLD=<N>Override the noise threshold (default 30 lines) below which Bash outputs pass through unchanged
HOOK_REWRITER_SENTINEL=<path>Override the capability sentinel path (default /tmp/claude-rewriter-supported). Used by tests to isolate parallel runs under $BATS_TEST_TMPDIR
HOOK_REWRITER_METRIC_LOG=<path>Override the bash filter metric log path (default /tmp/claude-rewriter.log). Same testing rationale
HOOK_LEGACY_NOTICE_SENTINEL=<path>Override the legacy notice sentinel base path (default /tmp/claude-base-legacy-warned, suffixed with .PPID). Same testing rationale

Log Files

Logging hooks write to /tmp/ (append mode, cleared on restart):

FileContent
/tmp/claude-sessions.logStartup, end of session, compaction, tasks
/tmp/claude-agents.logSub-agent and teammate activity
/tmp/claude-notifications.logPermissions and user waits
/tmp/claude-mcp.logMCP Elicitation events
/tmp/claude-permissions.logPermissions denied by the auto mode classifier
/tmp/claude-prompts.logUser prompt submissions (timestamps)
/tmp/claude-failures.logTool failures with tool name
/tmp/claude-rewriter.logOutput rewriter activity (tool name, original / filtered line counts)