Build This Now
Build This Now
キーボードショートカットステータスラインガイド
フックガイドClaude Code クロスプラットフォームフックClaude Code セットアップフックストップフック自己検証する Claude Code エージェントClaude Code セッションフックClaude Code コンテキストバックアップフックスキルアクティベーションフックClaude Code パーミッションフック
speedy_devvkoen_salo
Blog/Toolkit/Hooks/Stop Hooks

ストップフック

ストップフックはテストが失敗、ビルドが壊れている、またはlintがエラー状態のうちはClaude Codeがターンを終了するのをブロックする。4つの強制パターンとループ保護のセーフガード。

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

Published Feb 25, 2026Toolkit hubHooks index

問題: Claudeがレスポンスをまとめるが、作業は実際には終わっていない。テストはまだ失敗している。ファイルは半分しか書けていない。「終わった?」と聞くと「はい」と答えるが、ビルドはレッドのままだ。

即効策: このストップフックを追加すれば、テストがグリーンになるまでClaudeはターンを終了できなくなる:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python .claude/hooks/test-gate.py"
          }
        ]
      }
    ]
  }
}
#!/usr/bin/env python3
import json
import sys
import subprocess
 
input_data = json.load(sys.stdin)
 
# CRITICAL: Prevent infinite loops
if input_data.get('stop_hook_active', False):
    sys.exit(0)
 
# Run tests
result = subprocess.run(['npm', 'test'], capture_output=True, timeout=60)
 
if result.returncode != 0:
    output = {
        "decision": "block",
        "reason": "Tests are failing. Fix them before completing."
    }
    print(json.dumps(output))
    sys.exit(0)
 
sys.exit(0)

これ以降、Claudeはテストスイートが失敗した状態でターンを閉じることが文字通りできなくなる。

ストップフックの仕組み

Claudeがレスポンスを終了しようとするたびにこのフックが発火する。起こりうることは3つ:

  1. 停止を許可 - Exit 0で終了し、ターンが正常に終わる。
  2. 停止をブロック - {"decision": "block", "reason": "..."} を返すと、Claudeが継続する。
  3. バリデーションを実行 - テスト、チェック、任意のスクリプトを起動する。

ペイロード

{
  "session_id": "uuid-string",
  "stop_hook_active": false,
  "transcript_path": "/path/to/transcript.jsonl"
}

stop_hook_active に注意する。trueの場合、Claudeはすでに以前のブロックによる強制継続状態にある。このフラグを見落とすと無限ループになる。

パターン1: テストゲート

すべてのテストが通過するまでターンを開いたままにする:

#!/usr/bin/env python3
import json
import sys
import subprocess
 
input_data = json.load(sys.stdin)
 
if input_data.get('stop_hook_active', False):
    sys.exit(0)
 
result = subprocess.run(
    ['npm', 'test', '--passWithNoTests'],
    capture_output=True,
    timeout=120
)
 
if result.returncode != 0:
    # Extract last 10 lines of test output for context
    stderr = result.stderr.decode()[-500:] if result.stderr else ""
    print(json.dumps({
        "decision": "block",
        "reason": f"Tests failing. Output: {stderr}"
    }))
    sys.exit(0)
 
sys.exit(0)

パターン2: ビルドバリデーション

プロジェクトがコンパイルされるまでブロックする:

#!/usr/bin/env python3
import json
import sys
import subprocess
 
input_data = json.load(sys.stdin)
 
if input_data.get('stop_hook_active', False):
    sys.exit(0)
 
result = subprocess.run(
    ['npm', 'run', 'build'],
    capture_output=True,
    timeout=180
)
 
if result.returncode != 0:
    print(json.dumps({
        "decision": "block",
        "reason": "Build failed. Fix compilation errors before completing."
    }))
    sys.exit(0)
 
sys.exit(0)

パターン3: リントチェック

lintエラーが残ったままターンを終了させない:

#!/usr/bin/env python3
import json
import sys
import subprocess
 
input_data = json.load(sys.stdin)
 
if input_data.get('stop_hook_active', False):
    sys.exit(0)
 
result = subprocess.run(
    ['npx', 'eslint', 'src/', '--max-warnings=0'],
    capture_output=True,
    timeout=60
)
 
if result.returncode != 0:
    print(json.dumps({
        "decision": "block",
        "reason": "Lint errors detected. Run eslint --fix or resolve manually."
    }))
    sys.exit(0)
 
sys.exit(0)

パターン4: タスク完了マーカー

特定のタスクフラグでターンをゲートする:

#!/usr/bin/env python3
import json
import sys
from pathlib import Path
 
input_data = json.load(sys.stdin)
 
if input_data.get('stop_hook_active', False):
    sys.exit(0)
 
# Check for incomplete task marker
marker = Path('.claude/incomplete-task')
if marker.exists():
    task_info = marker.read_text().strip()
    print(json.dumps({
        "decision": "block",
        "reason": f"Task incomplete: {task_info}. Finish it before stopping."
    }))
    sys.exit(0)
 
sys.exit(0)

作業開始時にマーカーを配置する:

echo "Implement user authentication" > .claude/incomplete-task

作業が完了したらクリアする:

rm .claude/incomplete-task

無限ループの防止

stop_hook_active フラグが重要な理由はこれだ。なければこうなる:

Claude responds → Stop hook fires → "block" → Claude continues
                                            ↓
Claude responds → Stop hook fires → INFINITE LOOP (without flag check)

常にフラグを最初に確認する:

if input_data.get('stop_hook_active', False):
    sys.exit(0)  # Allow stopping, break the loop

複数チェックの組み合わせ

1つのフックで複数のゲートを連鎖できる:

#!/usr/bin/env python3
import json
import sys
import subprocess
 
input_data = json.load(sys.stdin)
 
if input_data.get('stop_hook_active', False):
    sys.exit(0)
 
checks = [
    (['npm', 'run', 'lint'], "Lint errors"),
    (['npm', 'run', 'typecheck'], "Type errors"),
    (['npm', 'test'], "Test failures"),
]
 
for cmd, error_msg in checks:
    result = subprocess.run(cmd, capture_output=True, timeout=120)
    if result.returncode != 0:
        print(json.dumps({
            "decision": "block",
            "reason": f"{error_msg} detected. Fix before completing."
        }))
        sys.exit(0)
 
sys.exit(0)

ストップフックを使うべき場面

適切なユースケース:

  • 「タスク完了」前にテストスイートをグリーンにする
  • ビルドが正常にコンパイルされていることを確認する
  • lintやタイプエラーを検出する
  • 自分なりの「完了」の定義に合わせたカスタムルール

適切でないユースケース:

  • 60秒のタイムアウトより長く実行されるもの
  • ネットワークにアクセスしてフレークするチェック
  • 人間の回答が必要なプロンプト(ここではインタラクションできない)

設定

.claude/settings.json に設定する:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python .claude/hooks/stop-validation.py"
          }
        ]
      }
    ]
  }
}

複数のフックを同時に並列で実行できる。いずれか1つから block が返るとClaudeは継続する。

デバッグ

ループにはまった場合

  • スクリプトの先頭で stop_hook_active を読み込んでいるか再確認する
  • ログに記録する: echo "stop_hook_active: $stop_hook_active" >> ~/.claude/stop-debug.log

ブロックが機能しない場合

  • JSONは {"decision": "block", "reason": "..."} の形式でなければならない
  • Exit code 0を使う。2ではない。Exit 2は別のブロックパスに使われる。

テストが長時間実行される場合

  • フックのタイムアウトは60秒
  • より小さなサブセットを実行するか、テストスイートを高速化する

「Ralph Wilgum」パターン

このパターンはコミュニティのテクニックで、ストップフックを使って永続的なタスクループを強制する:

  1. セッション開始時にタスクマーカーを配置する
  2. マーカーが存在する間はストップフックがブロックする
  3. Claudeに完了の証明としてマーカーを削除させる
  4. 作業が残っているのに誤って「完了」と言われることがなくなる

結果: Claudeはベストエフォートから保証された完了にシフトする。

次のステップ

  • メインのフックガイドですべてのフックタイプを確認する
  • コンテキストリカバリーを設定してセッションをコンパクション後も存続させる
  • スキルアクティベーションで自動的なスキル読み込みを設定する
  • 自動承認フローのパーミッションフックを確認する

Continue in Hooks

  • Claude Code セットアップフック
    スクリプト、エージェント、ドキュメントをClaude Codeのセットアップフックに組み合わせる方法。1つのコマンドで決定論的スクリプトを実行し、診断エージェントに出力を渡し、自動更新されるドキュメントを記録する。
  • Claude Code コンテキストバックアップフック
    StatusLineを活用したClaude Codeのコンテキストバックアップフック。10Kトークンごとに構造化されたスナップショットを書き込み、自動圧縮によってエラー文字列・関数シグネチャ・判断内容が失われるのを防ぐ。
  • Claude Code クロスプラットフォームフック
    Claude Codeのクロスプラットフォームフック: .cmd・.sh・.ps1のラッパーを捨て、nodeを直接呼び出すことで、1つの.mjsファイルがmacOS・Linux・Windowsで動く方法。
  • フックガイド
    Claude Code フックの基礎から実践まで: 終了コード、JSON出力、非同期コマンド、HTTPエンドポイント、PreToolUseとPostToolUseのマッチャー、本番環境パターン。
  • Claude Code パーミッションフック
    3階層の Claude Code パーミッションフックをインストールする: 安全な呼び出しは即時許可、危険な呼び出しは即時拒否、グレーゾーンは LLM チェック。スキップフラグ不要。
  • 自己検証する Claude Code エージェント
    自己検証する Claude Code エージェント: PostToolUse リントフック、Stop フック、読み取り専用レビュアーのサブエージェントをエージェント定義に組み込み、不良な出力が出荷されないようにする。

More from Toolkit

  • キーボードショートカット
    Claude Codeのkeybindings.jsonを設定する: 17のコンテキスト、キーストローク構文、コードシーケンス、修飾キーの組み合わせ、デフォルトショートカットを即座に無効化する方法。
  • ステータスラインガイド
    Claude Code のステータスラインにモデル名、gitブランチ、セッションコスト、コンテキスト使用量を表示する方法。settings.json の設定、JSON入力、bash、Python、Node.js スクリプトを解説。
  • AIによるSEOとGEO最適化
    Generative Engine Optimizationの解説: Googleで上位表示されるだけでなく、ChatGPT、Claude、Perplexityの回答内でコンテンツが引用されるようにする方法。
  • 2026年版 Claude Code と Cursor の比較
    2026年の Claude Code と Cursor を並べて比較します。エージェントモデル、コンテキストウィンドウ、料金プラン、そして各ツールが異なる開発ワークフローにどう適合するかを解説します。

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

Claude Code セットアップフック

スクリプト、エージェント、ドキュメントをClaude Codeのセットアップフックに組み合わせる方法。1つのコマンドで決定論的スクリプトを実行し、診断エージェントに出力を渡し、自動更新されるドキュメントを記録する。

自己検証する Claude Code エージェント

自己検証する Claude Code エージェント: PostToolUse リントフック、Stop フック、読み取り専用レビュアーのサブエージェントをエージェント定義に組み込み、不良な出力が出荷されないようにする。

On this page

ストップフックの仕組み
ペイロード
パターン1: テストゲート
パターン2: ビルドバリデーション
パターン3: リントチェック
パターン4: タスク完了マーカー
無限ループの防止
複数チェックの組み合わせ
ストップフックを使うべき場面
設定
デバッグ
「Ralph Wilgum」パターン
次のステップ

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。