Claude Code Hooksでテストを自動実行する方法:PostToolUse、Stop、最小検証フロー

Claude Code Hooksでテストを自動実行する実践ガイド。PostToolUseとStopの使い分け、ファイル種別ごとの最小テストコマンド、毎回フルテストを走らせないための設計を整理します。

Claude Code hooksでテストを自動実行すると、「CLAUDE.mdにテスト実行を書いたのに忘れる」「小さな変更で大きすぎるテストを走らせる」「失敗ログを雑に要約する」といった問題を減らせます。

Hooksの価値は、「覚えておいてほしい」を「そのイベントが起きたら必ず実行する」に変えることです。テスト用途でよく使うのは PostToolUseStop です。

結論

Claude Codeがファイルを編集した直後に軽いチェックを走らせたいなら、PostToolUse を使い、matcherを Edit|Write に絞ります。

Claude Codeがターンを終える前に最終確認したいなら、Stop が向いています。ただし、最初からフルテストを入れない方が安全です。

安定した構成は次のようになります。

  1. PostToolUse は軽量チェックだけを担当する。
  2. Stop は最終リマインドや狭い検証だけを担当する。
  3. 失敗時は重要なログだけを返す。
  4. 設定は .claude/settings.json、実処理は .claude/hooks/ に置く。
  5. まず小さなリポジトリで試す。

何を自動実行するか決める

最初から次のようにしない方がよいです。

1
npm test

編集に近い場所で実行するチェックほど、短く、決定的で、再現可能であるべきです。

場面 推奨チェック
フロントエンドコンポーネント変更 関連単体テスト、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が動かない場合:

  1. Claude Codeで /hooks を確認する。
  2. settings.json が正しいJSONか確認する。
  3. PostToolUseStop の名前を確認する。
  4. matcherが Edit|Write などに合っているか確認する。
  5. スクリプトパスを確認する。
  6. macOS/Linuxでは実行権限を確認する。
  7. WindowsではPowerShellの実行ポリシーと引用符を確認する。
  8. まず echo hook fired だけを出す。
  9. 最初から複雑なテストを接続しない。
  10. 出力が長い場合は要約にする。

まとめ

Claude Code hooksでテストを自動実行するポイントは、npm test を設定に入れることではなく、検証を小さく分けることです。

編集後は PostToolUse で軽量チェック、終了前は Stop で最終確認、フルテストはCIまたは手動確認へ。原則は CLAUDE.md、実行は .claude/hooks/ に分けると、安定して運用できます。

记录并分享
Hugo で構築されています。
テーマ StackJimmy によって設計されています。