← スキル一覧に戻る

warn-console-log
by oakoss
Open-source SaaS starter kit with React, TanStack, and Better Auth
⭐ 0🍴 0📅 2026年1月26日
SKILL.md
name: meta:hook-creator description: Create event hooks for Claude Code that trigger on specific events. Generate hooks with proper JSON configuration for automating workflows. Use when creating hooks, setting up event triggers, automating on file saves or tool calls.
Hook Creator
Quick Start
Add a hook to .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "echo 'File written!'"
}
]
}
]
}
}
Use /hooks command to manage hooks interactively.
Choosing an Approach
| Approach | Best For | Setup |
|---|---|---|
Hookify (/hookify) | Pattern-based warn/block | Markdown files, no code |
| Python hooks | Complex logic, external tools | Python scripts + settings.json |
| Inline bash | Simple one-liners | settings.json only |
Decision Tree
Need to detect a pattern and warn/block?
└─ Yes → Use hookify (/hookify "Don't use console.log")
└─ No, need complex logic?
└─ Yes → Use Python hook script
└─ No, just a simple command?
└─ Yes → Inline in settings.json
When to Use Hookify
- Block/warn based on regex pattern matching
- Quick setup without writing code
- Personal rules (
.local.mdfiles aren't committed)
# .claude/hookify.warn-console-log.local.md
---
name: warn-console-log
enabled: true
event: file
pattern: console\.log\(
action: warn
---
Remove console.log before committing.
When to Use Python Hooks
- Check file existence or conditions
- Run external validators
- Parse and analyze content
- Call APIs or external tools
#!/usr/bin/env -S uv run --quiet --script
# .claude/hooks/schema-change.py
import json, sys
input_data = json.loads(sys.stdin.read())
file_path = input_data.get("tool_input", {}).get("file_path", "")
if "src/modules/db/schema" in file_path:
print("📦 Schema modified. Run: pnpm db:generate")
Hook Locations
| Location | Scope | Committed |
|---|---|---|
.claude/settings.json | Project | Yes |
.claude/settings.local.json | Project (personal) | No |
~/.claude/settings.json | User (all projects) | N/A |
| Managed policy | Enterprise | N/A |
Event Types
| Event | Trigger | Matcher | Use Case |
|---|---|---|---|
PreToolUse | Before tool executes | Tool name | Block/validate |
PostToolUse | After tool completes | Tool name | Format/cleanup |
PermissionRequest | Permission dialog shown | Tool name | Auto-approve/deny |
UserPromptSubmit | User sends message | N/A | Transform input |
Notification | Claude sends notification | Type | Custom alerts |
Stop | Main agent finishes | N/A | Continue/cleanup |
SubagentStop | Subagent completes | N/A | Process results |
SessionStart | Session begins | Source | Initialization |
SessionEnd | Session ends | N/A | Final cleanup |
PreCompact | Before compaction | Trigger | Pre-compact logic |
Notification Matchers
| Matcher | Trigger |
|---|---|
permission_prompt | Permission request |
idle_prompt | Waiting for input (60s+) |
auth_success | Authentication success |
elicitation_dialog | MCP tool elicitation |
SessionStart Matchers
| Matcher | Trigger |
|---|---|
startup | New session |
resume | --resume, --continue, /resume |
clear | /clear command |
compact | Auto or manual compact |
Exit Codes
| Code | Meaning | Effect |
|---|---|---|
0 | Success | Continue normally |
1 | Error | Show error to user |
2 | Block | Block action (PreToolUse, PermissionRequest only) |
Hook Types
Command Hook
Executes a shell command:
{
"type": "command",
"command": "your-shell-command",
"timeout": 30
}
Prompt Hook (LLM-based)
Uses an LLM to evaluate (Stop/SubagentStop only):
{
"type": "prompt",
"prompt": "Evaluate if Claude should stop: $ARGUMENTS",
"timeout": 30
}
Environment Variables
| Variable | Available In | Purpose |
|---|---|---|
CLAUDE_PROJECT_DIR | All hooks | Project root path |
CLAUDE_ENV_FILE | SessionStart only | Persist env variables |
CLAUDE_PLUGIN_ROOT | Plugin hooks | Plugin directory |
CLAUDE_CODE_REMOTE | All hooks | "true" if remote session |
Persist Environment (SessionStart)
#!/bin/bash
if [ -n "$CLAUDE_ENV_FILE" ]; then
echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
fi
Matcher Patterns
| Pattern | Matches |
|---|---|
"Write" | Specific tool |
"Edit|Write" | Multiple tools (OR) |
"Bash.*" | Regex pattern |
"*" | All tools |
"" | Events without tools |
"mcp__github__.*" | MCP server tools |
Hook Configuration
{
"hooks": {
"<EventType>": [
{
"matcher": "<pattern>",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/script.sh",
"timeout": 30
}
]
}
]
}
}
Hooks in Components
Skills, agents, and commands can define hooks in frontmatter:
---
name: secure-operations
hooks:
PreToolUse:
- matcher: 'Bash'
hooks:
- type: command
command: './scripts/security-check.sh'
once: true
---
Supported events: PreToolUse, PostToolUse, Stop
The once: true option runs the hook only once per session (skills/commands only).
Common Templates
Block Dangerous Commands
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash -c 'input=$(cat); if echo \"$input\" | jq -e \".tool_input.command | test(\\\"rm -rf|--force\\\"; \\\"i\\\")\" >/dev/null 2>&1; then echo \"Blocked: Dangerous command\" >&2; exit 2; fi'"
}
]
}
]
}
}
Protect Files
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash -c 'input=$(cat); path=$(echo \"$input\" | jq -r \".tool_input.file_path // empty\"); if [[ \"$path\" == *.env* ]]; then echo \"Blocked: Protected file\" >&2; exit 2; fi'"
}
]
}
]
}
}
Auto-Format TypeScript
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'input=$(cat); file=$(echo \"$input\" | jq -r \".tool_input.file_path // empty\"); if [[ \"$file\" == *.ts ]]; then npx prettier --write \"$file\" 2>/dev/null; fi'",
"timeout": 10
}
]
}
]
}
}
Desktop Notification
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude needs permission\" with title \"Claude Code\"'"
}
]
}
]
}
}
Script-Based Hooks
For complex logic, use Python scripts with uv instead of inline bash. See reference.md for templates and examples.
Common Mistakes
| Mistake | Impact | Correct Pattern |
|---|---|---|
| Using settings.json for patterns | Overly complex | Use hookify for pattern matching |
| Exit 1 in PreToolUse | Shows error, doesn't block | Use exit 2 to block |
| Complex inline bash | Hard to maintain | Use Python script with uv |
| No timeout | Hangs on slow commands | Set reasonable timeout |
Missing $CLAUDE_PROJECT_DIR | Path errors | Quote: "$CLAUDE_PROJECT_DIR"/... |
| Not testing stdin parsing | Runtime failures | Test: echo '{}' | script.py |
Validation
Run validation after every hook change:
uv run .claude/skills/meta-hook-creator/scripts/validate-hook.py .claude/settings.json
Checklist
- Hook defined in settings.json
- Event type is valid
- Matcher pattern correct for event
- Command handles stdin JSON properly
- Exit codes match intended behavior
- Timeout set appropriately
- External scripts are executable
Delegation
- After creating/modifying hooks: Run
uv run .claude/skills/meta-hook-creator/scripts/validate-hook.py .claude/settings.json - Pattern discovery: For existing hook patterns, use
Exploreagent
Additional Resources
- For advanced JSON output, MCP integration, security: reference.md
- For complete Python hook examples: examples.md
References
- Official Hooks Reference: code.claude.com/docs/en/hooks
- Hooks Guide: code.claude.com/docs/en/hooks-guide
- jq Manual: stedolan.github.io/jq/manual
スコア
総合スコア
65/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
3ヶ月以内に更新
+5
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
レビュー
💬
レビュー機能は近日公開予定です

