Manages hooks for Claude Code and Codex CLI agents: add, list, remove, update, validate automation scripts for events like PreToolUse, PostToolUse, Notification.
npx claudepluginhub codealive-ai/agents-reflection-skillsThis skill uses the workspace's default tool permissions.
Manage hooks and automation through natural language commands.
Manages hooks and automation for coding agents like Claude Code, Codex CLI, OpenCode. Add, list, remove, update, or validate hooks for 28 events including SessionStart, PreToolUse, and FileChanged.
Configures Claude Code hooks for lifecycle events like PreToolUse, SessionStart, and automation use cases such as formatting enforcement and permission control.
Author Claude Code hooks for events like PreToolUse and PostToolUse using command, prompt, or agent types to automate workflows and validate operations.
Share bugs, ideas, or general feedback.
Manage hooks and automation through natural language commands.
IMPORTANT: After adding, modifying, or removing hooks, always inform the user that they need to restart the agent for changes to take effect. Hooks are loaded at startup.
Hook Events: PreToolUse, PostToolUse, PermissionRequest, UserPromptSubmit, Notification, Stop, SubagentStop, PreCompact, SessionStart, SessionEnd
Settings Files:
~/.claude/settings.json.claude/settings.json.claude/settings.local.jsonParse what the user wants:
Always run validation before saving:
python3 "$SKILL_PATH/scripts/validate_hooks.py" ~/.claude/settings.json
cat ~/.claude/settings.json 2>/dev/null || echo '{}'
Use Edit tool for modifications, Write tool for new files.
| User Says | Event | Matcher | Notes |
|---|---|---|---|
| "log all bash commands" | PreToolUse | Bash | Logging to file |
| "format files after edit" | PostToolUse | Edit|Write | Run formatter |
| "block .env file changes" | PreToolUse | Edit|Write | Exit code 2 blocks |
| "notify me when done" | Notification | "" | Desktop notification |
| "run tests after code changes" | PostToolUse | Edit|Write | Filter by extension |
| "ask before dangerous commands" | PreToolUse | Bash | Return permissionDecision: "ask" |
{
"hooks": {
"EVENT_NAME": [
{
"matcher": "TOOL_PATTERN",
"hooks": [
{
"type": "command",
"command": "SHELL_COMMAND",
"timeout": 60
}
]
}
]
}
}
PREFER SCRIPT FILES for complex hooks. Inline commands with nested quotes, osascript, or multi-step logic often break due to JSON escaping issues.
| Complexity | Approach | Example |
|---|---|---|
| Simple | Inline | jq -r '.tool_input.command' >> log.txt |
| Medium | Inline | Single grep/jq pipe with basic conditionals |
| Complex | Script file | Dialogs, multiple conditions, osascript, error handling |
Script location: ~/.claude/hooks/ (create if needed)
Script template (~/.claude/hooks/my-hook.sh):
#!/bin/bash
set -euo pipefail
# Read JSON input from stdin
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
# Your logic here
if echo "$cmd" | grep -q 'pattern'; then
# Option 1: Block with exit code
exit 2
# Option 2 (preferred for PreToolUse): JSON decision control
# jq -n '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"ask",permissionDecisionReason:"Reason"}}'
fi
exit 0 # Allow
Hook config using script:
{
"type": "command",
"command": "~/.claude/hooks/my-hook.sh"
}
Always:
~/.claude/hooks/chmod +x ~/.claude/hooks/my-hook.shecho '{"tool_input":{"command":"test"}}' | ~/.claude/hooks/my-hook.shLogging (PreToolUse):
{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}]
}
File Protection (PreToolUse, exit 2 to block):
{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | grep -qE '(\\.env|secrets)' && exit 2 || exit 0"
}]
}
Auto-format (PostToolUse):
{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "file=$(jq -r '.tool_input.file_path'); [[ $file == *.ts ]] && npx prettier --write \"$file\" || true"
}]
}
Desktop Notification (Notification):
{
"matcher": "",
"hooks": [{
"type": "command",
"command": "osascript -e 'display notification \"Claude needs attention\" with title \"Claude Code\"'"
}]
}
Codex CLI has a limited hook system. For blocking/allowing commands, use Starlark rules instead of hooks:
# In .codex/rules/safety.rules
prefix_rule(
pattern = ["rm", ["-rf", "-r"]],
decision = "forbidden",
justification = "Use git clean -fd instead.",
)
For notifications: notify = ["notify-send", "Codex"] in config.toml.
See references/codex-hooks.md for full Codex hooks reference and migration patterns.
See references/claude-event-schemas.md for complete JSON input schemas for each event type (Claude Code).
Run validation script to check hooks:
python3 "$SKILL_PATH/scripts/validate_hooks.py" <settings-file>
Validates:
PreToolUse hooks can return JSON on stdout to control tool execution. This is preferred over bare exit codes for PreToolUse because it supports three outcomes and richer control.
permissionDecision | Behavior |
|---|---|
"allow" | Bypass permissions, proceed silently |
"deny" | Block the tool call, reason shown to Claude |
"ask" | Prompt the user to confirm in the terminal |
Additional JSON fields:
permissionDecisionReason — shown to user for "allow"/"ask", shown to Claude for "deny"updatedInput — modify tool input before executionadditionalContext — inject context for Claude before the tool executesAsk user before dangerous command (PreToolUse):
#!/bin/bash
set -euo pipefail
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')
if echo "$cmd" | grep -qE 'supabase\s+db\s+reset'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "This will destroy and recreate the local database."
}
}'
else
exit 0
fi
Deny with reason (PreToolUse):
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
See references/claude-event-schemas.md for the full output schema.
| Code | Meaning | Use Case |
|---|---|---|
| 0 | Success/Allow | Continue execution |
| 2 | Block | Simple blocking (prefer JSON decision control for PreToolUse) |
| Other | Error | Log to stderr, shown in verbose mode |
Before adding hooks, verify:
* when possible)Hook not triggering: Check matcher case-sensitivity, ensure event name is exact.
Command failing: Test command standalone with sample JSON input.
Permission denied: Ensure script is executable (chmod +x).
Timeout: Increase timeout field or optimize command.