作ったのに一度も動いていない安全 hook を炙り出す
実装もテストも揃っているのに設定に未登録で一度も実行されていない hook を、毎セッション自動で検出する。誤検出で無視されなくする条件と、過去の「配線しない」判断を守る台帳まで含む
約4.1万トークンの節約 (API料金換算で約61円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「作ったのに一度も動いていない安全 hook を炙り出す」は、AIのしつけカテゴリのAI指示書(MDファイル)です。実装もテストも揃っているのに設定に未登録で一度も実行されていない hook を、毎セッション自動で検出する。誤検出で無視されなくする条件と、過去の「配線しない」判断を守る台帳まで含むこの巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約4.1万トークン(API料金換算で約61円)・91%のトークンを節約できます。
- カテゴリ
- AIのしつけ
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.5万トークン
- この巻物使用時
- 約4,200トークン
- 節約量
- 約4.1万トークン (約61円)
- 更新日
- 2026-09-14
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/hook-2/raw を読み込んで、この指示書どおりに実装して"
中身
作ったのに一度も動いていない安全 hook を炙り出す
AI エージェント(Claude Code 等)に「やってはいけないこと」を止めさせる hook / gate を 運用していると、実装もテストも揃っているのに設定ファイルへ登録されておらず、一度も 実行されていないものが静かに溜まる。本人も「対策済み」と記録しているので誰も気付かない。
この指示書は、その未配線 hook を毎セッション自動で炙り出す検出器の作り方と、 検出器そのものが無視されるようになる失敗(誤検出による狼少年化・過去の判断の上書き) の避け方をまとめたもの。
1. なぜ既存の「hook 健全性チェック」では見つからないのか
多くの現場には「必須 hook が欠けていないか」を見るチェッカーが既にある。しかしそれは 自分が持つ必須リストに書いてある物しか見ない。つまり:
リストへの追記漏れ(最も起きやすいミス)に対して、構造的に盲目。
hook を新規作成した人がリストに足し忘れると、その hook は永久に不可視になる。 検出は「リストと突き合わせる」のではなく 「ファイルシステム上に存在する hook 候補」を 起点に、設定へ登録されているかを逆引きする 必要がある。
2. 検出ロジック
hook 置き場のファイルのうち、次をすべて満たすものを「未配線」とする。
| # | 条件 | 除外する理由 |
|---|---|---|
| ① | 設定ファイルのどこにもファイル名が現れない | 現れれば配線済み |
| ② | 他の非テストソースから import されていない | ライブラリとして使われている |
| ③ | インストーラでない | export function install や --apply を持つ物は「設置する側」 |
| ④ | hook の形をしている | CLI チェッカーは hook ではない |
条件④の判定が要点
hook は「標準入力から JSON を受け取る」か「hook 用の構造化レスポンスを標準出力へ返す」
かのどちらか。どちらでもない物は --json と終了コードで応答する CLI チェッカーであり、
設定に登録されていなくて当然。
const looksLikeHook = (src) =>
src.includes('process.stdin') || src.includes('hookSpecificOutput');
標準入力の有無だけで判定してはいけない。 実際に、標準入力を直接使わず構造化レスポンス だけを返す hook が存在する。両方を OR で見ること。
3. 実装
import { readFileSync, readdirSync, existsSync } from 'node:fs';
import path from 'node:path';
import os from 'node:os';
const HOME = os.homedir();
const TOOLS = path.join(HOME, '<hook置き場ディレクトリ>');
const SETTINGS = [
path.join(HOME, '<設定ディレクトリ>', 'settings.json'),
path.join(HOME, '<設定ディレクトリ>', 'settings.local.json'),
];
const IGNORE_FILE = path.join(HOME, '<設定ディレクトリ>', 'orphan-gate-ignore.json');
// BOM を落として読む(設定ファイルの BOM でツールの自己更新が数日止まった前例がある)
function readText(file) {
try { return readFileSync(file, 'utf8').replace(/^/, ''); } catch { return ''; }
}
const isGateName = (f) => /(gate|guard)\.mjs$/.test(f) && !f.endsWith('.test.mjs');
const looksLikeHook = (src) => src.includes('process.stdin') || src.includes('hookSpecificOutput');
const isInstaller = (src) =>
/export\s+(async\s+)?function\s+install\b/.test(src)
|| src.includes("'--apply'") || src.includes('"--apply"');
export function findOrphans(toolsDir, settingsText) {
if (!existsSync(toolsDir)) return [];
const files = readdirSync(toolsDir).filter((f) => f.endsWith('.mjs'));
const sources = new Map(files.map((f) => [f, readText(path.join(toolsDir, f))]));
const orphans = [];
for (const f of files.filter(isGateName)) {
if (settingsText.includes(f)) continue; // ①
const importedBy = files.filter(
(o) => o !== f && !o.endsWith('.test.mjs') && sources.get(o)?.includes(f));
if (importedBy.length > 0) continue; // ②
const src = sources.get(f) ?? '';
if (isInstaller(src)) continue; // ③
if (!looksLikeHook(src)) continue; // ④
orphans.push(f);
}
return orphans.sort();
}
function main() {
const settingsText = SETTINGS.map(readText).join('\n');
if (!settingsText.trim()) process.exit(0); // 設定が読めない時は黙る(誤検出を出さない)
let ignored = {};
try { ignored = JSON.parse(readText(IGNORE_FILE) || '{}'); } catch { ignored = {}; }
const orphans = findOrphans(TOOLS, settingsText).filter((f) => !ignored[f]);
if (orphans.length === 0) process.exit(0); // 正常時は完全に無言
console.log([
`[orphan-gate] 未配線の hook が ${orphans.length} 件(実装済みだが設定に未登録=一度も動いていない):`,
...orphans.map((f) => ` - ${f}`),
'いずれかが安全側の検査なら、今この場で設定に登録するか、不要と判断した理由を台帳に記録すること。',
].join('\n'));
process.exit(0);
}
main();
セッション開始イベントに登録する。正常時に無言なのが重要(毎回何か出る検出器は読まれなくなる)。
4. 置き場所 — 同期で消えない場所に置く
共有ルール類を配布している環境では、ツール置き場が上流から定期的にディレクトリごと 上書きされることがある。そこに自作の検出器を置くと次の同期で消える。
- ✅ ユーザー固有の設定ディレクトリ配下(設定ファイルと同じ、同期対象外の場所)
- ❌ 上流から配布・同期されるツールディレクトリ
導入前に「この置き場は同期で上書きされるか」を必ず確認する。
5. 検出器を無視されなくする2つの仕掛け
ここを外すと検出器は数週間で死ぬ。
(a) 誤検出をゼロにする(狼少年化の防止)
名前が -gate / -guard でも hook でない物が必ず混ざる。実際に2種類を誤報した:
- インストーラ — 設定へ hook を書き込む側のスクリプト
- CLI チェッカー —
--jsonと終了コードで応答する定期実行用ツール
1件でも誤報が残ると「またあれか」と読み飛ばされ、本物の未配線が同じ行に埋もれる。 条件③④は快適さのためでなく、検出器を生かすために必須。
(b) 「配線しない」判断を理由付きで残せるようにする
検出器を入れると「毎回警告が出る → 誰かが良かれと思って配線する」圧力が生まれる。 すると過去に検討して意図的に見送った判断が、知らない人に静かに覆される。
実際にこれをやってしまった。「この hook は未配線だから配線すべきだ」と判断して登録したが、 引き継ぎ資料には2度にわたり「上位互換の hook が既にあるので配線しない」と決定済みだった。
対策は、警告を消す正規の経路を同時に用意すること。
{
"<ファイル名>": "<いつ・誰が・なぜ配線しないと判断したか。再検討時に何を実測すべきか>"
}
理由を必須にするのがポイント。ファイル名だけの除外リストにすると、 数ヶ月後に「なぜ除外されているのか分からない」となって結局また配線される。
6. 導入時の検証手順
--selftestを用意し、除外されるケースも検出されるケースも両方入れる (配線済み / 真の未配線 / import されている / インストーラ / 標準入力なしの hook / CLI)- selftest と本体ロジックが同じ関数を通るようにする。テスト内でロジックを再実装すると、 本体に条件を足したときにテストだけ取り残されて検証にならない(実際にやらかした)
- 実環境で1回実行し、出た名前を1件ずつ「本当に hook か」目視で確認する
- 設定ファイルは BOM なし・LF で保存する(BOM で自動更新が数日停止した前例あり)
- 数週間後にもう一度実行し、新しく届いた hook を捕まえられるかを確認する (これが本当の合格条件。導入直後に無言でも意味はない)
7. 効果
導入から13日後、上流から配布された新しい安全 hook が未配線のまま届いたのを、 人が気付く前に検出・配線できた。検出器が無ければ、その hook も 「実装済み・一度も動いていない」の列に加わっていた。
よくある質問
+「作ったのに一度も動いていない安全 hook を炙り出す」とは何ですか?
実装もテストも揃っているのに設定に未登録で一度も実行されていない hook を、毎セッション自動で検出する。誤検出で無視されなくする条件と、過去の「配線しない」判断を守る台帳まで含む
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.5万トークンかかりますが、この巻物を使えば約4,200トークンで済みます。差し引き約4.1万トークン(API料金換算で約61円)・91%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
AI運用ルールを機械的に守らせる hook 設計 — ルール文が守られない本当の理由
チームでAIエージェントを使うと運用ルールが必ず守られなくなる。真因は「読んでいない」ではなく hook がそのマシンで登録されていない/委譲先が沈黙して壊れていること。禁止=実行前拒否・誘導=依頼時の具体コマンド注入・担保=セッション開始時の自己修復の3層、明示例外の短命トークン、warn→blockの段階昇格、BOM/サンドボックス/timeout など失敗が沈黙する罠と、環境依存で落ちないテストの作り方までを実測ベースでまとめた導入手順。
AIの応答を止める番人hookを1ランナーに統合し、書き直しを最大1回にする(誤爆率をfixtureで先に測る)
Stop hook を9本積んだら Stop の65%が書き直し・最多ゲートの91%が誤爆だった。誤爆測定→否定文除外→1プロセス合流→再試行上限統一→全PC移行→KPIで効果確認までの手順。
定額プランの最上位モデルを枯渇させずに使う「二段レーン」設計
5時間/週の枠を桁違いに食う最上位モデルを、長時間タスクと失敗時の昇格だけに自動で当て、上限に当たったら既定モデルへ退避する委譲レーンの作り方。判定は純関数・検証まで含む。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア