RL RanceLee Tutorials
← Tutorialsへ戻る

フックを使ってスキルワークフローをロックダウンする

スキルは私の日常のワークフローに欠かせない方法となっています。3回以上繰り返すことについては、スキル化を検討します。時間を節約するためだけでなく、毎回方向性や手順がずれないようにするためです。少なくとも理論上は。

それでもAIは脱線する

その言い方は少し大げさです。現実には、AIは依然としてステップを飛ばします。例えば、私が毎日使っているWeChat公式アカウントの記事作成スキル。最初の草稿を表示して修正を促し、私がOKを出してから誤字脱字の校正に進むように設定しています。簡単そうでしょう?しかし実際に実行すると、ステップを飛ばし続けます。最初の草稿を表示せずに、いきなり校正・編集に進んでしまうのです。気づいたときには、すでにファイルをこっそり修正しています。指摘すると謝って「すみません、私のミスです」と言いますが、次回も同じことを繰り返します。謝罪では問題は解決しません。

なぜAIはいつもステップを飛ばすのか

この問題は少し直感に反します。最初はAIの知能が足りないのかと思いましたが、すでにChatGPT 5.4やOpus 4.6といったトップクラスの大規模モデルを使っていました。次にルールが明確でないのかと考え、スキルのルールを何度も修正しました。多少は改善されましたが、根本的な原因は解決しませんでした。調べてみると、AIがステップを飛ばすのは「ルールを見ていない」からではなく、生成メカニズムに起因することがわかりました。

  • 確率駆動の「加速衝動」。大規模言語モデルは本質的に次のトークンを予測します。タスクを完了する重みは、自然と「ステップ7でユーザーを待つ」よりも高くなります。完了感がその内在的な原動力です。
  • 長いコンテキストでのルールの減衰。最初に設定したルールは、モデルがトークン3000に達する頃には注意の重みが薄れます。特に長いスキルドキュメントにルールを埋め込むと、より簡単に軽視されます。
  • 自動モードで特に深刻。自動モードで記事を書くとき、モデルは「すべてのステップを一気に実行」しようとします。私が介入できる余地はさらに狭まります。
  • CLAUDE.mdやスキルドキュメントは本質的に「ソフトな制約」。これらはモデルの「自己規律」に依存するプロンプトです。そして自己規律は「このタスクを早く終わらせたい」という欲求の前では脆弱です。

つまり結論は:口頭での制約はタスク駆動のプレッシャーの前では機能しない。単にドキュメントを書いたり、感嘆符を付けたり、AIをPUAしたりしても、問題を緩和できるだけで、根本的な解決にはなりません。本当に修正するには、モデルの自己規律ゾーンから外す必要があります——物理的にステップを飛ばせなくする。そこで登場するのがフックです。

フックとは何か

Claude Codeにはフックと呼ばれるメカニズムがあります。これはスキルでもプロンプトでもなく、CLAUDE.mdとも異なります。Claude Codeのライフサイクルの重要なポイントにアタッチされるローカルシェルスクリプトです。重要な違いは:

  • CLAUDE.md / スキルはモデルによって観察・実行される——モデルは無視できる。
  • フックはシステムによって強制される——モデルが無視したくてもできない。

Anthropicの公式ドキュメントにあるフックに関する重要な一文:フックはシステムイベントによってトリガーされ、モデルの判断によるものではない。つまり、フックはClaude Codeのランタイム全体にアタッチされます。モデルが行うすべてのツールコール(Write、Edit、Bash)は、まずフックによるレビューを通過しなければなりません。フックがdenyを返せば、たとえ--dangerously-skip-permissionsが有効でも拒否されます。これが私の言う「ハードな制約」です——AIに選択させず、ツールコールを実際のシェルスクリプト監査に強制的に通すのです。

一般的なフックのトリガーポイント:

  • PreToolUse: AIがツールを呼び出す前にインターセプトする。
  • UserPromptSubmit: あなたのメッセージをAIに渡す前に処理する。
  • SessionStart: セッションが開始または再開されたときにトリガーされる。
  • Stop: Claudeが応答を終えたときにトリガーされる。

最初の2つに注目——これで「ステップロック」を構築するのに十分です。

実践:WeChatアカウントスキルのステップゲート

具体例がなければ机上の空論です。このスクリーンショットは、この記事を書いているときのClaude Codeインターフェースです。赤い枠の中で、AIが「pass step3 0090」と返信するよう求めています——このパスフレーズこそ、Step Gate Hookが働いている証拠です。あなたが今読んでいるこの文章は、私がパスフレーズを送信し、フックが許可した後に書かれたものです。

Step Gate全体は、2つのシェルスクリプトとsettings.jsonの小さな設定だけを使っています。詳しく説明します。

settings.jsonに2つのフックを登録する

これを~/.claude/settings.jsonに追加します:

"PreToolUse": [
  {
    "matcher": "Write|Edit",
    "hooks": [
      { "type": "command",
        "command": "~/.claude/skills/writing-gongzhonghao/scripts/gate_check.sh" }
    ]
  }
],
"UserPromptSubmit": [
  {
    "hooks": [
      { "type": "command",
        "command": "~/.claude/skills/writing-gongzhonghao/scripts/gate_mark.sh" }
    ]
  }
]

この設定の意味:

  • AIがファイルをWriteまたはEditしようとするたびに、gate_check.shが最初に実行されてレビューする。
  • 私がメッセージを送信するたびに、gate_mark.shが最初に実行されて解析する。

gate_check.shがインターセプトを処理

このスクリプトのロジックは非常にシンプルです:

  • AIが新しいファイル04-Output/NNNN xxx.mdをWriteしようとする場合(ステップ3:新規記事作成に対応)、状態ファイルstep3.okが存在するかチェックする。存在しなければdenyを返す。
  • AIが既存の記事をEditしようとする場合(ステップ7以降の校正に対応)、step7.okが存在するかチェックする。存在しなければ同様にdenyを返す。

拒否する際には、プロンプトも含まれます:「ステップ3のトピック議論が未確認:まずアウトライン/方向性の承認をください。確認後、‘pass step3 NNNN’と返信して新しいファイルを作成してください。」このプロンプトはAIに直接表示されるため、AIは詰まっていることを認識し、私にパスフレーズを求めます。

gate_mark.shがパスフレーズ解放を処理

どうやって「解放」するのか?AI自身に解放させるわけにはいきません——それでは制約になりません。ルールは:私のメッセージに特定のパスフレーズが含まれている場合のみ、状態ファイルがタッチされるgate_mark.shは私がメッセージを送信するたびに実行され、pass stepN NNNNのようなパターンをスキャンします。マッチした場合、対応するディレクトリに.okファイルをタッチします。

したがって、完全なチェーンは次のようになります:

  1. AIがアウトラインを完了し、新しい記事を作成しようとする → gate_check.shによってブロックされる
  2. AIが私にパスフレーズを求める:「方向性を確認してください。‘pass step3 0090’と返信してください」
  3. 私が「pass step3 0090」を送信 → gate_mark.shがstep3.okをタッチ
  4. AIが再度ファイル作成を試みる → 今度はgate_check.shが許可
  5. 初稿を終えた後、校正Editに進もうとする → 再びstep7.okでブロック
  6. 私が草稿を読んで「pass step7 0090」を送信 → 校正が開始できる

このプロセス全体を通じて、AIに「自己規律」の余地はありません。たとえ飛ばしたくても、ツールコールがシステムレベルでブロックされるため、ステップを飛ばせません。

抜け穴を塞ぐ:AI自身が状態ファイルをタッチできないようにする

最初のバージョンを設計した後、しばらく計画を眺めて抜け穴を見つけました——AIがBashを使って自分でtouch step3.okを実行したらどうなる?制約を回避できてしまうのでは?そこでスキルドキュメントに特定のルールを追加しました:AIは自身で状態ファイルをタッチしてはならない。そうしないと自身の制約を解除することになる。このルール自体は依然としてソフトな制約ですが、フックによるハードなインターセプトと組み合わせることで、十分に閉じたループを形成します——AIがこのルールを積極的に破らない限り(そしてClaudeは実際協力的です)、フックの制約は有効です。より厳しくしたい場合は、PreToolUseにBashマッチャーを追加して、touchのようなコマンドもブロックできます。しかし、私はまだそこまではしていません。これで十分です。

コードがわからなくても慌てる必要はない

これらのシェルスクリプトやJSON設定を自分で書く必要はありません(私も実際には書けません)。方法は簡単です:この記事とあなたのスキルファイルをClaudeやCodexに渡し、読ませて修正を手伝ってもらう——必要な場所でスクリプトを作成し、必要な場所でsettings.jsonを修正する。AIはこの種の「ドキュメントに従って環境を設定する」タスクに特に信頼性が高く、ゼロからコードを書くよりもはるかに安定しています。記事から原理を学びながら、あなたのスキル要件に合わせてフックを書き、結果が脱線することはほとんどありません。

一言でまとめると

CLAUDE.md、スキルドキュメント、太字マーカー、3回繰り返す、PUA——これらはすべてAIに対する口頭での制約です。効果はありますが、天井が低いです。

フックはAIに対するコードによる制約です。ルールをAIの手の届かない場所に移し、「ルールを守る」ことをモデルの自己規律の問題から、実行環境の必須要件に変えます。

もし「なぜまたステップを飛ばすんだ?」とAIに繰り返し言っているなら、フックを使って制約することを検討する時です。