creating-claude-hooks
Claude Code hooksを作成・公開する際に、実行可能な形式、イベントの種類、JSONの入出力、終了コード、セキュリティ要件、PRPMパッケージ構造など、必要な情報を網羅的に理解し、適切に設定・構築するSkill。
📜 元の英語説明(参考)
Use when creating or publishing Claude Code hooks - covers executable format, event types, JSON I/O, exit codes, security requirements, and PRPM package structure
🇯🇵 日本人クリエイター向け解説
Claude Code hooksを作成・公開する際に、実行可能な形式、イベントの種類、JSONの入出力、終了コード、セキュリティ要件、PRPMパッケージ構造など、必要な情報を網羅的に理解し、適切に設定・構築するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o creating-claude-hooks.zip https://jpskill.com/download/17073.zip && unzip -o creating-claude-hooks.zip && rm creating-claude-hooks.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/17073.zip -OutFile "$d\creating-claude-hooks.zip"; Expand-Archive "$d\creating-claude-hooks.zip" -DestinationPath $d -Force; ri "$d\creating-claude-hooks.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
creating-claude-hooks.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
creating-claude-hooksフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Claude コードフックの作成
このスキルは、Claude コードフックの作成、改善、または公開時に使用します。フックの形式、イベント処理、I/O規約、およびパッケージ構造に関する重要なガイダンスを提供します。
このスキルを使用するタイミング
以下の場合にこのスキルを有効にします。
- ユーザーが新しい Claude コードフックの作成を依頼した場合
- ユーザーがフックを PRPM パッケージとして公開したい場合
- ユーザーがフックの形式またはイベントを理解する必要がある場合
- ユーザーがフックの実行に関するトラブルシューティングを行っている場合
- ユーザーがフック、スキル、コマンドの違いについて質問した場合
クイックリファレンス
フックファイルの形式
| 側面 | 要件 |
|---|---|
| 場所 | .claude/hooks/<event-name> |
| 形式 | 実行可能ファイル(シェル、TypeScript、Pythonなど) |
| 権限 | 実行可能である必要がある(chmod +x) |
| シバン | 必須(#!/bin/bash または #!/usr/bin/env node) |
| 入力 | stdin 経由の JSON |
| 出力 | stdout 経由のテキスト(ユーザーに表示) |
| 終了コード | 0 = 成功、2 = ブロック、その他 = エラー |
利用可能なイベント
| イベント | 発火するタイミング | 一般的なユースケース |
|---|---|---|
session-start |
新しいセッションが開始されるとき | 環境設定、ロギング、チェック |
user-prompt-submit |
ユーザー入力が処理される前 | バリデーション、エンハンスメント、フィルタリング |
tool-call |
ツールの実行前 | 権限チェック、ロギング、変更 |
assistant-response |
アシスタントが応答した後 | フォーマット、ロギング、クリーンアップ |
フック形式の要件
ファイルの場所
プロジェクトフック:
.claude/hooks/session-start
.claude/hooks/user-prompt-submit
ユーザーグローバルフック:
~/.claude/hooks/session-start
~/.claude/hooks/tool-call
実行可能ファイルの要件
すべてのフックは以下を満たす必要があります。
-
シバン行を持つこと:
#!/bin/bash # または #!/usr/bin/env node # または #!/usr/bin/env python3 -
実行可能であること:
chmod +x .claude/hooks/session-start -
stdin からの JSON 入力を処理すること:
#!/bin/bash INPUT=$(cat) FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty') -
適切なコードで終了すること:
exit 0 # 成功 exit 2 # 操作をブロック exit 1 # エラー(ログに記録されるが続行)
入出力形式
JSON 入力構造
フックは、イベント固有のデータを含む JSON を stdin 経由で受信します。
{
"event": "tool-call",
"timestamp": "2025-01-15T10:30:00Z",
"session_id": "abc123",
"current_dir": "/path/to/project",
"input": {
"file_path": "/path/to/file.ts",
"command": "npm test",
"old_string": "...",
"new_string": "..."
}
}
Stdout 出力
- 通常の出力はトランスクリプトに表示されます
- 空の出力はサイレントに実行されます
- エラーには stderr (
>&2) を使用します
終了コード
| コード | 意味 | 動作 |
|---|---|---|
0 |
成功 | 通常どおり続行 |
2 |
ブロック | 操作を停止し、エラーを表示 |
1 またはその他 |
エラー | エラーをログに記録し、続行 |
スキーマ検証
フックは JSON スキーマに対して検証する必要があります。
スキーマ URL: https://github.com/pr-pm/prpm/blob/main/packages/converters/schemas/claude-hook.schema.json
必要なフロントマターフィールド:
name- フック識別子(小文字、ハイフンのみ)description- フックの機能event- イベントタイプ(オプション、ファイル名から推測)language- bash, typescript, javascript, python, binary (オプション)hookType: "hook"- ラウンドトリップ変換用
よくある間違い
| 間違い | 問題 | 解決策 |
|---|---|---|
| 変数を引用符で囲まない | スペースで壊れる | 常に "$VAR" を使用する |
| シバンがない | 実行されない | #!/bin/bash を追加する |
| 実行可能でない | 権限が拒否される | chmod +x hook-file を実行する |
| stdout へのロギング | トランスクリプトが乱雑になる | stderr を使用する: echo "log" >&2 |
| 間違った終了コード | 必要なときにブロックしない | exit 2 を使用してブロックする |
| 入力検証がない | セキュリティリスク | 常に JSON フィールドを検証する |
| 遅い操作 | Claude をブロックする | バックグラウンドで実行するか、PostToolUse を使用する |
| 絶対パスがない | スクリプトが見つからない | $CLAUDE_PLUGIN_ROOT を使用する |
基本的なフックの例
シェルスクリプトフック
#!/bin/bash
# .claude/hooks/session-start
# セッションの開始をログに記録
echo "Session started at $(date)" >> ~/.claude/session.log
# 環境をチェック
if ! command -v node &> /dev/null; then
echo "Warning: Node.js not installed" >&2
fi
# ユーザーに出力
echo "Development environment ready"
exit 0
TypeScript フック
#!/usr/bin/env node
// .claude/hooks/user-prompt-submit
import { readFileSync } from 'fs';
// stdin から JSON を読み取る
const input = readFileSync(0, 'utf-8');
const data = JSON.parse(input);
// プロンプトを検証
if (data.prompt.includes('API_KEY')) {
console.error('Warning: Prompt may contain secrets');
process.exit(2); // ブロック
}
console.log('Prompt validated');
process.exit(0);
ベストプラクティス
1. フックを高速に保つ
PreToolUse フックの場合は 100ms 未満を目標にします。
- 可能であれば結果をキャッシュする
- 重い操作はバックグラウンドで実行する
- ワイルドカードではなく、特定のmatcherを使用する
2. エラーを適切に処理する
# 依存関係が存在するか確認
if ! command -v jq &> /dev/null; then
echo "jq not installed, skipping" >&2
exit 0
fi
# 入力を検証
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
if [[ -z "$FILE" ]]; then
echo "No file path provided" >&2
exit 1
fi
3. シバンを使用する
常にシバンで開始します。
#!/bin/bash
#!/usr/bin/env node
#!/usr/bin/env python3
4. 機密ファイルを保護する
BLOCKED=(".env" ".env.*" "*.pem" "*.key")
for pattern in "${BLOCKED[@]}"; do
case "$FILE" in
$pattern)
echo "Blocked: $FILE is sensitive" >&2
exit 2
;;
esac
done
5. すべての変数を引用符で囲む
# 間違い - スペースで壊れる
prettier --write $FILE
# 正しい - スペースを処理する
prettier --write "$FILE"
6. デバッグのためにログを記録する
LOG_FILE=~/.claude-hooks/debug.log
# ファイルにログを記録
echo "[$(date)] Processing $FILE" >> "$LOG_FILE"
# stderr にログを記録 (トランスクリプトに表示)
echo "Hook running..." >&2
PRPM パッケージとして公開する
パッケージ構造
my-hook/
├─
(原文がここで切り詰められています) 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Creating Claude Code Hooks
Use this skill when creating, improving, or publishing Claude Code hooks. Provides essential guidance on hook format, event handling, I/O conventions, and package structure.
When to Use This Skill
Activate this skill when:
- User asks to create a new Claude Code hook
- User wants to publish a hook as a PRPM package
- User needs to understand hook format or events
- User is troubleshooting hook execution
- User asks about hook vs skill vs command differences
Quick Reference
Hook File Format
| Aspect | Requirement |
|---|---|
| Location | .claude/hooks/<event-name> |
| Format | Executable file (shell, TypeScript, Python, etc.) |
| Permissions | Must be executable (chmod +x) |
| Shebang | Required (#!/bin/bash or #!/usr/bin/env node) |
| Input | JSON via stdin |
| Output | Text via stdout (shown to user) |
| Exit Codes | 0 = success, 2 = block, other = error |
Available Events
| Event | When It Fires | Common Use Cases |
|---|---|---|
session-start |
New session begins | Environment setup, logging, checks |
user-prompt-submit |
Before user input processes | Validation, enhancement, filtering |
tool-call |
Before tool execution | Permission checks, logging, modification |
assistant-response |
After assistant responds | Formatting, logging, cleanup |
Hook Format Requirements
File Location
Project hooks:
.claude/hooks/session-start
.claude/hooks/user-prompt-submit
User-global hooks:
~/.claude/hooks/session-start
~/.claude/hooks/tool-call
Executable Requirements
Every hook MUST:
-
Have a shebang line:
#!/bin/bash # or #!/usr/bin/env node # or #!/usr/bin/env python3 -
Be executable:
chmod +x .claude/hooks/session-start -
Handle JSON input from stdin:
#!/bin/bash INPUT=$(cat) FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty') -
Exit with appropriate code:
exit 0 # Success exit 2 # Block operation exit 1 # Error (logs but continues)
Input/Output Format
JSON Input Structure
Hooks receive JSON via stdin with event-specific data:
{
"event": "tool-call",
"timestamp": "2025-01-15T10:30:00Z",
"session_id": "abc123",
"current_dir": "/path/to/project",
"input": {
"file_path": "/path/to/file.ts",
"command": "npm test",
"old_string": "...",
"new_string": "..."
}
}
Stdout Output
- Normal output shows in transcript
- Empty output runs silently
- Use stderr (
>&2) for errors
Exit Codes
| Code | Meaning | Behavior |
|---|---|---|
0 |
Success | Continue normally |
2 |
Block | Stop operation, show error |
1 or other |
Error | Log error, continue |
Schema Validation
Hooks should validate against the JSON schema:
Schema URL: https://github.com/pr-pm/prpm/blob/main/packages/converters/schemas/claude-hook.schema.json
Required frontmatter fields:
name- Hook identifier (lowercase, hyphens only)description- What the hook doesevent- Event type (optional, inferred from filename)language- bash, typescript, javascript, python, binary (optional)hookType: "hook"- For round-trip conversion
Common Mistakes
| Mistake | Problem | Solution |
|---|---|---|
| Not quoting variables | Breaks on spaces | Always use "$VAR" |
| Missing shebang | Won't execute | Add #!/bin/bash |
| Not executable | Permission denied | Run chmod +x hook-file |
| Logging to stdout | Clutters transcript | Use stderr: echo "log" >&2 |
| Wrong exit code | Doesn't block when needed | Use exit 2 to block |
| No input validation | Security risk | Always validate JSON fields |
| Slow operations | Blocks Claude | Run in background or use PostToolUse |
| Absolute paths missing | Can't find scripts | Use $CLAUDE_PLUGIN_ROOT |
Basic Hook Examples
Shell Script Hook
#!/bin/bash
# .claude/hooks/session-start
# Log session start
echo "Session started at $(date)" >> ~/.claude/session.log
# Check environment
if ! command -v node &> /dev/null; then
echo "Warning: Node.js not installed" >&2
fi
# Output to user
echo "Development environment ready"
exit 0
TypeScript Hook
#!/usr/bin/env node
// .claude/hooks/user-prompt-submit
import { readFileSync } from 'fs';
// Read JSON from stdin
const input = readFileSync(0, 'utf-8');
const data = JSON.parse(input);
// Validate prompt
if (data.prompt.includes('API_KEY')) {
console.error('Warning: Prompt may contain secrets');
process.exit(2); // Block
}
console.log('Prompt validated');
process.exit(0);
Best Practices
1. Keep Hooks Fast
Target < 100ms for PreToolUse hooks:
- Cache results where possible
- Run heavy operations in background
- Use specific matchers, not wildcards
2. Handle Errors Gracefully
# Check dependencies exist
if ! command -v jq &> /dev/null; then
echo "jq not installed, skipping" >&2
exit 0
fi
# Validate input
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
if [[ -z "$FILE" ]]; then
echo "No file path provided" >&2
exit 1
fi
3. Use Shebangs
Always start with shebang:
#!/bin/bash
#!/usr/bin/env node
#!/usr/bin/env python3
4. Secure Sensitive Files
BLOCKED=(".env" ".env.*" "*.pem" "*.key")
for pattern in "${BLOCKED[@]}"; do
case "$FILE" in
$pattern)
echo "Blocked: $FILE is sensitive" >&2
exit 2
;;
esac
done
5. Quote All Variables
# WRONG - breaks on spaces
prettier --write $FILE
# RIGHT - handles spaces
prettier --write "$FILE"
6. Log for Debugging
LOG_FILE=~/.claude-hooks/debug.log
# Log to file
echo "[$(date)] Processing $FILE" >> "$LOG_FILE"
# Log to stderr (shows in transcript)
echo "Hook running..." >&2
Publishing as PRPM Package
Package Structure
my-hook/
├── prpm.json # Package manifest
├── HOOK.md # Hook documentation
└── hook-script.sh # Hook executable
prpm.json
{
"name": "@username/hook-name",
"version": "1.0.0",
"description": "Brief description shown in search",
"author": "Your Name",
"format": "claude",
"subtype": "hook",
"tags": ["automation", "security", "formatting"],
"main": "HOOK.md"
}
HOOK.md Format
---
name: session-logger
description: Logs session start/end times for tracking
event: SessionStart
language: bash
hookType: hook
---
# Session Logger Hook
Logs Claude Code session activity for tracking and debugging.
## Installation
This hook will be installed to `.claude/hooks/session-start`.
## Behavior
- Logs session start time to `~/.claude/session.log`
- Displays environment status
- Runs silent dependency checks
## Requirements
- bash 4.0+
- write access to `~/.claude/`
## Source Code
\`\`\`bash
#!/bin/bash
echo "Session started at $(date)" >> ~/.claude/session.log
echo "Environment ready"
exit 0
\`\`\`
Publishing Process
# Test locally first
prpm test
# Publish to registry
prpm publish
# Version bumps
prpm publish patch # 1.0.0 -> 1.0.1
prpm publish minor # 1.0.0 -> 1.1.0
prpm publish major # 1.0.0 -> 2.0.0
Security Requirements
Input Validation
# Parse JSON safely
INPUT=$(cat)
if ! FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty' 2>&1); then
echo "JSON parse failed" >&2
exit 1
fi
# Validate field exists
[[ -n "$FILE" ]] || exit 1
Path Sanitization
# Prevent directory traversal
if [[ "$FILE" == *".."* ]]; then
echo "Path traversal detected" >&2
exit 2
fi
# Keep in project directory
if [[ "$FILE" != "$CLAUDE_PROJECT_DIR"* ]]; then
echo "File outside project" >&2
exit 2
fi
User Confirmation
Claude Code automatically:
- Requires confirmation before installing hooks
- Shows hook source code to user
- Warns about hook execution
- Displays hook output in transcript
Hooks vs Skills vs Commands
| Feature | Hooks | Skills | Commands |
|---|---|---|---|
| Format | Executable code | Markdown | Markdown |
| Trigger | Automatic (events) | Automatic (context) | Manual (/command) |
| Language | Any executable | N/A | N/A |
| Use Case | Automation, validation | Reference, patterns | Quick tasks |
| Security | Requires confirmation | No special permissions | Inherits from session |
Examples:
- Hook: Auto-format files on save
- Skill: Reference guide for testing patterns
- Command:
/review-prquick code review
Related Resources
- claude-hook-writer skill - Detailed hook development guidance
- typescript-hook-writer skill - TypeScript-specific hook development
- Claude Code Docs
- Schema
Checklist for New Hooks
Before publishing:
- [ ] Shebang line included
- [ ] File is executable (
chmod +x) - [ ] Validates all stdin input
- [ ] Quotes all variables
- [ ] Handles missing dependencies gracefully
- [ ] Uses appropriate exit codes
- [ ] Logs errors to stderr or file
- [ ] Tests with edge cases (spaces, Unicode, missing fields)
- [ ] Documents dependencies in HOOK.md
- [ ] Includes installation instructions
- [ ] Source code included in documentation
- [ ] Clear description and tags in prpm.json
- [ ] Version number is semantic