
Enhance Hooks
- 60 installs
- 931 repo stars
- Updated July 26, 2026
- avifenesh/agentsys
enhance-hooks is a Claude skill that analyzes Claude Code hook definitions and scripts for safety, correct frontmatter, and timeouts.
About
This skill analyzes Claude Code hook definitions and scripts for safety, correctness, and best practices. It classifies the hook type and event, checks frontmatter, matchers, timeouts, and exit codes against a bundled hook knowledge reference, and can apply auto-fixes with a --fix flag. Developers use it to review hooks before they run untrusted or unsafe automation in a session.
- Documents the full 11-event hook lifecycle and matcher requirements
- Checks hook safety, timeouts, exit codes, and frontmatter correctness
- Auto-fix mode plus certainty filtering on findings
Enhance Hooks by the numbers
- 60 all-time installs (skills.sh)
- Ranked #6,388 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
enhance-hooks capabilities & compatibility
- Capabilities
- hook review · agent config review · safety check
- Use cases
- code review · security audit
What enhance-hooks says it does
Analyze hook definitions and scripts for safety, correctness, and best practices.
npx skills add https://github.com/avifenesh/agentsys --skill enhance-hooksAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 60 |
|---|---|
| repo stars | ★ 931 |
| Last updated | July 26, 2026 |
| Repository | avifenesh/agentsys ↗ |
What it does
Analyze Claude Code hook definitions and scripts for safety, correct frontmatter, and timeouts, with optional auto-fixes.
Who is it for?
Reviewing Claude Code hooks for safety, timeouts, and correct configuration
Skip if: Reviewing non-hook agent files or application code
When should I use this skill?
The user wants to review hooks for safety, timeouts, or correct frontmatter
What you get
Hook definitions and scripts graded for safety and correctness, with optional auto-fixes.
- hook safety report
- auto-fixed hook config
By the numbers
- 11-event hook lifecycle
- 3 hook exit-code behaviors
Files
enhance-hooks
Analyze hook definitions and scripts for safety, correctness, and best practices.
Parse Arguments
const args = '$ARGUMENTS'.split(' ').filter(Boolean);
const targetPath = args.find(a => !a.startsWith('--')) || '.';
const fix = args.includes('--fix');Workflow
1. Discover - Find hook files (.md, .sh, .json) 2. Classify - Identify hook type and event 3. Parse - Extract frontmatter and script content 4. Check - Run all pattern checks against knowledge below 5. Filter - Apply certainty filtering 6. Report - Generate markdown output 7. Fix - Apply auto-fixes if --fix flag present
---
Hook Knowledge Reference
What Are Hooks
Hooks are automated actions triggered at specific points in a Claude Code session. They enable validation, monitoring, and control of Claude's actions through bash commands or LLM-based evaluation.
Hook Lifecycle (Complete Reference)
Hooks fire in this sequence:
| Order | Event | Description | Matcher Required |
|---|---|---|---|
| 1 | SessionStart | Session begins or resumes | No |
| 2 | UserPromptSubmit | User submits a prompt | No |
| 3 | PreToolUse | Before tool execution (can modify/block) | Yes |
| 4 | PermissionRequest | When permission dialog appears | Yes |
| 5 | PostToolUse | After tool succeeds | Yes |
| 6 | SubagentStart | When spawning a subagent | No |
| 7 | SubagentStop | When subagent finishes | No |
| 8 | Stop | Claude finishes responding | No |
| 9 | PreCompact | Before context compaction | No |
| 10 | SessionEnd | Session terminates | No |
| 11 | Notification | Claude Code sends notifications | No |
Hook Types
Command Hooks (type: "command"):
- Execute bash commands with full stdin/stdout control
- Available for all events
Prompt Hooks (type: "prompt"):
- Use LLM evaluation for intelligent, context-aware decisions
- Only supported for `Stop` and `SubagentStop` events
Configuration Locations
| File | Location | Scope | Committed |
|---|---|---|---|
| User settings | ~/.claude/settings.json | All projects | No |
| Project settings | .claude/settings.json | Current project | Yes |
| Local settings | .claude/settings.local.json | Current project | No |
Configuration Structure
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/validate-bash.sh",
"timeout": 30
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/format-code.sh"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Check if all requested tasks are complete.",
"timeout": 30
}
]
}
]
}
}Matcher Syntax
| Pattern | Description |
|---|---|
Write | Match exact tool name |
| `Edit\ | Write` |
Notebook.* | Regex pattern matching |
* or "" | Match all tools |
| (omitted) | Required for Stop, SubagentStop, UserPromptSubmit |
Input Schema (JSON via stdin)
All hooks receive this JSON structure:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript",
"cwd": "/project/root",
"permission_mode": "default",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test",
"description": "Run test suite"
}
}Exit Codes
| Exit Code | Behavior |
|---|---|
| 0 | Success - stdout shown to user or added as context |
| 2 | Blocking error - stderr shown, action blocked |
| Other | Non-blocking error - stderr shown in verbose mode |
Output Schemas
PreToolUse Decision Control:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow|deny|ask",
"permissionDecisionReason": "Reason for decision",
"updatedInput": {
"command": "modified command"
},
"additionalContext": "Context for Claude"
}
}Stop/SubagentStop Control:
{
"decision": "block",
"reason": "Tasks incomplete: missing test coverage"
}Environment Variables
| Variable | Description | Available In |
|---|---|---|
CLAUDE_PROJECT_DIR | Absolute path to project root | All hooks |
CLAUDE_CODE_REMOTE | "true" if remote session | All hooks |
CLAUDE_ENV_FILE | Path to persist env vars | SessionStart only |
CLAUDE_FILE_PATHS | Space-separated file paths | PostToolUse (Write/Edit) |
Practical Hook Examples
Security Firewall (PreToolUse):
#!/usr/bin/env bash
set -euo pipefail
cmd=$(jq -r '.tool_input.command // ""')
# Block dangerous patterns
if echo "$cmd" | grep -qE 'rm -rf|git reset --hard|curl.*\|.*sh'; then
echo '{"decision": "block", "reason": "Dangerous command blocked"}' >&2
exit 2
fi
exit 0Auto-Formatter (PostToolUse):
#!/usr/bin/env bash
set -euo pipefail
files=$(jq -r '.tool_input.file_path // ""')
for file in $files; do
case "$file" in
*.py) black "$file" 2>/dev/null || true ;;
*.js|*.ts) prettier --write "$file" 2>/dev/null || true ;;
esac
done
exit 0Command Logger (PreToolUse):
#!/usr/bin/env bash
set -euo pipefail
cmd=$(jq -r '.tool_input.command // ""')
printf '%s %s\n' "$(date -Is)" "$cmd" >> .claude/bash-commands.log
exit 0Workflow Orchestration (SubagentStop - prompt type):
{
"hooks": {
"SubagentStop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Review the subagent's work. Did it complete all tasks?"
}
]
}
]
}
}---
Detection Patterns
1. Frontmatter Validation (HIGH Certainty)
Required:
- YAML frontmatter with
---delimiters namefield in frontmatterdescriptionfield in frontmatter
Recommended:
timeoutfor command hooks (default: 30s)- Hook type specification
Flag:
- Missing frontmatter delimiters
- Missing name or description
2. Script Safety (HIGH Certainty)
Required Safety Patterns:
set -euo pipefailat script start- Error handling for jq/JSON parsing
- Proper quoting of variables
Dangerous Patterns to Flag:
| Pattern | Risk | Certainty |
|---|---|---|
rm -rf | Destructive without confirmation | HIGH |
git reset --hard | Data loss risk | HIGH |
| `curl \ | sh` | Remote code execution |
eval "$input" | Arbitrary code execution | HIGH |
rm -r | Recursive delete (may be intentional) | MEDIUM |
git push --force | Force push (may be intentional) | MEDIUM |
3. Exit Code Handling (HIGH Certainty)
Check: Scripts use correct exit codes
Flag:
- Missing
exit 0for success path - Using exit code 1 for blocking (should be 2)
- No exit code at end of script
4. Hook Type Appropriateness (HIGH Certainty)
Check: Hook type matches event
Flag:
- Prompt hooks used for events other than Stop/SubagentStop
- Missing type specification
5. Lifecycle Event Appropriateness (MEDIUM Certainty)
| Event | Appropriate Use Cases |
|---|---|
PreToolUse | Security validation, command blocking, input modification |
PostToolUse | Formatting, logging, notifications |
Stop | Completion checks, cleanup, summary |
SubagentStop | Workflow orchestration, result validation |
SessionStart | Environment setup, initialization |
Flag:
- PostToolUse hooks trying to block actions (too late)
- PreToolUse hooks doing heavy processing (should be fast)
- Prompt hooks on unsupported events
6. Timeout Configuration (MEDIUM Certainty)
Guidelines:
- Default: 30 seconds for command hooks
- Network operations: Always set explicit timeout
- External service calls: Set timeout based on expected latency
Flag:
- No timeout for network operations
- Timeout missing for external service calls
- Unreasonably long timeouts (>60s without justification)
7. Output Format (MEDIUM Certainty)
PreToolUse Output Fields:
permissionDecision: allow, deny, or askpermissionDecisionReason: Explanation for decisionupdatedInput: Modified tool input (optional)additionalContext: Context for Claude (optional)
Flag:
- Invalid permissionDecision values
- Missing reason for deny decisions
- Malformed JSON output
8. Matcher Patterns (MEDIUM Certainty)
Check: Matcher syntax is valid
Flag:
- Invalid regex patterns
- Too broad matchers (
*without justification) - Matcher on events that don't support it (Stop, SubagentStop)
9. Anti-Patterns (LOW Certainty)
- Complex logic in hooks (should be simple and fast)
- Missing documentation/comments
- Hardcoded paths (should use
$CLAUDE_PROJECT_DIR) - Network calls without error handling
- Secrets/credentials in hook scripts
---
Auto-Fix Implementations
1. Missing safety header
#!/usr/bin/env bash
set -euo pipefail2. Missing exit code
Add exit 0 at end of script
3. Missing frontmatter fields
---
name: hook-name
description: Hook description
timeout: 30
---4. Wrong blocking exit code
Replace exit 1 with exit 2 for blocking errors
---
Output Format
## Hook Analysis: {hook-name}
**File**: {path}
**Type**: {command|prompt|config}
**Event**: {PreToolUse|PostToolUse|Stop|...}
### Summary
- HIGH: {count} issues
- MEDIUM: {count} issues
### Frontmatter Issues ({n})
| Issue | Fix | Certainty |
### Safety Issues ({n})
| Issue | Fix | Certainty |
### Exit Code Issues ({n})
| Issue | Fix | Certainty |
### Lifecycle Issues ({n})
| Issue | Fix | Certainty |
### Output Format Issues ({n})
| Issue | Fix | Certainty |---
Pattern Statistics
| Category | Patterns | Auto-Fixable |
|---|---|---|
| Frontmatter | 3 | 2 |
| Safety | 6 | 2 |
| Exit Code | 3 | 2 |
| Hook Type | 2 | 0 |
| Lifecycle | 5 | 0 |
| Timeout | 3 | 0 |
| Output | 3 | 0 |
| Matcher | 3 | 0 |
| Anti-Pattern | 5 | 0 |
| Total | 33 | 6 |
---
<examples>
Example: Missing Safety Header
<bad_example>
#!/usr/bin/env bash
cmd=$(jq -r '.tool_input.command // ""')Why it's bad: Missing set -euo pipefail means errors may silently pass. </bad_example>
<good_example>
#!/usr/bin/env bash
set -euo pipefail
cmd=$(jq -r '.tool_input.command // ""')Why it's good: Fails fast on errors, unset variables, and pipe failures. </good_example>
Example: Wrong Exit Code for Blocking
<bad_example>
if [[ "$cmd" == *"rm -rf"* ]]; then
echo "Blocked dangerous command" >&2
exit 1 # Wrong!
fiWhy it's bad: Exit code 1 is non-blocking. Action will still proceed. </bad_example>
<good_example>
if [[ "$cmd" == *"rm -rf"* ]]; then
echo '{"decision": "block", "reason": "Dangerous command"}' >&2
exit 2 # Correct blocking exit code
fiWhy it's good: Exit code 2 blocks the action. JSON output provides context. </good_example>
Example: Prompt Hook on Wrong Event
<bad_example>
{
"hooks": {
"PreToolUse": [
{
"hooks": [{ "type": "prompt", "prompt": "Is this safe?" }]
}
]
}
}Why it's bad: Prompt hooks only work for Stop and SubagentStop events. </bad_example>
<good_example>
{
"hooks": {
"PreToolUse": [
{
"hooks": [{ "type": "command", "command": "./validate.sh" }]
}
]
}
}Why it's good: Command hooks work for all events. </good_example>
Example: Dangerous Command Pattern
<bad_example>
if echo "$cmd" | grep -q 'rm'; then
exit 2
fiWhy it's bad: Too broad - blocks legitimate rm file.tmp. </bad_example>
<good_example>
if echo "$cmd" | grep -qE 'rm\s+(-rf|-fr)\s+/'; then
exit 2
fiWhy it's good: Specific pattern targets actual dangerous commands. </good_example>
Example: Hardcoded Path
<bad_example>
log_file="/home/user/project/.claude/commands.log"Why it's bad: Hardcoded path breaks on other machines. </bad_example>
<good_example>
log_file="$CLAUDE_PROJECT_DIR/.claude/commands.log"Why it's good: Uses environment variable for portability. </good_example> </examples>
---
Constraints
- Only apply auto-fixes for HIGH certainty issues
- Be cautious about security patterns - false negatives worse than false positives
- Never remove content, only suggest improvements
- Validate against embedded knowledge reference above
Related skills
FAQ
How many hook events does it know about?
The eleven-event lifecycle from SessionStart through Notification, including PreToolUse and PostToolUse.
Which events support prompt hooks?
Prompt hooks using LLM evaluation are only supported for the Stop and SubagentStop events.