Claude Code hooksでテストを自動実行すると、「CLAUDE.mdにテスト実行を書いたのに忘れる」「小さな変更で大きすぎるテストを走らせる」「失敗ログを雑に要約する」といった問題を減らせます。
Hooksの価値は、「覚えておいてほしい」を「そのイベントが起きたら必ず実行する」に変えることです。テスト用途でよく使うのは PostToolUse と Stop です。
結論
Claude Codeがファイルを編集した直後に軽いチェックを走らせたいなら、PostToolUse を使い、matcherを Edit|Write に絞ります。
Claude Codeがターンを終える前に最終確認したいなら、Stop が向いています。ただし、最初からフルテストを入れない方が安全です。
安定した構成は次のようになります。
PostToolUse は軽量チェックだけを担当する。
Stop は最終リマインドや狭い検証だけを担当する。
- 失敗時は重要なログだけを返す。
- 設定は
.claude/settings.json、実処理は .claude/hooks/ に置く。
- まず小さなリポジトリで試す。
何を自動実行するか決める
最初から次のようにしない方がよいです。
編集に近い場所で実行するチェックほど、短く、決定的で、再現可能であるべきです。
| 場面 |
推奨チェック |
| フロントエンドコンポーネント変更 |
関連単体テスト、typecheck、lint |
| バックエンド関数変更 |
関連 package の単体テスト |
| 設定ファイル変更 |
設定検証、build dry run |
| Markdown変更 |
リンクまたはfront matterチェック |
| ターン終了前 |
最小検証のリマインド |
| コミットやリリース前 |
フルテストとビルド |
HooksはCIの代替ではありません。Claude Codeが低レベルなミスに気づくためのローカル安全網です。
推奨ディレクトリ構成
複雑な処理を settings.json の1行に詰め込まないでください。
1
2
3
4
5
6
|
your-repo/
.claude/
settings.json
hooks/
run-related-tests.sh
final-check.sh
|
Windows中心ならPowerShellでも構いません。
1
2
3
4
5
6
|
your-repo/
.claude/
settings.json
hooks/
run-related-tests.ps1
final-check.ps1
|
PostToolUseで編集後にチェックする
PostToolUse はツール呼び出しの後に発火します。自動テストでは、通常ファイルを書き込むツールだけを対象にします。
.claude/settings.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/run-related-tests.sh"
}
]
}
]
}
}
|
この設定はhook登録だけを行います。実際の判定はスクリプト側に置きます。
Bashスクリプト例
.claude/hooks/run-related-tests.sh:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#!/usr/bin/env bash
set -euo pipefail
INPUT="$(cat)"
FILE_PATH="$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty')"
if [ -z "$FILE_PATH" ]; then
exit 0
fi
case "$FILE_PATH" in
*.ts|*.tsx)
echo "Running TypeScript checks for $FILE_PATH"
npm run typecheck -- --pretty false
;;
*.test.ts|*.spec.ts|*.test.tsx|*.spec.tsx)
echo "Running focused test for $FILE_PATH"
npm test -- "$FILE_PATH" --runInBand
;;
*.py)
echo "Running Python checks for $FILE_PATH"
python -m pytest -q
;;
*.md)
echo "Markdown changed: skip code tests"
;;
*)
echo "No related test rule for $FILE_PATH"
;;
esac
|
実行権限を付けます。
1
|
chmod +x .claude/hooks/run-related-tests.sh
|
この例は保守的です。フルテストを走らせず、ログも長くしません。
PowerShell版
.claude/hooks/run-related-tests.ps1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
$inputJson = [Console]::In.ReadToEnd()
if ([string]::IsNullOrWhiteSpace($inputJson)) {
exit 0
}
$payload = $inputJson | ConvertFrom-Json
$filePath = $payload.tool_input.file_path
if ([string]::IsNullOrWhiteSpace($filePath)) {
exit 0
}
switch -Regex ($filePath) {
'\.tsx?$' {
Write-Output "Running TypeScript checks for $filePath"
npm run typecheck -- --pretty false
break
}
'\.(test|spec)\.tsx?$' {
Write-Output "Running focused test for $filePath"
npm test -- $filePath --runInBand
break
}
'\.py$' {
Write-Output "Running Python checks for $filePath"
python -m pytest -q
break
}
'\.md$' {
Write-Output "Markdown changed: skip code tests"
break
}
default {
Write-Output "No related test rule for $filePath"
}
}
|
対応する設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "powershell.exe -ExecutionPolicy Bypass -File \"$CLAUDE_PROJECT_DIR/.claude/hooks/run-related-tests.ps1\""
}
]
}
]
}
}
|
PowerShellでは引用符とパスが壊れやすいので、まず通常のターミナルでスクリプトを試してください。
失敗ログは短くする
hookの出力はClaude Codeの作業コンテキストに入ります。失敗ログが長すぎると、コンテキストを圧迫します。
1
|
npm test -- "$FILE_PATH" --runInBand 2>&1 | tail -n 80
|
hookには決定的なコマンドだけを置き、対話入力や手動確認が必要な処理は避けます。
Stopで最終チェックする
PostToolUse は編集直後のチェック向けです。Stop は「このターンが終わる前に確認する」用途に向いています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/final-check.sh"
}
]
}
]
}
}
|
.claude/hooks/final-check.sh:
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/usr/bin/env bash
set -euo pipefail
if git diff --quiet; then
echo "No working tree changes. Skip final checks."
exit 0
fi
echo "Working tree changed. Suggested final checks:"
echo "- run the focused test command for touched files"
echo "- run typecheck if code changed"
echo "- run full test suite before commit or deploy"
|
まずはリマインドだけにして、問題がなければ徐々に自動化を増やします。
自動実行しない方がよい場面
次の場合は注意が必要です。
- テストが遅い。
- データベース、ブラウザ、外部APIが必要。
- テストがローカルデータを変更する。
- ログが非常に大きい。
- 安定した最小テストコマンドがない。
- Claude Codeが大量のファイルをまとめて編集する。
この場合は実行ではなく、推奨コマンドの提示から始めるのが安全です。
リスクで分ける
| リスク |
自動化する動作 |
| 低 |
format、単一ファイルlint、Markdownチェック |
| 中 |
typecheck、関連単体テスト、設定検証 |
| 高 |
フルテスト、E2E、build、migrationチェック |
低リスクは PostToolUse、高リスクはCIまたは人間の確認に回します。
CLAUDE.mdとの分担
CLAUDE.md には原則を書きます。
1
2
3
|
変更後は最小の関連テストを優先する。
テスト失敗時は回避せず原因を直す。
ユーザーが要求しない限り、小さな変更で全量E2Eを走らせない。
|
Hooksには実行を書きます。
1
2
|
EditまたはWriteの後にrun-related-tests.shを実行する。
Stop時に最終チェック候補を出す。
|
トラブルシュート
hookが動かない場合:
- Claude Codeで
/hooks を確認する。
settings.json が正しいJSONか確認する。
PostToolUse や Stop の名前を確認する。
- matcherが
Edit|Write などに合っているか確認する。
- スクリプトパスを確認する。
- macOS/Linuxでは実行権限を確認する。
- WindowsではPowerShellの実行ポリシーと引用符を確認する。
- まず
echo hook fired だけを出す。
- 最初から複雑なテストを接続しない。
- 出力が長い場合は要約にする。
まとめ
Claude Code hooksでテストを自動実行するポイントは、npm test を設定に入れることではなく、検証を小さく分けることです。
編集後は PostToolUse で軽量チェック、終了前は Stop で最終確認、フルテストはCIまたは手動確認へ。原則は CLAUDE.md、実行は .claude/hooks/ に分けると、安定して運用できます。