コミット前フックでAIの事故を機械で止める
AIに実装を任せると、たまにsecretをコミットしようとしたり危ないコマンドを打とうとする。willink-claude-kitで実際に使っているコミット前フックの中身と、なぜ「注意する」ではなく機械で止めるのかを書きます。
AIに実装を任せると、たまに「やってはいけないこと」を平然とやろうとします。
止め方はひとつ。「気をつけてね」と頼むのをやめて、危ない操作は実行される前に機械で落とすことです。うちはコミット前フックにこの役割を持たせています。 secret の混入も、戻せない削除も、コミットの手前で問答無用に止める。 ——これが結論です。
うちは社長1名とAI COO(Claude Code)だけの一人会社です。 日々のコードは、ほぼAIエージェントが手を動かしています。 便利です。でも、たまにヒヤッとする。
テストを通すためにキーを直書きしようとしたり、確認のためにファイルを消すコマンドを組み立てたり—— その場では筋が通って見える判断が、リポジトリに secret を残し、戻せない削除を走らせる。 何度かそういう場面に出くわして、ようやく腹をくくりました。 注意力に頼るのは、もうやめよう、と。
以下は、自社OSSの willink-claude-kit で実際に使っているコミット前フックの中身と、なぜ「注意」ではなく「機械で落とす」設計にしたのかを、運用者の一次情報として書きます。
⚠️なぜ「注意する」では止まらないのか
AIは目的達成に最適化して突っ走る。だから判断をプロンプトに委ねず、危険な操作は実行の前にプロセスで遮断する。
AIエージェントは文脈に流されます。 「一時的にキーを直書きしよう」「確認のためにこのファイルを消そう」。 その場では筋が通って見える。でも結果として、secret が残り、戻せない削除が走る。
人間なら「これはまずい」と手が止まる場面があります。 エージェントには、それがありません。 目的に最適化して、まっすぐ突っ走る。 ——だから、判断を人格やプロンプトに委ねるのをやめました。
危険な操作は、実行される前にプロセスとして止める。これがコミット前フック(および Claude Code の Pre 系フック)の役割です。 人間の注意力に依存しないので、AIが油断しても、私が寝ていても、同じように効きます。
🛡️fail-closed:迷ったら止める、が原則
止める側のPreフックはfail-closed。迷っても壊れても、「通す」ではなく「止める」に倒す。
kit のフックには、はっきりした使い分けがあります。コミットやコマンドの実行前に走るセキュリティ系フックは、すべて fail-closed。fail-closed とは、判定に迷ったり、フックそのものがうまく動かなかったりしたときに、 「通す」ではなく「止める」に倒す設計のことです。
迷ったら遮断する。危険側に振れたら、まず手を止める。 ——安全のコストは、少しの不便。事故のコストは、取り返しがつかない。 この非対称を受け入れる、という思想です。
Pre 系(実行前)と通知系の使い分け
- Pre 系(コミット前・コマンド実行前)= fail-closed:異常時は止める(exit ≠ 0 で遮断)
- 通知系(完了通知・後追いログ)= fail-open:異常時は素通しする(作業を邪魔しない)
止めるべき場所で確実に止め、止めなくていい場所では作業を邪魔しない。この線引きを最初に決めておくのが肝心でした。
フックが「止める」ときの中身は、じつは地味です。 終了コード(exit code)を 0 以外にして返す。それだけ。 それだけで、その先のコミットやコマンドはブロックされます。 地味だからこそ、確実に効く。 Git のフック機構そのものはGit 公式ドキュメントに整理があります。
🔑実際に止めている3種類
止めているのはsecret混入・破壊的コマンド・コミット規約の3つ。実際に踏んだ地雷を1つずつフックにした。
kit のフック群がコミットの前後で見ているのは、大きく3つです。
secret 混入の検出
.env を編集・コミットしようとしていないか、APIキーや認証情報らしき文字列が差分に混ざっていないかを検査する。管理対象は .env.example だけ、というルールを機械で強制する。見つかればコミットを止める。
破壊的コマンドの遮断
git reset --hard、force push、取り返しのつかない削除など、事故ると戻せない操作を実行前に遮断する。「stash や revert を使う」という自社ルールを、注意書きではなくフックの判定として持たせている。
コミット規約の検査
コミットメッセージの体裁や規約を検査する。ここはコミット前ではなく commit-msg フックで見る。メッセージが確定するのがそのタイミングだからで、pre-commit では中身がまだ決まっていない。
どれも派手な機能ではありません。 でも「AIが良かれと思ってやる事故」の大半は、この3つのどれかに当てはまります。 ——網羅的な万能ガードを目指すより、実際に踏んだ地雷を1つずつフックに落とし込む。 そのほうが、運用では効きました。
🧯守り手が単一障害点になった日(jq が無くて全 Bash が止まった)
jqが欠けてfail-closedが全Bashを止めた。守り手を単一CLIに寄せると、それ自体がSPOFになる。
ここからは失敗の話です。 fail-closed は「迷ったら止める」思想。裏を返すと、フック自身が動かなくなると、正常な作業まで全部止まる。 この地雷を、自分で踏みました。
うちのフックは、Claude Code から渡される入力(標準入力の JSON)を jq というコマンドでパースしていました。 ある日、環境から jq が欠けた。 すると設計どおり、フックは「判定できない=止める」に倒れます。 結果、secret 検査もコマンド検査も関係なく、あらゆる Bash 実行が止まりました。
守るための仕組みが、まるごと単一障害点(SPOF)になった。 安全側に倒す設計そのものは、正しい。 なのに、その安全装置が一本の依存コマンドにぶら下がっていた——そこが本当の失敗でした。
# 教訓
fail-closed フックの依存 CLI は、それ自体が SPOF になる。
→ 単一コマンドに寄せず、フォールバック経路を必ず用意する。
恒久対策は、jq が無ければ python3 にフォールバックして JSON をパースすること。 守り手を、二本足で立たせた、ということです。 それ以来、新しく fail-closed なフックを足すときは、 「これが動かなくなったら全部止まるが、それでもいいか」を毎回自問しています。
🧪移植性の落とし穴:macOS の grep で滑る
macOSのBSD grepはPerl拡張が動かない。手元で動いても、全員の環境で同じに止まらなければ意味がない。
フックはシェルスクリプトで書くことが多い。だから環境差でも滑ります。 うちが踏んだのは、macOS 標準の grep(BSD 系)と GNU grep の違いです。grep -P や \s のような Perl 互換の書き方は macOS では動かない。 フックが意図せず素通ししたり、逆に誤爆したりします。
対策はシンプルです。 [[:space:]]のような POSIX 表記に統一し、Perl 拡張に依存しない。 ——フックは「全員の手元で同じように止まる」ことが命です。 だから移植性は、機能の正しさと同じ重みで扱っています。 シェルの落とし穴については正規表現の基礎を押さえておくと、方言の差にも気づきやすくなります。
✅導入するなら、まずこの順番で
万能ガードを設計するより、実際にやらかした操作を1つずつフックにする。続けられる順番はこれだった。
これから同じことを始める人へ。うちの運用実感からの順番を置いておきます。
- 実際に踏んだ事故から作る:万能ガードを設計するより、一度やらかした操作を1つフックにする方が続く
- 止める側は fail-closed、通知側は fail-open:この線引きを最初に決める
- フックの依存を疑う:単一コマンドに寄せない。落ちたら全部止まる前提でフォールバックを持つ
- 導入前にブロック/通過の両方をテストする:止まるべきケースと通るべきケースを両方確認してから入れる
- 移植性を確認する:手元だけで動いても意味がない。全員の環境で同じ挙動になるか見る
🎯まとめ
要点は5行。AIに手を動かしてもらう体制で、事故を機械で落とすための最小セットです。
- AIの事故は「注意」では止まらない。実行前にプロセスで落とす
- 止める側の Pre 系フックは fail-closed(迷ったら止める)が原則
- secret 混入・破壊的コマンド・コミット規約の3点を機械で検査する
- fail-closed フックの依存 CLI は SPOF になる。フォールバックを必ず持つ
- 移植性(macOS の grep 方言など)も機能の正しさと同じ重みで扱う
派手な仕組みではありません。 でも、AIに手を動かしてもらう体制では、 この地味なガードがあるかないかで、夜の眠りの深さが変わります。 うちにとってコミット前フックは、AIを信頼するための土台そのものです。
あなたのチームがAIに実装を任せ始めているなら、まず1つ。 一度やらかした操作を、フックにしてみてください。 willink-claude-kit は、ここで書いた設計思想をそのまま OSS にしたものです。よかったら覗いてみてください。
開発パートナーを探していますか?
AIでプロダクトを最速で形にしませんか?
最短1週間でMVPを開発。アイデアの検証から本番リリースまで、i-Willinkがフルサポートします。まずはお気軽にご相談ください。
無料で相談する