Claude Code in Action 後編:HooksとSDKで開発を自動化する

Claude Code in Action 後編:HooksとSDKで開発を自動化する

1. Claudeの挙動を制御する「Hooks」

Hooks(フック)とは、Claudeがツール(ファイルの読み書きなど)を実行する前後に、特定のスクリプトを割り込ませる機能です。主に2つのタイプがあります。

  • PreToolUse: ツール実行に動作。条件に応じて実行をブロックできます。
  • PostToolUse: ツール実行に動作。実行結果に応じたフォローアップ(整形など)が可能です。

設定ファイルの場所

Hooksは以下の設定ファイルに記述します。

  1. グローバル: ~/.claude/settings.json(全プロジェクトに適用)
  2. プロジェクト共有: .claude/settings.json(チームで共有)
  3. プロジェクト個人: .claude/settings.local.json(自分専用)

他にもこのようなものもあります

  • Notification(通知): Claude Code が通知を送信したときに実行されます。
    これは、Claude がツール使用の許可を求めたとき、または 60 秒間アイドル状態が続いた後に発生します。
  • Stop: Claude Code が応答を完了したときに実行されます。
  • SubagentStop: サブエージェント(UI 上では「Task」として表示される)が完了したときに実行されます。
  • PreCompact: コンパクト処理(手動または自動)が実行される前に実行されます。
  • UserPromptSubmit: ユーザーがプロンプトを送信したとき、Claude が処理する前に実行されます。
  • SessionStart: セッションを開始または再開したときに実行されます。
  • SessionEnd: セッションが終了したときに実行されます。

2. 【実践】機密ファイルを保護するHookの作成

例えば、Claudeに .env ファイルを絶対に読み取らせたくない場合、PreToolUse フックが有効です。

設定例(settings.json)

"PreToolUse": [
  {
    "matcher": "Read",
    "hooks": [
      {
        "type": "command",
        "command": "node /home/hooks/check_env.ts"
      }
    ]
  }
]

スクリプトのロジック(check_env.ts)

async function main() {
  const chunks = [];
  for await (const chunk of process.stdin) {
    chunks.push(chunk);
  }
  
  const toolArgs = JSON.parse(Buffer.concat(chunks).toString());
  
  // Extract the file path Claude is trying to read
  const readPath = 
    toolArgs.tool_input?.file_path || toolArgs.tool_input?.path || "";
  
  // Check if Claude is trying to read the .env file
  if (readPath.includes('.env')) {
    console.error("You cannot read the .env file");
    process.exit(2);
  }
}

標準入力から渡されるJSONを解析し、パスに .env が含まれていれば process.exit(2) で終了させます。これにより、Claude側にはエラーが返り、アクセスを未然に防ぐことができます。

Hooksのメリット:

  • 能動的な保護: 読み取られる前にブロック。
  • 透明性: なぜ失敗したのかをClaudeが理解し、次のアクションに活かせる。
  • 柔軟性: ファイル命名規則のチェックや、特定のディレクトリの編集禁止など、用途は多岐にわたります。

3. Hooksを効率よく開発するコツ

Claudeがツールを使おうとすると、 フックに JSONデータ(stdin) が渡されます。特に MCPサーバーを追加すると増えため、使えるルールは確認するようにしましょう。

Hooksに渡されるデータ構造も、実行されるツールによって異なります。中身が分からず開発が止まってしまう時は、以下の「デバッグ用Hook」を試してみてください。

"matcher": "*",
"hooks": [
  {
    "type": "command",
    "command": "jq . > debug-log.json"
  }
]

これで、Claudeが実行しようとした生データが debug-log.json に出力されるため、スクリプトが参照すべきプロパティを一目で確認できます。

例えば、フックに渡される stdin 入力のサンプルを見てみましょう。
ここでは、TodoWrite ツールの使用を監視している PostToolUse フックの例です。

参考までに、TodoWrite は Claude が ToDo 項目を管理するために使用するツールです。

{
  "session_id": "9ecf22fa-edf8-4332-ae85-b6d5456eda64",
  "transcript_path": "<path_to_transcript>",
  "hook_event_name": "PostToolUse",
  "tool_name": "TodoWrite",
  "tool_input": {
    "todos": [
      {
        "content": "write a readme",
        "status": "pending",
        "priority": "medium",
        "id": "1"
      }
    ]
  },
  "tool_response": {
    "oldTodos": [],
    "newTodos": [
      {
        "content": "write a readme",
        "status": "pending",
        "priority": "medium",
        "id": "1"
      }
    ]
  }
}

比較として、こちらは Stop フックに渡される入力の例です。

{
  "session_id": "af9f50b6-f042-4773-b3e2-c3a4814765ce",
  "transcript_path": "<path_to_transcript>",
  "hook_event_name": "Stop",
  "stop_hook_active": false
}

4. セキュリティとポータビリティの両立

Claude Codeでは、セキュリティ上の理由からHookスクリプトの指定に絶対パスを使うことが推奨されています。しかし、開発者ごとにディレクトリ構造が異なると、設定ファイルを共有しづらくなります。

これを解決するのが settings.example.json を活用した運用です。 パスの部分を $PWD/scripts/hook.ts のように記述しておき、セットアップ時に環境に合わせて絶対パスへ置換・コピーする運用にすることで、「安全な絶対パス」と「チームでの設定共有」を両立できます。


5. Claude Code SDKでAIをワークフローに組み込む

Claude Code SDKを使えば、ターミナルからではなく、自分のプログラム(TypeScript/Python)から直接Claude Codeの機能を呼び出せます。

権限の管理

デフォルトでは読み取り専用ですが、allowedTools: ["Edit"] オプションを追加することで、AIによる自動修正を許可できます。

推奨される活用シーン

  • Git Hooks: コミット時にAIが自動でコードレビューを行う。
  • CI/CD: パイプラインにおけるコード品質チェック
  • ドキュメント生成: ソースコードの変更を検知してREADMEを自動更新する。
  • コーディング: コード保守作業のためのヘルパーコマンド

まとめ

Claude CodeのHooksとSDKは、開発者の「こだわり」や「プロジェクトのルール」をAIにコードレベルで叩き込むためのツールです。

  • Hooksでガードレールを敷き、安全に開発をサポートさせる。
  • SDKで定型的なレビューやメンテナンスを自動化する。

これらを組み合わせることで、開発効率は次のステージへと進むはずです。ぜひあなたのプロジェクトにも導入してみてください。