enhance-hooks について
Agent 開発者向けの Claude Code Hook 監査スキルです。Hook の設定とスクリプトの安全性、正確性、ライフサイクルとの適合性を確認し、一部の修正を適用できます。
主な機能
- 01Hook ファイルの検出と分類
- 02メタデータと設定の検証
- 03スクリプト内の危険なパターンの確認
- 04終了コード・イベント種別・マッチャーの検査
- 05一部の修正の提案または適用
活用シーン
- 01プロジェクトの Hook 設定の監査
- 02コマンドスクリプトの危険な操作の確認
- 03ブロック動作とイベントの適合性確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agent-sh/ agentsys --skill enhance-hooksインストール後、Claude Code で/enhance-hooksを入力して読み込まれたか確認します。
詳細
enhance-hooks
フック定義とスクリプトを分析し、安全性、正確性、ベストプラクティスを確認します。
引数の解析
const args = '$ARGUMENTS'.split(' ').filter(Boolean);
const targetPath = args.find(a => !a.startsWith('--')) || '.';
const fix = args.includes('--fix');
ワークフロー
- 検出 - フックファイル(.md、.sh、.json)を検索します
- 分類 - フックの種類とイベントを特定します
- 解析 - フロントマターとスクリプトの内容を抽出します
- チェック - 以下のナレッジに基づいて、すべてのパターンチェックを実行します
- フィルタリング - 確度によるフィルタリングを適用します
- レポート - Markdown形式の出力を生成します
- 修正 - --fix フラグが指定されている場合、自動修正を適用します
フックのナレッジリファレンス
フックとは
フックとは、Claude Code セッションの特定のタイミングで実行される自動アクションです。bash コマンドや LLM ベースの評価を通じて、Claude のアクションの検証、監視、制御を行えます。
フックのライフサイクル(完全なリファレンス)
フックは次の順序で実行されます。
| 順序 | イベント | 説明 | マッチャー必須 |
|---|---|---|---|
| 1 | SessionStart | セッションの開始または再開 | いいえ |
| 2 | UserPromptSubmit | ユーザーがプロンプトを送信 | いいえ |
| 3 | PreToolUse | ツールの実行前(変更またはブロック可能) | はい |
| 4 | PermissionRequest | 権限ダイアログの表示時 | はい |
| 5 | PostToolUse | ツールの実行成功後 | はい |
| 6 | SubagentStart | サブエージェントの起動時 | いいえ |
| 7 | SubagentStop | サブエージェントの終了時 | いいえ |
| 8 | Stop | Claude の応答完了時 | いいえ |
| 9 | PreCompact | コンテキストの圧縮前 | いいえ |
| 10 | SessionEnd | セッションの終了時 | いいえ |
| 11 | Notification | Claude Code が通知を送信 | いいえ |
フックの種類
コマンドフック(type: "command"):
- stdin/stdout を完全に制御して bash コマンドを実行します
- すべてのイベントで使用できます
プロンプトフック(type: "prompt"):
- LLM による評価を使い、コンテキストを考慮したインテリジェントな判断を行います
StopイベントとSubagentStopイベントでのみサポートされています
設定場所
| ファイル | 場所 | スコープ | コミット対象 |
|---|---|---|---|
| ユーザー設定 | ~/.claude/settings.json | すべてのプロジェクト | いいえ |
| プロジェクト設定 | .claude/settings.json | 現在のプロジェクト | はい |
| ローカル設定 | .claude/settings.local.json | 現在のプロジェクト | いいえ |
設定構造
{
"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
}
]
}
]
}
}
マッチャーの構文
| パターン | 説明 |
|---|---|
Write | ツール名と完全一致 |
Edit|Write | 複数のツールに一致(正規表現の OR) |
Notebook.* | 正規表現パターンによる照合 |
* または "" | すべてのツールに一致 |
| (省略) | Stop、SubagentStop、UserPromptSubmit で必須 |
入力スキーマ(stdin 経由の JSON)
すべてのフックは、次の JSON 構造を受け取ります。
{
"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"
}
}
終了コード
| 終了コード | 動作 |
|---|---|
| 0 | 成功 - stdout がユーザーに表示されるか、コンテキストとして追加されます |
| 2 | ブロックエラー - stderr が表示され、アクションがブロックされます |
| その他 | 非ブロッキングエラー - verbose モードで stderr が表示されます |
出力スキーマ
PreToolUse の判断制御:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow|deny|ask",
"permissionDecisionReason": "Reason for decision",
"updatedInput": {
"command": "modified command"
},
"additionalContext": "Context for Claude"
}
}
Stop/SubagentStop の制御:
{
"decision": "block",
"reason": "Tasks incomplete: missing test coverage"
}
環境変数
| 変数 | 説明 | 使用可能な場所 |
|---|---|---|
CLAUDE_PROJECT_DIR | プロジェクトルートの絶対パス | すべてのフック |
CLAUDE_CODE_REMOTE | リモートセッションの場合は "true" | すべてのフック |
CLAUDE_ENV_FILE | 環境変数を永続化するためのパス | SessionStart のみ |
CLAUDE_FILE_PATHS | ファイルパスをスペース区切りで指定 | PostToolUse(Write/Edit) |
実用的なフックの例
セキュリティファイアウォール(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 0
自動フォーマッター(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 0
コマンドロガー(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 0
ワークフローオーケストレーション(SubagentStop - prompt タイプ):
{
"hooks": {
"SubagentStop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Review the subagent's work. Did it complete all tasks?"
}
]
}
]
}
}
検出パターン
1. フロントマターの検証(確度:高)
必須:
---区切りを使用した YAML フロントマター- フロントマター内の
nameフィールド - フロントマター内の
descriptionフィールド
推奨:
- command フックの
timeout(デフォルト:30s) - フックタイプの指定
検出対象:
- フロントマター区切りの欠落
- name または description の欠落
2. スクリプトの安全性(高い確度)
必須の安全パターン:
- スクリプトの先頭に
set -euo pipefailを記述する - jq/JSON の解析でエラーを処理する
- 変数を適切に引用符で囲む
注意すべき危険なパターン:
| パターン | リスク | 確度 |
|---|---|---|
rm -rf | 確認なしで破壊的な操作を行う | 高 |
git reset --hard | データ損失のリスク | 高 |
curl | sh | リモートコード実行 | 高 |
eval "$input" | 任意のコード実行 | 高 |
rm -r | 再帰的な削除(意図的な場合もあります) | 中 |
git push --force | 強制プッシュ(意図的な場合もあります) | 中 |
3. 終了コードの処理(高い確度)
確認項目: スクリプトが適切な終了コードを使用していること
注意すべき点:
- 成功時の処理に
exit 0がない - ブロックする処理に終了コード 1 を使用している(2 を使用する必要があります)
- スクリプトの最後に終了コードがない
4. フックタイプの適切さ(高い確度)
確認項目: フックタイプがイベントに適合していること
注意すべき点:
- Stop/SubagentStop 以外のイベントにプロンプトフックを使用している
- タイプの指定がない
5. ライフサイクルイベントの適切さ(中程度の確度)
| イベント | 適切なユースケース |
|---|---|
PreToolUse | セキュリティ検証、コマンドのブロック、入力の変更 |
PostToolUse | フォーマット、ログ記録、通知 |
Stop | 完了確認、クリーンアップ、要約 |
SubagentStop | ワークフローのオーケストレーション、結果の検証 |
SessionStart | 環境設定、初期化 |
注意すべき点:
- PostToolUse フックでアクションをブロックしようとしている(処理が遅すぎます)
- PreToolUse フックで負荷の高い処理を行っている(高速である必要があります)
- サポートされていないイベントでプロンプトフックを使用している
6. タイムアウトの設定(中程度の確度)
ガイドライン:
- デフォルト:コマンドフックは 30 秒
- ネットワーク操作:必ず明示的にタイムアウトを設定する
- 外部サービス呼び出し:想定されるレイテンシーに応じてタイムアウトを設定する
注意すべき点:
- ネットワーク操作にタイムアウトがない
- 外部サービス呼び出しにタイムアウトが設定されていない
- 妥当でないほど長いタイムアウト(正当な理由なく 60 秒を超える)
7. 出力形式(中程度の確度)
PreToolUse の出力フィールド:
permissionDecision:allow、deny、または askpermissionDecisionReason:判断の理由updatedInput:変更されたツール入力(任意)additionalContext:Claude に渡すコンテキスト(任意)
注意すべき点:
permissionDecisionの値が無効- deny の判断に理由がない
- JSON 出力の形式が不正
8. マッチャーパターン(中程度の確度)
確認項目: マッチャーの構文が有効であること
注意すべき点:
- 正規表現パターンが無効
- 範囲が広すぎるマッチャー(正当な理由なく
*を使用) - マッチャーをサポートしていないイベント(Stop、SubagentStop)で使用している
9. アンチパターン(低い確度)
- フック内の複雑なロジック(単純かつ高速である必要があります)
- ドキュメントやコメントがない
- パスがハードコードされている(
$CLAUDE_PROJECT_DIRを使用する必要があります) - エラー処理のないネットワーク呼び出し
- フックスクリプト内のシークレット/認証情報
自動修正の実装
1. 安全性ヘッダーがない場合
#!/usr/bin/env bash
set -euo pipefail
2. 終了コードがない場合
スクリプトの末尾に exit 0 を追加する
3. フロントマターフィールドがない場合
---
name: hook-name
description: Hook description
timeout: 30
---
4. ブロック時の終了コードが誤っている場合
ブロックエラーでは exit 1 を exit 2 に置き換える
出力形式
## 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 |
パターン統計
| カテゴリ | パターン数 | 自動修正可能 |
|---|---|---|
| フロントマター | 3 | 2 |
| 安全性 | 6 | 2 |
| 終了コード | 3 | 2 |
| フックタイプ | 2 | 0 |
| ライフサイクル | 5 | 0 |
| タイムアウト | 3 | 0 |
| 出力 | 3 | 0 |
| マッチャー | 3 | 0 |
| アンチパターン | 5 | 0 |
| 合計 | 33 | 6 |
### 例:安全性ヘッダーがない場合
<bad_example>
#!/usr/bin/env bash
cmd=$(jq -r '.tool_input.command // ""')
問題点:set -euo pipefail がないと、エラーが気付かれないまま処理される可能性があります。
</bad_example>
<good_example>
#!/usr/bin/env bash
set -euo pipefail
cmd=$(jq -r '.tool_input.command // ""')
良い点:エラー、未設定の変数、パイプの失敗が発生すると、すぐに処理を中断します。 </good_example>
例:ブロック時の終了コードが誤っている
<bad_example>
if [[ "$cmd" == *"rm -rf"* ]]; then
echo "Blocked dangerous command" >&2
exit 1 # Wrong!
fi
問題点:終了コード 1 ではブロックされません。アクションは引き続き実行されます。 </bad_example>
<good_example>
if [[ "$cmd" == *"rm -rf"* ]]; then
echo '{"decision": "block", "reason": "Dangerous command"}' >&2
exit 2 # Correct blocking exit code
fi
良い点:終了コード 2 はアクションをブロックします。JSON 出力でコンテキストが示されます。 </good_example>
例:プロンプトフックのイベントが誤っている
<bad_example>
{
"hooks": {
"PreToolUse": [
{
"hooks": [{ "type": "prompt", "prompt": "Is this safe?" }]
}
]
}
}
問題点:プロンプトフックは Stop イベントと SubagentStop イベントでのみ機能します。 </bad_example>
<good_example>
{
"hooks": {
"PreToolUse": [
{
"hooks": [{ "type": "command", "command": "./validate.sh" }]
}
]
}
}
良い点:コマンドフックはすべてのイベントで機能します。 </good_example>
例:危険なコマンドパターン
<bad_example>
if echo "$cmd" | grep -q 'rm'; then
exit 2
fi
問題点:範囲が広すぎるため、正当な rm file.tmp までブロックします。
</bad_example>
<good_example>
if echo "$cmd" | grep -qE 'rm\s+(-rf|-fr)\s+/'; then
exit 2
fi
良い点:具体的なパターンで、実際に危険なコマンドを対象にしています。 </good_example>
例:パスのハードコード
<bad_example>
log_file="/home/user/project/.claude/commands.log"
問題点:パスをハードコードすると、ほかのマシンで動作しなくなります。 </bad_example>
<good_example>
log_file="$CLAUDE_PROJECT_DIR/.claude/commands.log"
良い点:環境変数を使用することで、移植性を確保しています。 </good_example>
制約
- 確実性が高い問題に対してのみ、自動修正を適用してください
- セキュリティパターンは慎重に扱ってください。誤検知よりも見逃しのほうが深刻です
- コンテンツは削除せず、改善案のみを提示してください
- 上記に埋め込まれたナレッジリファレンスに照らして検証してください