Claude Code Modsは、プラグインに同梱したTypeScriptやJavaScriptの関数を、Claude Codeの処理の途中で呼ばせる拡張です。ツール呼び出しを止める、プロンプトに情報を足す、スピナーの横に数字を出す。こうした変更を、外部スクリプトではなくClaude Code自身の中で行えます。
この記事では、modの仕組みとsettings hooksとの違い、3ファイルで作る危険コマンドのガード、出荷前の検査、組織で利用者のmodを止める管理設定までを実装の順に並べました。プラグインそのものの作り方と社内配布はClaude Codeプラグインの作り方と社内配布|marketplace.json・管理設定【2026年9月版】で扱っています。前提は公式ドキュメントの2026年10月時点の記述で、端末版はv2.1.287以降が対象です。
まとめ:Claude Code Modsの要点と導入前に決めておく4つの判断
一つ目。modは新しい配布形式ではありません。プラグインのhooks/hooks.jsonにmodulesキーを書き、コードファイルを指すだけで、そのプラグインがmodになります。入れ方も更新も/pluginのままです。
二つ目は、settings hooksとの住み分けです。シェルスクリプトで許可・拒否・記録をするだけなら、従来のhooksで足ります。modを選ぶ主な理由は、画面に描くこと、フック同士で変数を共有すること、セッション中に即応するコマンドを足すことの三つです。
三つ目。modはサンドボックスの外で、利用者と同じ権限で動きます。APIキーを含む環境変数も読めるため、入れる前にclaude plugin validateで呼び出す機能を一覧し、出どころを確かめてください。
四つ目は組織の方針です。何も設定しなければmodは有効で、利用者は任意のmarketplaceから入れられます。止める手段は、管理設定のallowManagedModsOnlyです。
Claude Code Modsの仕組み|プラグイン内のTypeScriptが動く場所
公式のMods overviewは、modを「Claude Codeの見た目と振る舞いを変えるプラグイン」と定義しています。中身はイベントごとに呼ばれる関数の集まりです。
modとプラグインの関係はhooks.jsonのmodulesキー1行で決まる
プラグインは配布の入れ物で、modはその中に入る部品の一つです。同じプラグインにスキルやMCPサーバを同居させることもできます。プラグインをmodにする条件は、hooks/hooks.jsonのmodulesに、コードファイルへの相対パスを1本書くことだけです。
コードファイルは公式に「hooks module」と呼ばれ、拡張子は.js、.ts、.mjs、.tsxなど8種を受け付けます。
フックが受け取る3つの引数と観察・書き換え・応答の3通りの扱い
modの関数は、読み込み時に呼ばれるregister(on)の中でon('イベント名', 関数)として登録します。登録された関数がフックで、毎回3つの引数を受け取ります。mods APIの$、イベントの中身e、そして後続へ渡すnextです。
扱い方は3通りあります。next(e)をそのまま返せば観察だけ。中身を変えた写しをnextへ渡せば書き換え。nextを呼ばずに結果を返せば、Claude Codeの既定動作の代わりに自分が応答します。eは深く凍結されたデータで、直接代入すると例外になります。
ファイル読み書き、プロセス起動、ネットワーク通信、モデル呼び出しは、すべて$.fsや$.httpなどのmods API経由に限られます。この制約があるから、Claude Codeは実行前にmodの呼び出しを静的に列挙できます。
動く場所の差|VS Code拡張とclaude -pでは描画されない
フックの実行と画面への描画は、環境によって分かれます。公式の対応表を要約しました。
| 実行環境 | フック | 描画 |
|---|---|---|
| 端末のclaude(JetBrains連携含む) | 動く | 出る |
| DesktopアプリのCodeタブ | 動く | 出る(端末専用要素を除く) |
| DesktopアプリのWSLセッション | 動かない | 出ない |
| VS Code拡張のチャット欄 | 動く | 出ない |
| claude -p とAgent SDK | 動く | 出ない |
| クラウドセッション | 条件付きで動く | 出ない |
ガード用途のmodは、CIのclaude -pでも効きます。一方で画面に描くmodをVS Code拡張の利用者へ配っても、何も表示されません。
Settings HooksとModsの違い|同じイベントでも書けることが変わる
両者はどちらもイベントで動くため混同されがちです。公式は、settingsファイルに書く従来型を「settings hook」、modの関数を「hook」と呼び分けています。従来型の設定とイベントの全体像はClaude Code Hooksとは?CLAUDE.md・Skillsとの違いとできることで整理しました。
Mods・Settings Hooks・Skills・MCPの比較表と選ぶ基準
| 項目 | Mod | Settings hook | Skill | MCPサーバ |
|---|---|---|---|---|
| 実体 | プロセス内の関数 | シェル・HTTP・プロンプト | SKILL.md | 外部プロセス |
| 書く言語 | JS/TS | 任意のスクリプト | Markdown | 任意 |
| 画面への描画 | できる | できない | できない | できない |
| 変えられる範囲 | ツール・プロンプト・ターン・画面 | 実行可否・引数・結果・追加文脈 | Claudeの知識と手順 | 使えるツール |
既存のスクリプトで拒否や記録をしたいならsettings hook、毎回貼る指示を固定したいならスキル、外部システムに届かせたいならMCPを選びます。
ツール呼び出しの回数をスピナーに出す処理は、数える側と描く側が同じ変数を見るためmodでしか書けません。
PreToolUseフックとtool.callの実行順|管理設定のブロックは最終
両方を併用すると、順番が効いてきます。React to events with a modによると、管理設定に書いたPreToolUseはすべてのmodより先に走り、そこでのブロックは覆りません。
ユーザー設定やプロジェクト設定、プラグインのhooks.jsonに書いたPreToolUseは違います。最後のmodがnextを呼んだあとに走るため、modがnextを呼ばずに応答すると、そもそも実行されません。さらにtool.checkイベントは許可判定のあとに来るので、modはsettings hookが止めた呼び出しを許可に変えることもできます。
最初のmodを作る手順|3ファイルの配置から–plugin-dirで読み込むまで
ここで作るのは、rm -rfとforce pushを止めるガードです。Create a modのチュートリアルと同じ構成で、対話中にClaudeへ頼んで書かせる方法もあります。その場合は組み込みのplugin-authoringスキルが使われ、ファイルは~/.claude/dev-mods/配下のセッション専用フォルダに置かれます。
plugin.jsonとhooks.jsonとregister.jsの3ファイルを置く
bash-guard/
├── .claude-plugin/
│ └── plugin.json
└── hooks/
├── hooks.json
└── register.js
マニフェストにmod固有の必須項目はありません。名前がclaude-で始まるとAnthropic製と紛らわしいとして検査で落ちるため、社名などの接頭辞を付けます。
// bash-guard/.claude-plugin/plugin.json
{
"name": "bash-guard",
"version": "0.1.0",
"description": "rm -rf と force push を止めるガード",
"author": { "name": "Your Name" }
}
// bash-guard/hooks/hooks.json
{
"description": "bash-guard の hooks module",
"modules": ["./register.js"]
}
JSONにはコメントを書けないため、先頭のファイル名の行は保存時に外してください。
危険なBashコマンドをtool.callで止めるガードを書く
// bash-guard/hooks/register.js
// 止めたいコマンドの型(rm -r/-rf と --force 付きの git push)
const RISKY = /\brm\s+-rf?\b|\bgit\s+push\b.*--force/
async function guard($, e, next) {
if (!RISKY.test(e.command)) return next(e)
// next を呼ばずに返すとコマンドは実行されない
return { deny: '破壊的なコマンドは禁止です。対象を絞った別の方法を提案してください。' }
}
export function register(on) {
on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
// guard が例外や時間切れで落ちたときは止める側に倒す
if (next.called) return next(e)
return { deny: 'ガードの判定に失敗したため実行しませんでした: ' + next.error.kind }
})
}
第2引数の{ tool: 'Bash' }はマッチャーで、Bashの呼び出しにだけ反応させます。denyの文はClaudeがツールの結果として読むため、次に取るべき行動を書いておくと無駄な再試行が減ります。
見落としやすいのは.catchです。フックが例外を投げるか時間切れになると、Claude Codeはそのフックを飛ばして次へ進みます。つまり既定ではガードが壊れた瞬間に素通しです。.catchでdenyを返すと、失敗時に止める側へ倒せます。フック自身の実行時間は10秒、.catchは1秒が上限とMods referenceに記載があります。
なお、この正規表現はgit push -fのような別の書き方を拾いません。文字列照合のガードは「Claudeへのお知らせ」程度に考え、本当に守るべきブランチはGitホスト側で保護してください。
claude plugin validateとplugin testで出荷前に確かめる
claude --plugin-dir ./bash-guard
claude plugin validate ./bash-guard
claude plugin test ./bash-guard
1行目はインストールせずに1セッションだけ読み込むコマンドで、保存のたびに再読み込みが走ります。2行目はコードを実行しない静的解析で、hooks:行に処理するイベント、calls:行に呼び出すmods APIが並ぶ形です。.catchのないガードにはgating hook without .catchの行が出るため、付け忘れもここで分かります。
静的解析を通すには書き方の制約があります。$.uiなどを変数に代入しない、onのイベント名は文字列リテラルで書く、動的import()を使わない、の3点です。3行目は.test.tsで終わるファイルを、セッションもネットワークもなしで実行します。1件の既定の制限時間は5秒です。
組織でModsを管理する設定|allowManagedModsOnlyと既定のガード
情報システム部門が最初に確認すべきなのはここです。Manage mods for your organizationによると、modはv2.1.286以降で既定有効になっています。
既定で入る守りと入らない守り|sec-defaultが保護する範囲
管理設定がある端末、またはTeam・Enterpriseプランでサインインした利用者には、組み込みのガードsec-default@builtinが利用者のmodより先に読み込まれます。ソースはGitHubのmods/sec-defaultで公開されています。
このガードが守るのは、管理設定のフック、システムプロンプト、管理側のCLAUDE.md、管理側MCPサーバのツール定義などです。拒否ルールで止めた呼び出しを、利用者のmodが許可に変えることもできません。
利用者のmodは、ファイルの読み書き、プロセスの起動、ネットワーク通信を利用者の権限で行えます。Read(.env)を拒否ルールに入れても、modが$.fs.readで同じファイルを読むことは止まりません。APIキーでの認証やBedrock経由の利用者は、端末に管理設定が無いとガード自体が読み込まれない点にも注意してください。
利用者のmodを止めるmanaged-settings.jsonの書き方
{
"pluginConfigs": {
"cc-plugin-sec-default@builtin": {
"options": {
"allowManagedModsOnly": true
}
}
},
"disableSideloadFlags": true
}
allowManagedModsOnlyを立てると、利用者が入れたmod、--plugin-dirで読み込んだmod、Claudeがセッション中に書いたmodのいずれもフックを実行しません。組み込みmodと、組織のものと認められたmodは動き続けます。利用者のsettings hooksやステータスラインも止まりません。
disableSideloadFlagsは、起動時の--plugin-dirと--plugin-urlを拒否する設定です。キーの書き方には癖があり、pluginConfigsではcc-plugin-sec-default@builtinの形しか読まれません。同じ記述をユーザー設定に書いても効かず、管理設定に置いたときだけ有効になります。管理設定の配布経路やパスはClaude Codeのセキュリティ設定|権限ルール・サンドボックス・管理設定で守る実装手順【2026年10月】にまとめています。
自社製のmodだけを通すには、端末上のディレクトリを管理設定でmarketplaceとして登録し、enabledPluginsとprependPluginsに載せます。GitHubやnpm由来のプラグインは、管理設定で有効化しても利用者のmod扱いです。
インストール前にvalidateのcalls行で確認すべきAPI呼び出し
外部のmodを審査するときは、取得したディレクトリにclaude plugin validateをかけ、calls:行を次の表と突き合わせます。
| calls行の表示 | 意味 | 審査の重み |
|---|---|---|
| $.env.get、$.settings.read | 環境変数と設定の読み取り | 最優先で確認 |
| $.http.fetch | ネットワーク送信 | 送信先をコードで確認 |
| $.process.run、spawn | 任意プログラムの起動 | 原則として不許可 |
| $.fs.write | 任意ファイルの書き込み | 書き込み先を確認 |
| $.prompt.submit | 利用者名義でのプロンプト送信 | 用途を確認 |
| $.model.complete | 利用者の契約でのモデル呼び出し | 費用の発生を確認 |
実務ではまず上の3行を見れば足ります。$.env.getと$.http.fetchが同居していれば、APIキーを外へ送れる構造です。悪意がなくても、その組み合わせを持つmodは送信先と送信内容をコードで読み切ってから許可してください。hooks:行にtool.checkがあれば、許可確認の前に承認を出せるmodだと分かります。
Claude Code Modsを業務に入れる条件と見送るべき場面の線引き
modで書くべき場面|画面表示と状態共有が要るときに限って選ぶ理由
採用してよいのは、settings hooksでは構造的に書けない次の三つの要件です。一つはコンテキスト残量や利用量を常時見せる表示で、$.session.usage()の値をプロンプト上の帯に描けます。公式サンプルのclaude-code-playgroundのmodsにあるtoken-weatherがこの型です。
二つ目は、危険な操作をいったん保留し、利用者に選ばせる確認画面です。$.ui.askで質問を出し、答えが出るまでツール呼び出しを待たせられます。三つ目は、組織横断の監査ログです。prependPluginsで先頭に置いたmodは、他のmodが手を加える前の呼び出しを記録できます。利用量そのものの集計なら、modより先にClaude CodeのOpenTelemetry設定で足りないかを確かめてください。
社内規程に合わせたガードや表示を組み込みたいが、TypeScriptでの実装やテストまで手が回らない場合は、生成AI開発・AI受託開発で設計からご相談を受けています。
見送る場面|権限統制やシークレット保護の代わりにmodを使わない
modを統制の手段にするのは見送りです。理由は二つあります。フックは失敗すると既定で素通しになり、利用者は--safe-modeで起動すればインストールしたmodをまとめて外せます。組織として必ず止めたいものは、管理設定の拒否ルールとPreToolUse、Gitホストのブランチ保護に置いてください。
拒否ルールやsettings hooksで書ける要件をmodに移すのも勧めません。イベント名とAPIはリリースごとに変わりうると公式が明記しており、型定義の追随という保守が新たに発生します。rm -rfの拒否ぐらいなら、既存のhooksで十分です。
出どころの確認できないmodを評価目的で入れるのも避けます。読み込まれた時点で環境変数と全プロンプトに届くため、試すなら資格情報を置いていない検証環境に限ってください。
よくある質問
Claude Code Modsについて、導入前に出やすい質問をまとめました。
Claude Code Modsを使うのに追加料金はかかりますか?
mod自体に料金はなく、v2.1.287以降のClaude Codeに含まれる機能です。ただし、modが$.model.completeでモデルを呼び出すと、利用者のプランやAPIキーの使用量として計上されます。maxTokensの既定は1024です。calls:行にこの呼び出しがあれば、費用が発生する構造だと判別できます。
Claude Code Hooksはこれから使えなくなりますか?
使えなくなりません。公式の組織管理ページは、settingsファイルとプラグインのhooks.jsonに書くフックが従来どおり動き、非推奨の扱いもないと明記しています。シェルスクリプトで止める・記録する用途は、引き続きsettings hooksで書くほうが短く済みます。イベントの一覧と書式はClaude Code Hooksの設定方法|全33イベント一覧とsettings.jsonの書き方【2026年9月版】を参照してください。
modを書くのにTypeScriptの開発環境は必要ですか?
不要です。Claude Codeが.jsと.tsを直接読み込むため、Node.jsもビルド工程も要りません。--plugin-dirで読み込むと、Claude Codeが.claude-plugin/types/に型定義を書き出します。エディタの補完に使え、ページの記述と食い違ったときは型定義を正とするよう公式も案内しています。
一時的にmodをすべて止めて原因を切り分ける方法はありますか?
1セッションだけならclaude --safe-modeで起動してください。インストールしたmodがまとめて外れる一方、他のカスタマイズも止まります。全セッションで止める場合は、~/.claude/settings.jsonに"disableAllHooks": trueと書く方法です。組み込みmodはどちらでも止まらず、/diffなどは動き続けます。
early access時のCLAUDE_CODE_ENABLE_FUNCTION_HOOKSはまだ有効ですか?
無効です。v2.1.287以降はこの環境変数を値にかかわらず無視するため、0を設定していてもmodは止まりません。先行期間にこの変数でmodを止めていた組織は、管理設定のallowManagedModsOnlyへ置き換える必要があります。
関連記事
- Claude Codeプラグインの作り方と社内配布|marketplace.json・管理設定【2026年9月版】:modを入れる器であるプラグインの作り方と配り方
- Claude Code Hooksとは?CLAUDE.md・Skillsとの違いとできること:従来型のsettings hooksの位置づけ
- Claude Code Hooksの設定方法|全33イベント一覧とsettings.jsonの書き方【2026年9月版】:settings hooksのイベントと書式の一覧
- Claude Codeのセキュリティ設定|権限ルール・サンドボックス・管理設定で守る実装手順【2026年10月】:拒否ルールと管理設定の配布
- Claude CodeのOpenTelemetry設定|利用状況とコストを組織で可視化する実装:利用量の集計をmodなしで行う方法