課題
Claude Codeに「Mods(モッド)」という仕組みが入った。スピナーの横に情報を出したり、画面に小さなパネルを足したりできる拡張で、見た目をいじれるおもちゃのように見える。
ただ、公式ドキュメントを読むと、Modは見た目だけの話ではなかった。自分の権限で動くプログラムで、ファイルの読み書きや外部との通信までできる。
となると気になるのは、「人が作ったModを入れる前に、何を確かめればいいのか」になる。
解決できるようにすること
他人が作ったModを入れる前に、公式の確認コマンドで何を見ればいいか、どの呼び出しに注意すればいいかを判断できるようにする。あわせて、Modがどこで表示されるか、止めたいときにどうするかも整理する。
先に結論
公式の確認コマンドclaude plugin validateを、中身の違う3つの自作Modにかけてみた。
- 公式ドキュメントの最小Mod(ツールを呼んだ回数をスピナーに出すだけ)→ 合格
- プロンプトを送るたびにファイルと環境変数を読み、外部へ送るMod → これも合格
- 呼び出す機能の名前を実行時に組み立てて、何をするか読めなくしたMod → 不合格
つまり、確認コマンドの「passed(合格)」は「安全です」という判定ではなかった。見るべきは一番下の合格表示ではなく、その上に出るhooks:とcalls:の行になる。
この記事でわかること
- Modsとは何で、何ができてしまうのか
- 確認コマンドの出力で、どの行を読めばいいか
calls:に出てきたら目的と照らし合わせたい呼び出しの一覧- Modが表示される場所と、止める方法
ここで、こう思う人もいるかもしれない。
「確認コマンドで合格したなら、入れても大丈夫なんじゃないの?」
今回の結果を見る限り、そうとは言えない。外部へデータを送るModでも、合格の表示は最小Modと同じだった。違いが出たのはcalls:の行だけだった。
公式発表で分かったこと
Claude Codeの更新履歴では、2026年10月1日のv2.1.287に「Added Claude Mods: plugins may now modify deeper behavior」と書かれている。プラグインが、より深いところの動きを変えられるようになった、という話になる。
公式ドキュメントによると、Modはプラグインの中に入れるJavaScript/TypeScriptのコードで、Claude Codeの中で起きる出来事(プロンプトの送信、ツールの呼び出し、画面の描画など)を受け取って動く。ここでいう「プラグイン」は、Claude Codeに機能を足すための配布単位で、Modはその一部として入ってくる。
注意したいのは、Modができることの範囲になる。公式ドキュメントには、読み込まれたModは次のことができると書かれている。
- 自分のパソコンのアカウントで触れる範囲のファイルを読み書きし、プログラムを起動し、ネットワーク通信をする
- 環境変数や設定ファイルを読む。そこに置いたAPIキーも含まれる
- 自分が送るプロンプトと、Claudeが行うツール呼び出しをすべて見る
- プロンプトやツール呼び出しを書き換えたり、自分が打ったかのようにプロンプトを送ったりする
- 自分に確認が出る前に、ツール呼び出しを許可する
- 自分のプランやAPIキーでモデルを呼び、利用枠を使う
さらに、Modはサンドボックス(隔離された実行環境)の外で動く。Claude Codeのサンドボックスを有効にしていても、それが隔離するのはClaudeが実行するBashコマンドで、Modが起動したプロセスはその外で動くと書かれている。
公式ドキュメントも「Install mods only from authors and marketplaces you trust」として、信頼できる作者や配布元のModだけを入れるよう案内している。そのうえで、入れる前に何をするかを一覧にする方法として、claude plugin validateが紹介されていた。
使える条件と、表示される場所
| 項目 | 公式ドキュメントの記載 |
|---|---|
| 必要なバージョン | ターミナル版はv2.1.287以上、DesktopアプリはClaude Code v2.1.286以上 |
| 既定の状態 | Modsは最初から有効 |
| 料金・プラン | Modsについての料金・プラン条件は書かれていない |
| バージョンの確認 | ターミナルはclaude --version、Desktopアプリは「Code」タブで/status |
Modsが最初から有効ということは、Modを含むプラグインを入れれば、そのまま動くということになる。
表示される場所にも差がある。公式ドキュメントの表を整理すると、こうなる。
| Claude Codeを使う場所 | Modの処理 | Modが描く表示 |
|---|---|---|
ターミナルのclaude(エディタ内のターミナルも含む) | 動く | 出る |
| Desktopアプリの「Code」タブ(WSLのセッションを除く) | 動く | 出る(ターミナル専用の要素を除く) |
| VS Code拡張機能のチャット画面 | 動く | 出ない |
claude -p | 動く | 出ない |
ここは地味に大事なポイントで、VS Code拡張機能のチャット画面では、Modの表示は出ないのに処理は動く。見た目で「何も入っていない」と判断できない、ということになる。
実際に試した環境
試したのは2026年10月8日、macOSになる。
自分の環境では、シェルにclaudeコマンドが入っていなかった。そこで、VS Code拡張機能の中に入っているClaude Code本体(claude --versionの表示は2.1.289)を、AIに直接呼び出してもらった。Modsが既定で有効になるv2.1.287以上なので、条件は満たしている。
今回は、Modsを記事にすると決めたうえで、試し方はAIに組み立ててもらった。AIが3つの小さなModを作り、それぞれを確認コマンドにかけている。表示の確認まではせず、ここで止めると決めたのは自分になる。
試し方では、次の3つを守った。
- 外部から誰かのModはダウンロードしない。Anthropicが公開しているサンプルModもあるけど、今回は使わず、3つとも自作にする
- 3つとも、Claude Codeに読み込ませない。確認コマンドにかけるだけにする
- 外部へ送るModも、送り先は例示用のドメイン(example.com)にして、実行はしない
確認コマンドの使い方は、公式ドキュメントではこう書かれている。
claude plugin validate ./some-mod
Modのフォルダを指定すると、Modを実行せずに中身を読んで、結果を表示してくれる。以下の出力は実際の表示をそのまま載せていて、ファイルの場所の表示だけ短く置き換えている。
1つ目:公式の最小Modは、設定ファイルの書き方で一度つまずいた
1つ目は、公式ドキュメントに載っている最小のModを写したもの。Claudeがツールを呼ぶたびに回数を数えて、スピナーの横に「tool calls: 3…」のように表示する。
最初は、AIがModの設定ファイル(hooks/hooks.json)の書き方を推測で{ "module": "./register.js" }と書いてしまい、確認コマンドでエラーになった。
❯ root: hooks.json must have `hooks` (the hook matchers) or `modules` (hooks modules), or both
✘ Validation failed
hooksかmodulesのどちらか(または両方)が必要、という内容になる。公式のリファレンスどおり、次の形に直すと通った。
{ "modules": ["./register.js"] }
直した後の出力はこうなった。
❯ ./register.js hooks: tool.call, ui.render{component=Spinner}
❯ ./register.js calls: $.ui.invalidate
✔ Validation passed with warnings
警告は1件で、中身は「author: No author information provided.」。作者情報が書かれていない、というだけだった。
hooks:の行は、Modが受け取る出来事の一覧になる。ここにtool.callがある。公式ドキュメントでは、tool.callを受け取るModは「すべてのツール呼び出しを見て、書き換えられる」と説明されている。回数を数えるだけの最小Modでも、受け取っている出来事としては強いものが入っている、ということになる。
一方、calls:の行は、ModがClaude Codeに頼む操作の一覧で、ここには$.ui.invalidate(画面を描き直す)しか無い。ファイルにも通信にも触っていないことが、この行から読める。
2つ目:ファイル・環境変数・外部送信をするModも「合格」だった
2つ目は、比較用にわざと作ったModになる。プロンプトを送るたびに、手元のファイルを読み、環境変数を1つ読み、それらとプロンプトの中身をまとめて外部(example.com)へ送る、という作りにした。
もしこんなModが本当に読み込まれたら、自分が打った内容やAPIキーが外へ出ていくことになる。ただ、確認コマンドの結果はこうだった。
❯ ./register.js hooks: prompt.submit
❯ ./register.js calls: $.env.get, $.fs.read, $.http.fetch
❯ ./register.js env writes: nothing
❯ ./register.js env reads: EXAMPLE_TOKEN
✔ Validation passed with warnings
最後の行は、1つ目の最小Modとまったく同じ「Validation passed with warnings」。警告も同じく作者情報が無いという1件だけだった。
違いが出たのは、その上の行になる。
hooks:にprompt.submitがある → 送るプロンプトをすべて見られるcalls:に$.env.get(環境変数を読む)、$.fs.read(ファイルを読む)、$.http.fetch(通信する)が並んでいるenv reads:に、読む環境変数の名前(EXAMPLE_TOKEN)がそのまま出ている
つまり、確認コマンドは「このModは何をするか」をきちんと一覧にしてくれた。ただ、それが危ないかどうかの判定まではしない。合格の表示だけを見て入れると、この差に気づけない。ここが今回いちばんはっきりした点になる。
3つ目:呼び出しを隠したModは「不合格」で弾かれた
3つ目は、Modが使う機能の名前を、コードの中で文字をつなげて組み立てる作りにした。見た目のコードからは、ファイルを読むのかどうかが分かりにくくなる書き方になる。
結果は不合格だった。
✘ Found 1 error:
❯ modules../register.js: hidden-call-mod: ./hidden-call-mod/hooks/register.js:5: a computed or optional member access on $; $ is always spelled $.noun.event(...) at the call site, on is always on("<event>", hook), and next.to always next.to(e, "<tier>")
✘ Validation failed
エラーの中心は「a computed or optional member access on $」で、機能の呼び出しは決まった書き方($.fs.read(...)のような形)でしか書けない、という内容になる。
公式ドキュメントにも、確認コマンドで読み取れない使い方をしているModは、Claude Codeが読み込みを拒否すると書かれている。今回のModは読み込ませていないので拒否される場面そのものは見ていないけど、少なくとも確認コマンドの段階でははっきり止まった。
期待どおりだった点と、うまくいかなかった点
期待どおりだったのは、公式ドキュメントのとおり、Modを実行しなくてもhooks:とcalls:の一覧が出たこと。外部へ送る呼び出しも、読む環境変数の名前も、隠そうとしなければ全部表に出てきた。呼び出しを隠す書き方は、確認コマンドがエラーで止めた。
うまくいかなかった、というより注意が要ると分かった点は2つある。
- 合格・不合格は、安全かどうかではなく、書き方として読み取れるかどうかで分かれているように見えた。外部へ送るModでも合格だった
- 最小Modでも
tool.callを受け取っていた。hooks:の行だけを見て「強い出来事を受け取っているから危険」とは決めつけられず、calls:の行と合わせて読む必要がある
それと、つまずいた点として、自分の環境ではシェルにclaudeコマンドが無かった。確認コマンドはシェルで打つものなので、VS Code拡張機能だけで使っている人は、先にコマンドが使えるかを確かめておくと迷いにくい。
入れる前に見る行と、注意したい呼び出し
公式ドキュメントの管理者向けページには、calls:の行で注意すべき呼び出しの一覧が載っている。初心者向けに言い換えると、こうなる。
calls:に出る呼び出し | 何ができるか |
|---|---|
$.fs.read、$.fs.write | 自分のアカウントで触れる範囲のファイルを読む・書く |
$.process.run、$.process.spawn | 自分としてプログラムを起動する |
$.http.fetch | ネットワーク通信をする |
$.env.get、$.settings.read | 環境変数や設定を読む。APIキーが入っていることがある。読む変数名はenv reads:の行に出る |
$.env.set | 環境変数を書き換える。その後にClaude Codeが起動するコマンドやMCPサーバーの動きが変わり得る。書き換える変数名はenv writes:の行に出る |
$.mcp.call | つないでいるMCPサーバーのツールを呼ぶ(そのセッションの権限ルールの範囲で) |
$.model.complete | 自分のプランやAPIキーでモデルを呼ぶ |
$.prompt.submit | プロンプトを送る。自分が書いた言葉として送ることもできる |
$.session.send | 別のセッションやサブエージェントのClaudeが読むメッセージを送る |
hooks:の行では、次の出来事に注意したい。
tool.call:すべてのツール呼び出しを見て、書き換えられるprompt.submit:送るプロンプトをすべて見て、書き換えられるtool.check:自分に許可の確認が出る前に、ツール呼び出しを許可・拒否できるsession.append:会話の各行を、保存される前に書き換えられる
これらがあるだけでダメ、という話ではない。大事なのは、Modの説明に書かれた目的と照らし合わせて、必要以上のことをしていないかを見ることになる。
入れる前のチェックリスト
- 作者や配布元を信頼できるか確かめた
- Modのファイルを手元に取ってきただけで、まだ読み込んでいない
claude plugin validateをそのフォルダにかけた- 一番下の「passed」ではなく、
hooks:とcalls:の行を読んだ calls:に上の表の呼び出しがあれば、Modの目的に必要かを考えたenv reads:に出た環境変数の名前を見て、APIキーなどが含まれていないか確かめた- 「Validation failed」になったModは、そのまま入れない
Modを止めたいときの方法
公式ドキュメントでは、止める範囲ごとに方法が分かれている。
- 1つのModだけ止める:
/pluginの「Installed」タブで、そのプラグインを無効にするかアンインストールする - 入れたModをすべて、1回のセッションだけ止める:
--safe-modeを付けてClaude Codeを起動する。ほかのカスタマイズもまとめて止まる - 入れたModをすべて、ずっと止める:
~/.claude/settings.jsonに"disableAllHooks": trueを書く。設定ファイルで作ったフックや、自作のステータスラインも止まる
なお、Claude Codeに最初から組み込まれているModは、--safe-modeやdisableAllHooksでは止まらないと書かれている。
今どのModが読み込まれているかは、ターミナルのClaude Codeで/pluginを開くと、タブの下に「1 mod active · first-mod」のような行で出ると公式ドキュメントにある。ここは今回、自分の画面では確かめていない。
どんな人に向くか
今回の確認方法が役立つのは、次のような人になる。
- ターミナルやDesktopアプリの「Code」タブでClaude Codeを使っていて、人が作ったModやプラグインを入れてみたい人
- SNSや紹介記事で見かけたModを、そのまま入れようとしている人
- VS Code拡張機能のチャット画面だけを使っていて、Modが入っていても表示では気づけない人
逆に、Claude Codeをまだ使っていない人や、プラグインを入れる予定が無い人は、今すぐ急いで何かをする必要はないと思う。
今回は確認できなかったこと
- Modを実際に読み込ませて、スピナーの表示や
/pluginの「mod active」の行を見る確認はしていない。表示はターミナルが必要で、今回はその確認を見送った - 確認コマンドの段階で止まったModを、Claude Codeが本当に読み込み拒否するかは見ていない
- Anthropicが公開しているサンプルModは、ダウンロードしていない
- 試したのはmacOSで、Claude Code 2.1.289の1つのバージョンだけ。WindowsやDesktopアプリでは試していない
- Modsに関する料金・プラン条件は、公式ドキュメントに書かれていなかった
現時点の判断
| 項目 | 内容 |
|---|---|
| 結論 | 確認コマンドの「合格」は安全の判定ではない。外部へ送るModも合格した。見るべきはhooks:とcalls:の行 |
| 対象Plan | Mods自体の料金・プラン条件は公式ドキュメントに記載なし。必要なのはターミナル版v2.1.287以上(Desktopアプリはv2.1.286以上) |
| 確認日 | 2026-10-08(macOS、Claude Code 2.1.289。Modは読み込まず、確認コマンドのみ) |
同じ状況に陥ったときの回避策
- Modを入れる前に、
claude plugin validateをそのフォルダにかけ、calls:とenv reads:の行を読む - 「Validation passed」が出ても、それだけで入れない。外部へ送る作りでも合格はする
$.http.fetchと$.env.getが一緒に並んでいるModは、何をどこへ送るのかを説明やコードで確かめる- VS Code拡張機能のチャット画面ではModの表示が出ないので、
/pluginで入っているものを確認する - 不安になったら、
--safe-modeで1回だけModを止めた状態で起動できる - シェルで
claudeが見つからないときは、確認コマンドを打つ前にその状態を解消しておく
Claude Codeのバージョンが上がると、表示や判定の仕方が変わる可能性もある。入れる前には、そのときの公式ドキュメントも見ておきたい。
次に読むなら
Modは、自分に確認が出る前にツール呼び出しを許可できる。そもそもClaude Codeがどの操作を自分に確認してから進めるのかは、権限モードで変わるので、先に押さえておくと判断しやすい。
- Claude CodeのPlan ModeとAuto Modeはどう違う?使い分け方を公式ドキュメントで確認した — Claude Codeが操作の前に確認を求める場面と、自動で進む場面の違いが分かる
公式情報
この記事は、2026年10月1日のClaude Codeの更新情報と公式ドキュメント、2026年10月8日の実践記録を基に、独自調整したAIが下書きを作成し、筆者が事実確認・編集を行った上で公開しています。

