|$ curl https://forge-ai.dev/api/markdown?path=docs/ai/agent-hooks
$cat docs/agent-hooks.md
updated November 2026·30 min read·published

Agent Hooks

◆Hooks◆Lifecycle◆Guardrails◆Agents◆Advanced🎯Free Tools
What are Agent Hooks?

Agent hooks are shell commands that run automatically at specific lifecycle events during an AI coding agent session. Unlike skills (which provide advisory guidance to the model) or MCP servers (which provide tools), hooks are deterministic — they run your code, not the model, and they execute with the full power of your shell.

Hooks are the enforcement layer of the agent stack. A skill might suggest that the agent run tests after making changes. A hook guarantees it. A CLAUDE.md file might ask the agent not to modify certain files. A hook blocks it with exit code 2.

✕

danger

Hooks are the only agent extension mechanism that can unconditionally block operations. Skills suggest, MCP provides tools, subagents delegate — but only hooks can prevent an action from happening. This makes them critical for security and safety.
Hook Lifecycle Events

Hooks fire at specific points during the agent session lifecycle. Each event provides different context and supports different use cases.

EventWhen It FiresCan Block?Common Use Cases
PreToolUseBefore any tool call executes✅ Yes (exit code 2)Block dangerous commands, validate file paths, check permissions
PostToolUseAfter any tool call completes❌ NoAuto-format code, run linters, log tool usage
SessionStartWhen a new agent session begins❌ NoLoad project context, check environment, set up state
SessionEndWhen the agent session ends❌ NoCleanup, generate summary reports, commit changes
UserPromptSubmitWhen the user submits a message❌ NoLog user requests, inject context, validate input
NotificationWhen the agent sends a notification❌ NoCustom alerting, external integrations, status updates
Hooks vs Skills vs Rules

These three mechanisms control agent behavior in fundamentally different ways. Understanding the difference is critical for building reliable agent systems.

PropertySkillsRules (CLAUDE.md)Hooks
ExecutionModel reads and followsModel reads and followsShell command runs (no model)
Deterministic❌ No — model may ignore❌ No — model may ignore✅ Yes — always runs
Can block❌ No❌ No✅ Yes (exit code 2)
Context costUses context window tokensUses context window tokensZero context cost
Best forWorkflows, conventions, patternsProject context, coding standardsValidation, formatting, security gates
ℹ

info

The mnemonic: Skills teach, Rules remind, Hooks enforce. Use skills for workflows the agent should follow, rules for context the agent should know, and hooks for things that must happen regardless of what the model decides.
Configuring Hooks

Hooks are configured in your project .claude/settings.json file. Each hook specifies a matcher (which tools trigger it) and a command to run.

.claude/settings.json
JSON
1{
2 "hooks": {
3 "PreToolUse": [
4 {
5 "matcher": "Write|Edit",
6 "hooks": [
7 {
8 "type": "command",
9 "command": "python3 ~/.claude/validators/validate_file.py"
10 }
11 ]
12 },
13 {
14 "matcher": "Bash",
15 "hooks": [
16 {
17 "type": "command",
18 "command": "python3 ~/.claude/validators/block_dangerous.py"
19 }
20 ]
21 }
22 ],
23 "PostToolUse": [
24 {
25 "matcher": "Write|Edit",
26 "hooks": [
27 {
28 "type": "command",
29 "command": "npx prettier --write \"$CLAUDE_FILE_PATHS\""
30 }
31 ]
32 }
33 ],
34 "SessionStart": [
35 {
36 "hooks": [
37 {
38 "type": "command",
39 "command": "echo \"Session started at $(date)\" >> .claude/session.log"
40 }
41 ]
42 }
43 ]
44 }
45}
📝

note

The matcher field uses regex to match tool names. Write|Edit matches both the Write tool and the Edit tool. Use .* to match all tools. Environment variables like $CLAUDE_FILE_PATHS are available to your hook commands.
Common Hook Patterns

Pattern 1: Auto-Format on Save

Run Prettier (or Black, rustfmt, gofmt) after every file write or edit. This ensures the codebase stays formatted regardless of what the agent generates.

auto-format.json
JSON
1{
2 "PostToolUse": [{
3 "matcher": "Write|Edit",
4 "hooks": [{
5 "type": "command",
6 "command": "npx prettier --write --log-level error \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true"
7 }]
8 }]
9}

Pattern 2: Block Secrets in Code

Scan every file write for hardcoded secrets (API keys, passwords, tokens) and block the write if any are found.

block_secrets.py
Python
1#!/usr/bin/env python3
2"""Block writes that contain hardcoded secrets."""
3import re
4import sys
5import json
6import os
7
8SECRET_PATTERNS = [
9 r"sk-[a-zA-Z0-9]{32,}", # OpenAI API key
10 r"sk-ant-[a-zA-Z0-9-]{32,}", # Anthropic API key
11 r"ghp_[a-zA-Z0-9]{36}", # GitHub PAT
12 r"AKIA[0-9A-Z]{16}", # AWS Access Key
13 r"-----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY-----",
14]
15
16def check_file(filepath: str) -> list[str]:
17 try:
18 with open(filepath) as f:
19 content = f.read()
20 return [p for p in SECRET_PATTERNS if re.search(p, content)]
21 except Exception:
22 return []
23
24# Read file paths from environment
25files = os.environ.get("CLAUDE_FILE_PATHS", "").split(":")
26violations = []
27
28for f in files:
29 if f.strip():
30 found = check_file(f.strip())
31 if found:
32 violations.append(f"{f}: {', '.join(found)}")
33
34if violations:
35 print(json.dumps({
36 "decision": "block",
37 "reason": f"Hardcoded secrets detected: {'; '.join(violations)}"
38 }))
39 sys.exit(2) # Exit code 2 = block the operation
40else:
41 sys.exit(0) # Exit code 0 = allow

Pattern 3: Block Dangerous Commands

Prevent the agent from running destructive shell commands like rm -rf, force pushes, or database drops.

block_dangerous.py
Python
1#!/usr/bin/env python3
2"""Block dangerous shell commands."""
3import json
4import sys
5import os
6
7DANGEROUS_PATTERNS = [
8 "rm -rf /",
9 "rm -rf ~",
10 "rm -rf .",
11 "git push --force",
12 "git push -f",
13 "DROP TABLE",
14 "DROP DATABASE",
15 "TRUNCATE",
16 "> /dev/sda",
17 "mkfs.",
18 "dd if=",
19]
20
21tool_input = json.loads(os.environ.get("CLAUDE_TOOL_INPUT", "{}"))
22command = tool_input.get("command", "")
23
24for pattern in DANGEROUS_PATTERNS:
25 if pattern.lower() in command.lower():
26 print(json.dumps({
27 "decision": "block",
28 "reason": f"Dangerous command blocked: '{pattern}' detected in: {command}"
29 }))
30 sys.exit(2)
31
32sys.exit(0)

Pattern 4: Run Tests After Code Changes

Automatically run the test suite after the agent writes or edits code files. This catches regressions immediately.

run-tests.json
JSON
1{
2 "PostToolUse": [{
3 "matcher": "Write|Edit",
4 "hooks": [{
5 "type": "command",
6 "command": "if [[ \"$CLAUDE_FILE_PATHS\" == *.ts || \"$CLAUDE_FILE_PATHS\" == *.tsx ]]; then npx jest --passWithNoTests --silent 2>&1 | tail -5; fi"
7 }]
8 }]
9}
Blocking vs Non-Blocking Hooks

Only PreToolUse hooks can block operations. The exit code determines the outcome:

Exit CodeBehaviorUse Case
0Allow the operation to proceedValidation passed, everything is fine
1Allow with a warning message to the modelNon-critical issue — agent sees the warning and can adjust
2Block the operation entirelySecurity violation, dangerous operation, policy breach
⚠

warning

Be careful with blocking hooks. If your hook has a bug and blocks everything (e.g., always exits with code 2), the agent becomes unusable. Always test hooks thoroughly and include a bypass mechanism for emergencies.
Hook Security

Hooks are your primary defense against agent misuse — both accidental and adversarial. A well-designed hook system provides defense in depth.

◆Always validate file paths — prevent writes outside the project directory
◆Scan for secrets before any write — API keys, passwords, tokens should never enter source code
◆Block destructive commands — rm -rf, force pushes, database drops
◆Rate-limit expensive operations — prevent the agent from running 100 builds in a loop
◆Log all hook executions — you need an audit trail for debugging and compliance
◆Keep hooks fast — a 10-second hook on every file write makes the agent unusable
◆Use exit code 1 for warnings, exit code 2 only for things that must be blocked
◆Version control your hooks — they are as critical as your application code
$Blueprint — Engineering Documentation·Section ID: AI-HOOKS·Revision: 1.0

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.