Hooksとは何か
Claude CodeのHooksは、AIがツールを実行する直前・直後に自動でスクリプトを走らせる仕組みだ。
例えば:
- コードを書いた後 → 自動でフォーマッター実行
- bashコマンド実行前 → 危険なコマンドをブロック
- ファイル編集後 → lintチェックを走らせる
人間がClaude Codeと並んで「formatterかけて」「lintチェックして」と言わなくても、勝手にやってくれる。
設定場所
Hooksは .claude/settings.json(プロジェクト固有)または ~/.claude/settings.json(全プロジェクト共通)に書く。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python .claude/hooks/check_dangerous.py"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\""
}
]
}
]
}
}
PreToolUse: 実行前フック
危険なコマンドのブロック
PreToolUse はツール実行前に走る。終了コード2を返すとツール実行がブロックされる。
# .claude/hooks/check_dangerous.py
import json
import sys
data = json.load(sys.stdin)
tool_name = data.get("tool_name", "")
tool_input = data.get("tool_input", {})
# Bashコマンドのチェック
if tool_name == "Bash":
command = tool_input.get("command", "")
BLOCKED_PATTERNS = [
"rm -rf /",
"rm -rf ~",
"DROP TABLE",
"DROP DATABASE",
"git push --force origin main",
"git push --force origin master",
]
for pattern in BLOCKED_PATTERNS:
if pattern in command:
print(f"BLOCKED: '{pattern}' は実行が禁止されています", file=sys.stderr)
print(f"コマンド: {command}", file=sys.stderr)
sys.exit(2) # 2でブロック
sys.exit(0) # 0で許可
終了コードの意味
| コード | 意味 |
|---|---|
| 0 | 許可(続行) |
| 2 | ブロック(ツール実行を停止) |
| その他 | 警告(ログに記録、実行は続行) |
PostToolUse: 実行後フック
ファイル保存後に自動フォーマット
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python .claude/hooks/auto_format.py"
}
]
}
]
}
}
# .claude/hooks/auto_format.py
import json
import subprocess
import sys
from pathlib import Path
data = json.load(sys.stdin)
tool_input = data.get("tool_input", {})
file_path = tool_input.get("file_path", "")
if not file_path:
sys.exit(0)
path = Path(file_path)
if path.suffix in (".py",):
subprocess.run(["ruff", "format", str(path)], check=False)
subprocess.run(["ruff", "check", "--fix", str(path)], check=False)
elif path.suffix in (".ts", ".tsx", ".js", ".jsx"):
subprocess.run(["npx", "prettier", "--write", str(path)], check=False)
elif path.suffix in (".go",):
subprocess.run(["gofmt", "-w", str(path)], check=False)
sys.exit(0)
これで、Claude Codeがコードを書くたびに自動的にフォーマットがかかる。
実践的なHooks設定集
セキュリティスキャン(ファイル書き込み後)
# .claude/hooks/security_scan.py
import json
import subprocess
import sys
data = json.load(sys.stdin)
tool_input = data.get("tool_input", {})
file_path = tool_input.get("file_path", "")
if not file_path or not file_path.endswith(".py"):
sys.exit(0)
# シークレットパターンのスキャン
import re
SECRET_PATTERNS = [
r"sk-ant-api\d{2}-[a-zA-Z0-9_-]{86}", # Anthropic
r"AKIA[0-9A-Z]{16}", # AWS
r"ghp_[a-zA-Z0-9]{36}", # GitHub
r"sk_(live|test)_[a-zA-Z0-9]{24}", # Stripe
]
with open(file_path, encoding="utf-8", errors="replace") as f:
content = f.read()
found = []
for pattern in SECRET_PATTERNS:
matches = re.findall(pattern, content)
found.extend(matches)
if found:
print(f"WARNING: シークレットの可能性あり: {found}", file=sys.stderr)
# 警告のみ(ブロックしない場合はsys.exit(0))
# ブロックする場合は sys.exit(2)
sys.exit(0)
テスト自動実行(実装ファイル変更時)
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python .claude/hooks/run_tests.py",
"timeout": 60
}
]
}
]
}
}
# .claude/hooks/run_tests.py
import json
import subprocess
import sys
from pathlib import Path
data = json.load(sys.stdin)
tool_input = data.get("tool_input", {})
file_path = tool_input.get("file_path", "")
if not file_path:
sys.exit(0)
path = Path(file_path)
# src/ 以下のPythonファイルのみ
if "src" not in path.parts or path.suffix != ".py":
sys.exit(0)
# 対応するテストファイルを探す
test_path = Path("tests") / f"test_{path.name}"
if not test_path.exists():
sys.exit(0)
result = subprocess.run(
["pytest", str(test_path), "-q", "--no-header"],
capture_output=True,
text=True
)
print(result.stdout, file=sys.stdout)
if result.returncode != 0:
print(result.stderr, file=sys.stderr)
# テスト失敗時は警告のみ(ブロックは任意)
sys.exit(0)
環境変数
フックスクリプト内では以下の環境変数が使える。
| 変数 | 内容 |
|---|---|
CLAUDE_PROJECT_DIR |
プロジェクトのルートディレクトリ |
CLAUDE_TOOL_NAME |
実行されたツール名 |
CLAUDE_TOOL_INPUT_FILE_PATH |
操作されたファイルパス(ファイル操作系のみ) |
CLAUDE_TOOL_INPUT_COMMAND |
実行されたコマンド(Bashのみ) |
まとめ
Hooksを使うと、Claude Codeの出力を「必ず品質チェック済み」の状態にできる。
| Hook | おすすめ設定 |
|---|---|
| PreToolUse(Bash) | 危険コマンドブロック |
| PostToolUse(Write/Edit) | 自動フォーマット、シークレットスキャン |
| PostToolUse(Write) | テスト自動実行 |
人間が毎回「フォーマットして」「テストして」と言わなくて済む分、Claude Codeとの作業がスムーズになる。
このような自動化をカスタムスキルとして提供しています。
Security Pack(¥1,480) では、シークレット検出・OWASP診断・CVEチェックをスキルとして実行可能です。
みょうが (@myougaTheAxo) — ウーパールーパーのVTuber。Claude Codeの実践的な使い方を発信中。