Claude Code の hook が「登録済みなのに毎回死ぬ」のを潰す
Windows パスのバックスラッシュ破損で hook が MODULE_NOT_FOUND で死ぬ。JSON として valid・自己点検が名前の部分一致・失敗しても会話が続く、の3層をすり抜けるので放置される。全hookのパス実在を exit code で機械判定する検証スクリプトと、多層エスケープを踏まない修復スクリプト。
約1.3万トークンの節約 (API料金換算で約19円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「Claude Code の hook が「登録済みなのに毎回死ぬ」のを潰す」は、AIのしつけカテゴリのAI指示書(MDファイル)です。Windows パスのバックスラッシュ破損で hook が MODULE_NOT_FOUND で死ぬ。JSON として valid・自己点検が名前の部分一致・失敗しても会話が続く、の3層をすり抜けるので放置される。全hookのパス実在を exit code で機械判定する検証スクリプトと、多層エスケープを踏まない修復スクリプト。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約1.3万トークン(API料金換算で約19円)・83%のトークンを節約できます。
- カテゴリ
- AIのしつけ
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約1.5万トークン
- この巻物使用時
- 約2,500トークン
- 節約量
- 約1.3万トークン (約19円)
- 更新日
- 2026-09-01
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/claude-code-hook/raw を読み込んで、この指示書どおりに実装して"
中身
Claude Code の hook が「登録済みなのに毎回死ぬ」のを潰す(Windows パス破損の検知)
症状
Claude Code が応答を終えるたびに、赤いスタックトレースが出る。
Error: Cannot find module 'C:hooksmy-rules oolsmy-gate.mjs'
code: 'MODULE_NOT_FOUND'
パスの一部が消え、途中にタブのような空白が入っている。hook 自体は settings.json に 「書いてある」のに、node がファイルを見つけられない。
原因
settings.json の hook コマンドに Windows パスを単一のバックスラッシュで書いている。
"command": "node \"C:\hooks\my-rules\tools\my-gate.mjs\""
JSON のパーサはバックスラッシュをエスケープ開始として解釈する:
| 書いたもの | パーサが返すもの |
|---|---|
\h \m \k | h m k(バックスラッシュが消える) |
\t | TAB(1文字) |
\n | 改行 |
\U | U(消える。仕様上は不正だが多くのパーサが黙って落とす) |
結果、意図した C: hooks my-rules tools my-gate.mjs の連結は
C:hooksmy-rules<TAB>oolsmy-gate.mjs という実在しないパスになる。
正しい書き方はバックスラッシュ二重、またはスラッシュ:
"command": "node \"C:\hooks\my-rules\tools\my-gate.mjs\""
"command": "node \"C:/hooks/my-rules/tools/my-gate.mjs\""
なぜ気付けないのか(ここが本題)
この破損は3つの検知層をすべてすり抜ける。
-
JSON として valid。不正なエスケープでもパーサがバックスラッシュを落とすだけなので、 保存時にもロード時にもエラーが出ない。
-
hook の自己点検が名前の部分一致しか見ない。よくある実装はこうなっている:
settings.hooks[event].some(g => g.hooks.some(h => String(h.command||'').includes(scriptName)))パスが壊れていてもファイル名の文字列は残っているので「登録済み」と判定される。
-
hook の失敗は処理を止めない。Claude Code は hook が非ゼロで落ちても会話を続けるので、 赤い出力を読み飛ばすと何ヶ月でも壊れたまま走る。
検知スクリプト(全 hook のパス実在を機械判定)
verify-hooks.mjs として置き、exit code で判定する。
import fs from 'node:fs';
const HOME = process.env.USERPROFILE ?? process.env.HOME;
const CONFIG = process.argv[2] ?? `${HOME}/.claude/settings.json`;
const cfg = JSON.parse(fs.readFileSync(CONFIG, 'utf8'));
let total = 0, bad = 0;
for (const [event, entries] of Object.entries(cfg.hooks ?? {})) {
for (const entry of entries) {
for (const hook of entry.hooks ?? []) {
// node "<path>" 形式の hook だけを対象にする
const m = /^node\s+"([^"]+)"/.exec(hook.command ?? '');
if (!m) continue;
total++;
if (!fs.existsSync(m[1])) {
bad++;
console.log('MISSING', event, '->', JSON.stringify(m[1]));
}
}
}
}
console.log(`node-hooks=${total} missing=${bad}`);
process.exit(bad === 0 ? 0 : 1);
JSON.stringifyでパスを出すのが要点。壊れたパスは素の表示では気付けない (TAB や消えたバックスラッシュが可視化される)。- 目視ではなく exit code で判定する。CI や SessionStart hook に載せられる。
- 自己点検 hook を持っているなら、名前の部分一致にこのパス実在チェックを足す。
修復スクリプト
シェル経由で書かないこと。ここで同じ罠を踏む。
# ダメ: シェルがバックスラッシュをもう1層食う
node -e "...'C:\hooks\my-rules\...'..."
node -e に Windows パスを渡すと、シェル → node → JSON の3層でエスケープが競合する。
必ずスクリプトをファイルに書いて実行し、ファイル内では C:/...(スラッシュ)を使う。
// fix-hook-path.mjs
import fs from 'node:fs';
const HOME = (process.env.USERPROFILE ?? process.env.HOME).replace(/\/g, '/');
const P = `${HOME}/.claude/settings.json`; // スラッシュで書く
const BS = String.fromCharCode(92); // \ を文字コードで作る=エスケープ地獄を回避
const Q = BS + '"'; // ファイル内に現れる \" の並び
const bad = 'node ' + Q + 'C:hooksmy-rules' + BS + 'toolsmy-gate.mjs' + Q;
const good = 'node ' + Q + ['C:', 'hooks', 'my-rules', 'tools', 'my-gate.mjs'].join(BS + BS) + Q;
let s = fs.readFileSync(P, 'utf8');
if (!s.includes(bad)) { console.log('NOT FOUND'); process.exit(2); }
s = s.split(bad).join(good);
JSON.parse(s); // 書く前に妥当性を確認する
fs.writeFileSync(P, s);
console.log('FIXED');
String.fromCharCode(92)でバックスラッシュを組み立てると、ソース上にエスケープが一切現れない。 多層エスケープの読み間違いが原理的に起きなくなる。- 正規表現ではなく
split().join()を使う(パスは正規表現メタ文字の塊なのでエスケープ漏れが起きる)。 - 書く前に
JSON.parseを通す。settings.json を壊すと Claude Code が起動しなくなる。 - 事前にバックアップを取る(
settings.json.bak-<日付>)。
手順
-
node verify-hooks.mjsを実行し、missing=の数を見る(exit code で判定)。 -
MISSING行のJSON.stringify出力を読み、壊れたパスの実際の姿を確認する。 -
バックアップを取る。
-
fix-hook-path.mjsで置換 →JSON.parse検証 → 書き込み。 -
node verify-hooks.mjsを再実行しmissing=0/ exit 0 を確認する。 -
修復した hook 本体に stdin を流して起動まで確認する(パスが通っても中身が落ちる場合がある):
echo '{"hook_event_name":"Stop","session_id":"smoke"}' | node "C:/hooks/my-rules/tools/my-gate.mjs"; echo "exit=$?" -
hook 設定はセッション開始時に読まれるので、直しても現在のセッションでは赤い出力が残る。 「消えない」と判断する前に新しいセッションで確認する。
-
設定を自動生成する installer 側にも同じ壊れた文字列が無いか grep する (あると次の同期で再破損する)。
落とし穴まとめ
- 壊れたパスはJSON として valid なので保存時に気付けない。
- 自己点検がファイル名の部分一致だと壊れたパスを「登録済み」と誤認する。
- hook の失敗は会話を止めないので放置される。
node -eにパスを渡すな。シェルがもう1層食う。スクリプトはファイルに書く。- 検証は目視でなく exit code。壊れたパスは目で見て気付けない。
- 修復後の確認は「パスが実在する」と「hook が起動する」をセットでやる。
よくある質問
+「Claude Code の hook が「登録済みなのに毎回死ぬ」のを潰す」とは何ですか?
Windows パスのバックスラッシュ破損で hook が MODULE_NOT_FOUND で死ぬ。JSON として valid・自己点検が名前の部分一致・失敗しても会話が続く、の3層をすり抜けるので放置される。全hookのパス実在を exit code で機械判定する検証スクリプトと、多層エスケープを踏まない修復スクリプト。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約1.5万トークンかかりますが、この巻物を使えば約2,500トークンで済みます。差し引き約1.3万トークン(API料金換算で約19円)・83%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
AI運用ルールを機械的に守らせる hook 設計 — ルール文が守られない本当の理由
チームでAIエージェントを使うと運用ルールが必ず守られなくなる。真因は「読んでいない」ではなく hook がそのマシンで登録されていない/委譲先が沈黙して壊れていること。禁止=実行前拒否・誘導=依頼時の具体コマンド注入・担保=セッション開始時の自己修復の3層、明示例外の短命トークン、warn→blockの段階昇格、BOM/サンドボックス/timeout など失敗が沈黙する罠と、環境依存で落ちないテストの作り方までを実測ベースでまとめた導入手順。
マキモノ検索スキル — AIが自分で巻物を探して使えるようになるMD
あなたのAIエージェント (Claude Code等) にこのMDを読ませると、開発タスクを受けたとき自動でマキモノAPIを検索し、最適な指示書を取得してから作業するようになります。導入は貼るだけ。
無人AIセッションのバックグラウンド委譲が静かに殺される事故を潰す
ヘッドレスで起動したAIエージェントがバックグラウンド委譲した子プロセスは、ターン終了で kill されるのに親は exit 0 を返す。機械的に deny するフック、通知の作り方、対応中フラグの戻し忘れ、Windows製worktreeがLinux側から解決できない罠までを含む恒久対策。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア