ModsCode日本語ブログ Claude から Mod のコード例を探す

ModsCode / 日本語ブログ / Claude Code の Mod が動かない・反映されない時の確認手順

Claude Code の Mod が動かない・反映されない時の確認手順

Claude Code の Mod が何も起きない、コマンドが出ない、画面に描かれない、編集が反映されないときの原因を症状別に整理。validate とデバッグログの読み方、拒否メッセージの意味まで解説します。

Claude Code の Mod は、読み込みに失敗したり、フックの 1 つが失敗したりしても、そこだけを飛ばしてセッションを続けます。そのため、壊れた Mod は「何も起きない Mod」に見えます。この記事では、Mod が動かないときに、どこから確認し、どの症状がどの原因につながるかを整理します。メッセージの意味は Anthropic の公式ドキュメントのトラブルシューティングに沿っており、validate の出力は Claude Code 2.1.289 で実際に確かめたものです。

先に結論:最初にやる 3 つ

  1. claude plugin validate を実行する:Mod のフォルダを指定すると、マニフェストの誤りとコードの読み取りの失敗を、セッションを起動せずに調べられます。
  2. /plugin を開く:タブの下に 1 mod active · 名前 の行があるか見ます。名前がなければ、Mod は読み込まれていません。
  3. デバッグログを取る:claude --debug-file ./mod-debug.log で起動すると、読み込んだ Mod、拒否した Mod、失敗したフックのすべてに 1 行ずつ残ります。

1. validate で見つかる誤り

claude plugin validate ./my-mod

次のような誤りは、起動する前にここで分かります。

  • イベント名の書き間違い:on('tool.calls', ...) と書くと、"tool.calls" is not an event というエラーで失敗します。
  • hooks.json に modules がない・綴りが違う:modules を module と書いた私たちの検証では、hooks.json must have hooks (the hook matchers) or modules (hooks modules), or both というエラーで失敗しました。
  • hooks: の行が出ない:hooks: の行は、Mod が受け取るイベントの一覧です。そこに期待したイベントがなければ、そのフックは呼ばれません。

validate は、実行はせずに、コードを静的に読みます。書き方の規則($ の呼び出しをそのまま書く、イベント名は文字列リテラル、import は宣言の形で、など)は 初めての Mod の作り方 にまとめました。

2. 症状から探す

何も起きない:コマンドも描画もない

まず /plugin の mods active の行に、Mod の名前があるかを見ます。ない場合は読み込まれていません。次を上から確認してください。

  • Claude Code のバージョンが古い:ターミナルは v2.1.287 以降、デスクトップアプリは同梱版が v2.1.286 以降が必要です。
  • 初めて開いたディレクトリ:信頼するかどうかの確認に答えるまで、Mod は読み込まれません。そのディレクトリで対話セッションの claude を起動し、確認を承認してください。
  • --safe-mode で起動している:インストールしたプラグインはすべて無効になります。フラグを外してください。
  • WSL のセッション:デスクトップアプリの WSL セッションでは、プラグインが使えません(動く場所の違い)。
  • 設定で止められている:disableAllHooks や、組織の管理設定が Mod を止めています。次の節の拒否メッセージを見てください。
  • Claude が書いた Mod が読み込まれない:最初のファイルの保存時に聞かれるホットリロードの確認が、答えが選ばれないまま 3 回終わると、それ以降は聞かれなくなります(自分で閉じた質問は数えません)。askUserQuestionTimeout を設定していて、答える前に時間切れになる場合がこれにあたります。このときは、Mod のフォルダを自分の場所にコピーし、claude --plugin-dir で読み込んでください。

拒否メッセージの読み方

読み込みを拒否されると、デバッグログに hooks module 名前 not loaded: で始まる行が残ります。コロンの後ろが理由です。主なものを表にしました。

理由の始まり意味
hooks modules are turned off for installed plugins in this process: the rollout switch served offAnthropic が、インストールした Mod を遠隔でオフにしている
... the rollout switch was saved off by an earlier session以前のセッションが保存した値が使われた。古い可能性があるので、Claude Code をもう一度起動する
disableAllHooks in managed settings組織が、インストールしたプラグインのフックを止めている
only managed plugins and built-in plugins runallowManagedHooksOnly が設定されている、または、管理設定以外の設定ファイルで disableAllHooks が設定されている
installed plugins that are not managed load no hooks module in this mode (--bare)--bare で起動している
another plugin of that name loads first同じ名前のプラグインが 2 つあり、読み込める Mod は名前ごとに 1 つだけ

組織のガードによる拒否では、mods are limited to your organization's by policy (allowManagedModsOnly) のようなメッセージが出ます。これは、組織が自分たちの Mod だけを許可している状態です。個人の側で直すことはできません(組織で Mods を管理する)。

読み込まれたのに、フックが働かない

/plugin に名前はあるのに、狙った動きにならないときです。

  • hook skipped:my-mod: tool.call hook skipped: threw Error: boom のような行が出ます。フックが例外を投げた、時間制限(1 つのイベントで 10 秒)を超えた、または正しくない形の結果を返した、のどれかです。同じイベントと原因の組み合わせでは 1 回だけ出ます。デバッグログには、発生のたびに 1 行残ります。
  • registered /x but no command.run hook answered it:/コマンド は登録したのに、答えるフックがない状態です。command.run のフックがない、matcher が別のコマンド名になっている、または next(e) を返している、のどれかです。
  • it crashed the hooks worker:インストールした Mod は 1 つのワーカースレッドを共有します。await のない無限ループのように、スレッドを塞ぐフックがあると、その Mod が外されます。
  • mods that run in the hooks worker are off for this session:ワーカーが 3 回止まり、原因の Mod を特定できなかったため、内蔵でない Mod が全部外された状態です。/reload-plugins で読み直せます。

ツール呼び出しが拒否される

  • a hook changed this call's input after the model wrote it:自動モードで、サーバー側の分類器が確認した後に、フックがツール呼び出しの入力を書き換えたことを示します。同じ呼び出しをもう一度出すように Claude に伝えられますが、それも拒否されるなら、フックが毎回書き換えています。その Mod かフックを止めるか、自動モードをやめて自分で承認してください。
  • tried to lift a deny rule in your settings:あなたの Mod の tool.check が、deny ルールで拒否される呼び出しを許可しようとしました。呼び出しは拒否のままです。

描画が出ない・反応しない

  • ペインや帯が空、または Claude Code のいつもの表示のまま:ui.render が返した木が検証に通りませんでした。--plugin-dir で読み込んだ場合は、トランスクリプトに ui.render (Pane) refused: と理由が出ます。存在しない props や、そのアプリにない要素が典型です。
  • threw while drawn:木の描画中にエラーが起きました。行の最後に the engine drew its own とあれば、その場所は Claude Code の元の表示に戻っています。
  • $.ui.open を呼んだのにペインが出ない:Mod が自分の判断で開いたペインは、端末が 144 桁以上ないと出ません(ユーザーが一度自分で開いた後は 110 桁)。コマンドやボタンから開くか、戻り値の isPlaced を確認してください。
  • トーストが出ない:デバッグログに $.ui.toast (名前): 本文 の行があるか確かめてください。ほかのペインが holdToasts で保留している、通常の表示で新しいトーストに置き換えられた、全画面表示で 3 つを超えた、などが原因です。
  • ホットキーが効かない:ペインにキーボードのフォーカスがありません。Ctrl+X の後に Tab を押すか、ペインをクリックしてください。コマンドから開くときは focus: true を付けます。
  • ターミナルでは出るのにデスクトップアプリで出ない:その場所や要素が、デスクトップアプリにありません。

編集した内容が反映されない・値が消える

  • 編集が反映されない:インストールしたプラグインを編集していませんか。Claude Code は、インストールしたバージョンのキャッシュを動かします。開発中は claude --plugin-dir ./my-mod で作業フォルダを指してください。保存すると読み込み直されます。
  • 再読み込みで値が戻る:モジュールの変数は、読み込み直すたびに初期化されます。保持したい値は $.state か $.store に置きます。
  • /clear、/resume、/branch の後に値が戻る:これらは $.state をデフォルトに戻し、session.start は再び呼ばれません。classic.SessionStart のフックで、保存した値を読み直します。

3. デバッグログの取り方

claude --debug-file ./mod-debug.log --plugin-dir ./my-mod

別のターミナルで、ログを追いながら Mod の名前で絞り込みます。Bash や Zsh では次のとおりです。

tail -f ./mod-debug.log | grep my-mod

PowerShell では次のとおりです。

Get-Content ./mod-debug.log -Wait -Tail 20 | Select-String my-mod

読み込まれた Mod には、名前とイベントを並べた行が残ります。--plugin-dir で読み込んだ Mod は、名前の後ろに @inline が付きます。

読み込まれた Mod のログ(公式の例)
hooks module first-mod@inline loaded (worker, environment 2, tier user); events: session.start,tool.call,command.run,ui.render

自分のコードからログに書きたいときは、$.ui.log('message', { to: 'debug' }) のように、第 2 引数に { to: 'debug' } を付けます。付けないと、トランスクリプトに暗い 1 行が出ます。保存で再読み込みに失敗すると、reload failed, the previous version stays loaded: と理由が出て、最後に動いた版が動き続けます。

まとめ

動かないときは、validate、/plugin の行、デバッグログの順に見れば、たいていの原因に行き着きます。再現を保つには、自動テストが役に立ちます(Mod のテストの書き方)。コードを書き直す前に、似た実装を探したいときは、ModsCode の MCP が、実際の Mod のコードを返します。原文は 公式のトラブルシューティング にあります。