Claude Codeを日々の仕事に合わせて最適化し、より使いやすくしたいと考えたことはありませんか?
Claude Modsを利用すれば、画面に独自のインターフェースを追加したり、自分専用のコマンドを作成したりと、Claude Codeの見た目や内部の振る舞いを直接カスタマイズすることができます。
では、具体的にModsで何をどこまで拡張でき、最初のModはどう作ればよいのでしょうか。
本記事では、Claude Codeを自身の作業環境に合わせて拡張したい方に向けて、Modsの全体像と具体的な開発手順を解説します。
まず「設定フック(Hooks)」や「Skills」「MCP」といった他の手段との違いを整理し、Modsならではの強みを明らかにします。
次に、公式サンプルを用いた導入準備から、最初のModを作成して実際の動作を確認するまでの手順を紹介します。
さらに、海外の開発者が実践しているターミナル向けの描画テクニックや、処理の受け渡し(next)・状態管理・再描画の仕組みといった実践的なTipsを取り入れ、Modを実用的なツールへと育てる方法を解説します。
権限の確認やトラブル時の切り分け方も扱い、独自の機能を持つ拡張ツールの権限と挙動を確かめながら構築する手順を紹介します。
Claude Modsとは?Skills・MCP・Hooksとの違い


Claude Modsは、Claude Codeの見た目や振る舞いを直接書き換えることができる拡張機能(プラグイン)です。
これまでClaudeに指示を与えたり外部ツールを繋いだりする方法はいくつかありましたが、Modsの最大の特徴は「Claude Codeの内部で動作する」という点にあります。
JavaScriptやTypeScriptを用いてイベントハンドラー(出来事に応じて実行する関数)を記述します。
ツールの呼び出し、プロンプトの送信、画面の描画といったタイミングに介入して、独自の処理を組み込むことができます。
内部処理に直接アクセスできるため、Modsを使うと外部スクリプトやプロンプトの調整だけでは実現できなかった高度な画面拡張が可能になります。
たとえば、実行履歴(トランスクリプト)の横にペインを追加したり、入力プロンプトの上部に専用の領域(バンド)を設けたりして、そこにタブやボタン、テキスト入力欄などのインターフェースを新しく配置できます。

これにより、リクエストごとのコンテキストの埋まり具合をグラフ化して表示するといった使い方が可能になります。
また、新規の描画だけでなく、Claude Code自身が描画する既存のインターフェースを書き換えることもできます。
処理待ち時間を示すスピナーの横に「ツール呼び出し回数」をリアルタイムで追記したり、ツール実行の行の見た目を変更したりと、作業記録を自分の見やすい形にカスタマイズできます。
さらに、ModsはClaudeの推論やツールの動作自体にも介入できます。
Claudeが特定のツールを実行しようとするイベントを捕捉し、その実行を保留してユーザーに確認の質問を投げかけたり、特定のリクエストだけを別のAIモデルに切り替えたりする制御が可能です。
スラッシュから始まる独自のカスタムコマンドを追加することもでき、これはClaudeの推論ターンを伴わずに即座に実行されるため、利用者自身がモデルに推論させずに処理を走らせる用途に役立ちます。
また、ひとつのModに含まれる複数のイベントハンドラー(フック)は変数を共有できるため、あるフックでトークン使用量を計測し、別のフックでその数値を画面に描画するといった連携が簡単に実現できます。
Claude Codeを仕事に合わせるための手段には、Modsのほかに「設定フック(Settings hooks)」「Skills」「MCPサーバー」があります。目的に応じてこれらを使い分けることが作業環境を整える第一歩です。
画面のインターフェースを追加したい場合や、カスタムコマンドを作りたい場合、イベントの動作自体を書き換えたい場合は、これまで説明したClaude Modsが適しています。
一方で、イベントをブロックしたり許可したり、単純にログに残したりするだけであれば、設定ファイルを用いた設定フックで十分です。こちらはシェルコマンドやHTTPリクエストなど、すでに手元にある外部の実行環境やスクリプトを特定のタイミングで呼び出したい場合に向いています。
必須検査を設定フックで止める設計は、Claude Code・Codex向けのHooks解説で具体例を紹介しています。
チャットのたびに同じ前提条件や指示を入力する手間を省きたい場合は、Skillsを使います。マークダウンファイルに指示を書いて読み込ませることで、Claudeの前提知識を定型化して共有できます。
そして、Claudeに外部のシステムやサービスを操作する新しい能力(ツール)を与えたい場合は、MCP(Model Context Protocol)サーバーを使います。特定の機能を持たせたサーバーを外部プロセスとして動かすことで、Claudeの対応範囲を広げます。
これらは互いに排他関係にあるわけではなく、1つのプラグインの中にModのコードとSkill、MCPサーバーをまとめてパッケージ化して扱うことも可能です。
Modsが描画する独自のインターフェースは、実行環境によって表示できるかどうかが変わります。ターミナルで実行する通常のコマンド(エディタの統合ターミナルやJetBrainsプラグインを含む)や、Claude DesktopアプリのCodeタブでは、それぞれの環境が対応する画面要素を描画できます。
しかし、VS Code拡張機能のチャットパネルや非対話型環境などでは、Modsの内部処理自体は実行されますが、独自ペインの描画は行われません。
そのため、画面描画を伴うModを利用・開発する際は、動作環境を判定して描画ができない環境では通常のテキストとしてログに出力するなどの代替処理を考慮する必要があります。
なお、Claude DesktopのWSLセッションでは、プラグインの仕組み自体が利用できないためModsも機能しません。
目的に応じて適切な拡張手法を選び、インターフェースや内部動作に深く介入したい場合にClaude Modsを活用することで、自身の業務に寄り添う快適な作業環境を構築できます。
Claude Modsを使う準備と公式サンプル


Claude Modsを使うには、Claude Codeのバージョンがv2.1.287以降である必要があります。
このバージョンからはModsがデフォルトで有効になっています。
現在の環境を確認するには、ターミナルでclaude --versionと入力してください。
古いバージョンが表示された場合は、アップデートしてから試してください。古い記事にあるCLAUDE_CODE_ENABLE_FUNCTION_HOOKSは、現行版では値を問わず無視されます。
Modsは隔離されたサンドボックス環境ではなく、Claude Codeを実行しているユーザー自身の権限で直接動作します。
つまり、ファイルの読み書き、別のプログラムの起動、ネットワーク通信などをユーザーと同じように実行できます。
さらに、環境変数や設定ファイルに保存されたAPIキーなどの機密情報を読み取ったり、ユーザーが許可を出す前に独自の判断でツールの実行を承認したりすることも可能です。
Claudeの課金枠を使ってモデルを呼び出すこともできるため、Modsをインストールする際は信頼できる作成元やマーケットプレイスからのみ入手することが重要です。
Claudeのツールに対するdenyルールは、Mod自身の$.fsや$.processのアクセスを制限しません。ファイルを読むツールを拒否していても、Modが同じファイルへアクセスできる場合があります。
このような強い権限を持つModsを安全に扱うため、Claude Codeにはインストール前にそのModが何を行うかを調べる機能が備わっています。
Modのファイル一式をダウンロードしたあと、ターミナルでclaude plugin validate ./対象のディレクトリを実行します。
そのModが反応するイベント(hooks)と、Claude Codeに要求する操作(calls)をリストアップできます。
これを確認することで、通信やファイルアクセスに使うAPIを事前に把握できます。
実際にModsがどのように機能するのかを体験するためには、Anthropicが公式に提供しているサンプルリポジトリ「claude-code-playground」を試すのが一番の近道です。
このリポジトリには、実装例のModがいくつか収録されています。各READMEは、公式製品としてのサポートや保守を保証しないサンプルであると明記しています。 例えば「token-weather」は、コンテキストウィンドウの消費具合を天気予報に見立てて、プロンプト上部に表示するModです。
空き容量に余裕があれば「☀ Clear」、半分ほど埋まれば「☂ Showers」、限界が近づくと「☇ Storm」といったアイコンと使用率、最近のターンの推移を示すブロックグラフを描画します。

ほかにも、「blast-radius」というModは、ファイルの強制削除やGitの強制プッシュなど危険なコマンドの実行を一時停止させ、影響範囲を確認したうえで実行・キャンセルのボタンを画面に表示します。
「replay-theater」は、Claudeが前回のやり取りで行ったファイルの変更内容を順を追って確認できる専用のカスタムコマンド(/replay)を追加するものです。
ここでは「token-weather」を自分の環境で試す手順を紹介します。
まず、ターミナルでgit clone https://github.com/anthropics/claude-code-playground.gitを実行し、リポジトリをダウンロードします。
続いてclaude-code-playground/claude-code/modsディレクトリへ移動します。 先ほど紹介した検証機能を使ってclaude plugin validate ./token-weatherを実行し、内容を確認します。
問題がなければ、まずは一時的な読み込みを試します。
claude --plugin-dir ./token-weatherを実行すると、そのセッション限定でModが読み込まれた状態のClaude Codeが起動します。
起動後、いくつかのファイルを読み込ませるなどして作業を進めると、ターミナルのプロンプトのすぐ上に天気アイコンとトークンの状況が表示されるはずです。
このModは、トークン使用量を計測するために課金を伴うリクエストを発生させず、セッション内の既存の利用データを無料で読み取る仕組みを活用しています。
そこからターン完了後に数値を更新し、画面に独自のインターフェースを描画するというModsならではの処理を単一のファイルで実現しています。 このModを継続して使いたい場合は、現在いるclaude-code-playground/claude-code/modsでローカルのマーケットプレイスを登録します。
claude plugin marketplace add ./
claude plugin install token-weather@claude-code-playground-mods --scope userインストール後は、次回以降も読み込まれるようになります。
なお、Token Weatherが描くAbovePromptはターミナル専用です。Modの描画対応は、Claude Desktopでも各表示要素によって異なります。
VS Code拡張機能のチャットパネルなど描画に対応していない環境では、グラフ等の表示が行われない点には留意してください。
公式サンプルを動かしてModsの挙動を体感できた後は、ご自身の用途に合わせて最初のオリジナルModを作成するステップへと進んでいきましょう。
最初のModを作り、読み込みと動作を確認する


公式サンプルでClaude Modsの可能性に触れたあとは、実際に自分自身のModを作成してみましょう。ここでは公式のチュートリアルに沿って、ツールの呼び出し回数をカウントする「first-mod」を作成します。
処理中のスピナーの横に回数を表示し、専用のコマンドでもカウントを確認できる拡張機能です。
Claude Modsの優れた点のひとつは、Node.jsのプロジェクト設定やビルド作業が不要なことです。指定のフォルダに設定ファイルとJavaScript(またはTypeScript)のファイルを配置するだけで、Claude Codeが直接コードを読み込んで実行してくれます。
必要なディレクトリと設定ファイルの準備
まずは、Modを構成するファイルを格納するディレクトリを作成します。ターミナルで以下のコマンドを実行し、プラグイン情報の設定とコードの置き場所となるフォルダを用意します。
mkdir -p first-mod/.claude-plugin first-mod/hooksWindowsのPowerShellでは、代わりに次のコマンドを実行してください。
New-Item -ItemType Directory -Force first-mod\.claude-plugin, first-mod\hooks次に、このModの基本情報(マニフェスト)を定義します。以下の内容をfirst-mod/.claude-plugin/plugin.jsonという名前で保存します。
{
"name": "first-mod",
"version": "0.1.0",
"description": "ツール呼び出し回数をカウントし、スピナー横への表示と/tallyコマンドを追加します",
"author": { "name": "あなたの名前" }
}続いて、Claude Codeに実行してほしいコードの場所を伝える設定ファイルを作成します。以下の内容をfirst-mod/hooks/hooks.jsonとして保存します。このファイルが存在し、modulesキーでコードへのパスが指定されていることが、単なるプラグインを「Mod」として機能させる条件になります。
{
"description": "first-modのフックモジュール",
"modules": ["./register.js"]
}フックモジュールの実装と仕組み
設定ができたら、Modの心臓部となるコードを記述します。先ほど指定したfirst-mod/hooks/register.jsを作成し、以下のコードを保存してください。
// フック間で共有するカウント用変数
let calls = 0;
// Mod読み込み時にClaude Codeから一度だけ呼び出される関数
export function register(on) {
// 1. セッション開始時: /tally コマンドを登録する
on('session.start', async ($, e, next) => {
await $.command.register({
name: 'tally',
description: 'Claudeがツールを何回呼び出したかを表示します'
});
// 本来のセッション開始処理をそのまま続行させる
return next(e);
});
// 2. ツール実行前: カウントを増やし、画面の再描画を要求する
on('tool.call', async ($, e, next) => {
calls += 1;
// UIのレンダリング処理を無効化し、再描画を促す
$.ui.invalidate('ui.render');
return next(e);
});
// 3. コマンド実行時: /tally が入力された場合のみ応答する
on('command.run', { command: 'tally' }, async () => {
// トランスクリプト(履歴)に表示するテキストを返す
return { text: 'このModが読み込まれてからのツール呼び出し回数は' + calls + '回です' };
});
// 4. UI描画時: スピナーの表示内容を書き換える
on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
// 既存のスピナーのプロパティを保持しつつ、文字列(suffix)を追加する
return next({
...e,
props: {
...e.props,
suffix: ' · ツール呼び出し回数:' + calls + '…'
}
});
});
}このコードでは、register関数を通じて4つの「フック(イベントハンドラー)」を登録しています。それぞれのフックは、以下の3つの引数を受け取って動作します。
$(Mods API)は、Modが外部の機能にアクセスするためのインターフェースです。コマンドの登録($.command.register)や画面の再描画要求($.ui.invalidate)などを行います。e(イベントデータ)は、発生したイベントの詳細情報です。next(次の処理へ渡す関数)は、処理を他のModやClaude Code本体へ引き継ぎます。
たとえばsession.startやtool.callでは、独自の処理を行ったあとにnext(e)を返すことで、Claude Codeの通常の処理を妨げずに進行させています。
一方、command.runではnextを呼ばず自前でテキストを返しているため、ClaudeのAIモデルによる推論などをスキップして即座に結果を表示できます。
ui.renderでは、受け取ったイベントデータeの中身を少し書き換えてからnextに渡すことで、既存の画面表示に介入しています。
テスト機能を使った事前の動作検証
Modを実際の作業に投入する前に、期待通りに動くかをテスト機能で確認してみましょう。Claude Codeには、ネットワーク通信やAIモデルの推論を発生させずにModの挙動を検証できるコマンドが用意されています。
テスト用のフォルダを作成します。
mkdir -p first-mod/testsテスト用のファイルをfirst-mod/tests/first-mod.test.tsとして作成し、以下の内容を記述します。
import { expect, test } from 'claude-code/testing'
test('/tallyコマンドがツール呼び出し回数を正しく報告する', async ($, on) => {
// 実際のツールが動かないよう、Claude Codeの代わりにダミーの応答(スタブ)を登録
on('tool.call', () => ({ result: 'ok' }))
// テスト用のツール呼び出しイベントを2回発生させる
await $.tool.call({ tool: 'Bash', command: 'ls' })
await $.tool.call({ tool: 'Read', file_path: 'README.md' })
// /tally コマンドを実行し、返ってきたテキストを確認する
const answer = await $.command.run({ command: 'tally', args: '' })
expect(answer.text).toBe('このModが読み込まれてからのツール呼び出し回数は2回です')
})ファイルを作成したら、ターミナルでModのディレクトリを指定してテストを実行します。
claude plugin test ./first-modコンソールに1 passと表示されれば、この2回のスタブ呼び出しに対するカウントと返答のテストが通っています。実際の画面表示は、次の手順で別に確認します。このようにテストを書いておくと、機能を追加した際にも動作が壊れていないか素早く確認できます。
実際の画面での読み込みとホットリロードの体験
テストが成功したら、いよいよ実際のClaude Code環境で読み込んでみましょう。一時的に読み込むためのフラグを使って起動します。
claude --plugin-dir ./first-mod起動したら、Claudeに「このディレクトリのファイルをリストアップして、READMEを読んで」など、ツールを複数回使うような指示を出してみてください。Claudeが思考しツールを実行するたびに、画面下部のスピナーに「Thinking · ツール呼び出し回数:2…」といった具合に回数がリアルタイムで追記されていく様子が確認できます。
処理が完了したあとに、プロンプトで/tallyと入力してEnterキーを押すと、トランスクリプト上に現在のカウント結果が表示されます。スラッシュコマンドの一覧をTabキーで補完した際にも、このコマンドが追加されていることがわかるはずです。
この数はtool.callを受け取った回数です。拒否や失敗も含み、成功した操作数ではありません。サブエージェントやMCPの呼び出しも含まれます。
さらに、Claude Modsには「ホットリロード」という便利な機能があります。Claude Codeのセッションを開いたまま、エディタでregister.jsを開き、スピナー描画部分のテキストを' · ツール呼び出し回数:'から' · 呼び出し数:'に変更して保存してみてください。
保存した瞬間にターミナル上で再読み込みが行われたことが通知され、その後の操作ではすぐに新しいテキストが反映されます。いちいちClaude Codeを再起動することなく、コードを書き換えながらインタラクティブに開発を進められるのが、Claude Modsの大きな魅力です。
このように、たった3つのファイルを用意するだけで、Claudeの内部動作にフックし、画面表示やコマンドを自分好みに拡張できることが確認できました。次のステップでは、この仕組みをさらに活用していくための実践的なTipsを見ていきましょう。
海外の実装から学ぶClaude Modsの活用Tips

世界中の開発者が公開しているClaude Modsの実装例や、Anthropic公式のPlaygroundリポジトリには、ターミナル上で快適な体験を作るための工夫や、現行の仕様に合わせた実践的なTipsが多く含まれています。ここでは、海外の実装事例から、自分の仕事用Modを作る際に役立つ判断基準やテクニックをいくつか紹介します。
Modを使って独自のインターフェースを追加する際、ターミナルならではの制約に直面することがあります。
コンテキストウィンドウの使用量を天気予報のように表示する「Token Weather」というModは、当初SVGを用いてグラフを描画するアイデアから始まりましたが、ターミナル環境ではSVGを直接描画できません。
そこで最終的な実装では、絵文字の代わりにどのフォントでも幅が揃いやすいテキストシンボル(☀や☂)と、ブロック文字(▁▂█)を並べてグラフを表現する判断がなされています。
また、画面の幅に応じた表示の切り替えも重要です。
危険なコマンドの実行を一時停止させる「Blast Radius」や、ファイル変更の差分を後から振り返る「Replay Theater」は、画面右側に独立した領域(Pane)を開いて情報を表示します。
しかし、ターミナルの幅が狭いとPaneを配置できない場合があります。
これらのModは、Paneが配置できたかどうか(isPlaced)を確認し、開けない環境ではプロンプト上部の細長い領域(AbovePromptバンド)に表示を切り替えるというフォールバック処理を実装しています。
AbovePromptは複数のModで1つの場所を取り合う仕様のため、環境に合わせて柔軟に描画先を変える工夫が実用性を高めます。
日々の業務で常用するModであれば、余計なAPI課金や意図せぬファイルの破壊は避けたいところです。
Token Weatherでは、トークンの使用状況を把握するためにモデルへ問い合せるのではなく、フックの中で$.session.usage()を呼び出しています。
この呼び出しは内訳を要求せず、Claude Codeのステータスラインと同じ数値を返すため、追加のトークン計数リクエストを送らずにターン完了後の状態を画面に反映できます。
またBlast Radiusでは、削除されるファイルの数やサイズを事前計算するために、裏側でfindやduなどのシェルコマンドを実行します。
このとき、対象のパスはシェル用の文字列へ結合せず、$.process.runの引数配列へ渡します。さらに、相対パスの先頭に./を付けます。
引数配列はパス中の文字がシェルの命令として実行されるのを防ぎ、./はファイル名がfindのアクション(-deleteなど)として読まれるのを防ぎます。
Modの内部処理が引き起こす副作用を抑える設計は、ローカルの作業環境を守る上で欠かせません。
ただしBlast Radiusは、シェル全体を解析しません。bash -cや別のスクリプト経由の削除などは見逃します。測定するのは1行の最初の危険部分で、Proceedは行全体を実行します。
また、移行処理の状態確認では、Proceedを押す前にプロジェクトのコードを起動します。画面の確認ボタンより前にも処理が走るため、未知のプロジェクトで試す際は、この計測処理も読んでください。
Modのイベントハンドラー(フック)自体の処理には、「10秒以内」という制限時間が設けられています。しかしBlast Radiusのように、ユーザーが「実行」か「キャンセル」のボタンを押すまでツールの実行を保留したい場合、10秒では短すぎます。
この制約に対して作者が取った手法は、待機ループで$.process.run(["sleep", "0.25"])を呼び出すというものです。
現行の仕様では、$経由で外部プロセスを呼び出している間の時間は、フックコード自体の10秒の制限にはカウントされません。
この仕様を使って、ユーザーのボタン操作を待機させています。Blast Radius自身は、10分の無回答やターンの中断ではコマンドを拒否します。
Claude Codeは、1回の指示に対してメインの応答を返すだけでなく、裏側でさらに別のAIエージェント(サブエージェント)を起動して処理を分割することがあります。そのため、すべてのツール呼び出しやターン完了のイベントに無条件で反応すると、表示が細かくなりすぎたり、内部の状態管理が複雑になったりします。
前述のReplay Theaterは、turn.startとturn.completeでメインのやり取りごとに記録を区切ります。

活動内容を映画風のエンドロールにする「Roll Credits」は、tool.callとturn.completeを観測し、成功したメインの応答ターンを数えます。
その際、サブエージェントが実行した細かいターンはスキップしたり、メインターンの結果にまとめたりする判断が組み込まれています。
これにより、人間が見て意味のある単位で記録を整理し、ノイズのないインターフェースを保っています。
Replay Theaterには、呼び出された後に拒否された編集や、失敗した編集も表示されます。差分は操作の成功証明ではないため、反映を確認するには実ファイルも見てください。
Roll Creditsの編集数は、成功したEdit・Write・NotebookEditの呼び出し数です。Bashや外部エディタの編集は含まず、変更行数やコード品質を示すものでもありません。
/credits --textなら文字だけ、/credits --stillなら静止した表示で確認できます。/credits demoは架空データです。記録は再読み込みで消え、共有した画面のファイル名にも注意が必要です。
海外の解説からは、複数のModを組み合わせるときの確認方法も学べます。Vanjaの記事は、個々のハンドラーだけでなく処理の連鎖を読む必要性を指摘しています。
たとえば、前のModがコマンドを書き換えると、後のModが確認するコマンドも変わります。next(e)の前後で何を渡し、何を受け取るかを確認し、単体テストに加えて併用時の動作も試してください。
Karan Bansalの調査では、実行せずに取得したAPI一覧を公開しています。学べるのは、そのModが触れる対象を導入前に確認する手順です。
$.process.runがあるという表示だけでは、起動するプログラムまでは分かりません。バッジを安全性の判定にせず、引数を含むコードと、利用中の版での検証結果を確認してください。
Claude Code Modsの入門例は、強制プッシュの拒否と通常コマンドの通過を両方テストしています。禁止したい入力だけでなく、通常の作業を妨げないことも試す方法です。
この教育用ガードは、sudoやenv、bash -cを挟んだ呼び出しなどを捕捉しません。書き方を変えて通り抜ける例もテストへ残し、検出できる入力とできない入力を分けてください。
これらの海外記事には、初期公開版の有効化フラグや型取得手順が残っています。使うときは、現行版の既定有効と型の自動生成に読み替え、昔のコマンドをそのままコピーしないようにしてください。自身の業務に合わせてModを開発する際も、これらの事例を参考にすることで、より安全で安定して動作する拡張機能を作り上げることができます。
next・状態・描画を押さえてModを育てる

最初のModを作成した後は、さらに複雑な処理を組み込み、独自のツールへと育てていく段階に入ります。Claude Modsを実用的なレベルに引き上げるためには、「next関数による継続(Continuation)」「型定義による支援」「状態の管理と再描画の仕組み」という重要な要素を理解する必要があります。
処理の「前」と「後」を包み込むnext関数
Claude Modsのイベントハンドラー(フック)は、常に3つの引数($, e, next)を受け取ります。$はMods APIへのアクセス手段、eはイベントのデータですが、処理の要となるのが3つ目のnext関数です。
Modsのフックは、複数の拡張機能やClaude Code本体の動作へと順番に処理を受け渡していくミドルウェアのような構造を持っています。イベントに対して何も変更を加えずに観察するだけであれば、最後にreturn next(e)を呼び出すことで、処理は元の流れに戻ります。
この構造の最大の利点は、1つの関数の中で「実行前」と「実行後」の両方を制御できる点にあります。たとえば、ツールの実行結果をログに残したい場合、以下のように記述します。
// ツールの実行を待ち、その結果を受け取る
const result = await next(e);
// ツール実行後の結果(result)をここで処理できる
return result;このようにawait next(e)で処理の完了を待てば、Claude Codeが行った処理の結果を受け取り、それを確認してから返すことができます。これまで別々のスクリプトで監視していた入力と出力を、1つの場所でまとめて管理できるのがModsの強力な点です。
また、イベントを書き換える(Rewrite)ことも可能です。
ただし、受け取ったイベントデータeは凍結(Deep freeze)されており、直接値を代入しようとするとエラーになります。
たとえばprompt.submitの本文を変更するなら、next({ ...e, text: '新しいテキスト' })のように、コピーした新しいオブジェクトを渡します。
変更するフィールドはイベントごとに異なります。Bashのtool.callではtextではなくcommandを使います。
逆に、特定のコマンドをブロックしたり、自前の処理だけで完結させたい場合は、nextを一切呼び出さずに結果のオブジェクトを直接返します(Answer)。
たとえばtool.callで拒否するなら{ deny: '実行を拒否しました' }です。返すオブジェクトの形もイベントごとに異なります。これにより、そのイベントの後続処理をスキップさせることができます。
エディタの補完を効かせる型定義
Claude Codeのバージョンが上がるにつれて、Modsで利用できるイベントや機能は変化します。これに対応するため、Claude Codeには強力な開発支援の仕組みが備わっています。
claude --plugin-dir ./first-modで読み込むと、Claude Codeは.claude-plugin/types/へ型定義ファイル(TypeScript用の宣言ファイル)を書き出します。
Mods APIの詳細は、その中のclaude-code/index.d.tsで確認できます。
型定義には、そのClaude Codeのバージョンで使えるイベント名、イベントデータ、Mods APIのメソッドが記述されています。
Modのルートにtsconfig.jsonがなければ、Claude Codeが生成設定を継承するファイルを追加します。既存の設定がある場合は、次のextendsを設定してください。
{
"extends": "./.claude-plugin/types/tsconfig.json"
}JavaScriptのregister.jsでは、registerの直前に型を伝えるJSDocコメントを加えると、onからイベントの型を追えます。
/** @param {import('claude-code').On} on */
export function register(on) {
// ここへ先ほどの4つのフックを置く
}普段使っているVS Codeなどのエディタで、onのイベント名やハンドラー内の$の候補を確認します。補完が出なければ、型ファイルとtsconfig.jsonの読み込みを確認してください。公式のリファレンスを毎回確認しなくても、変数$と打ち込んだ瞬間に利用できる機能の一覧が表示されるため、利用できる型を確かめながら開発できます。
一時的な変数と永続的な状態の管理
複数のイベントをまたいでデータを保持したい場合、いくつかの方法があります。最初のMod作成で体験したように、モジュール(ファイル)のトップレベルにlet calls = 0;のような変数を宣言すれば、セッション内で一時的に状態を共有できます。しかし、ファイルを書き換えてホットリロードが行われると、この変数はリセットされてしまいます。
セッションをまたいだり、再読み込み後も状態を維持したい場合は、Mods APIの永続化機能である$.storeを利用します。
$.store.set('key', value)で値を保存し、$.store.get('key')で読み込むことができます。
保存データはプラグインごとに管理され、同じPCのセッション間で共有されます。暗号化や秘密情報の管理を保証するAPIではないため、APIキーを保存する用途とは分けて考えてください。
これまでの統計情報を保持したいときに使えます。
状態の変化を画面の描画に反映する
変数の値や状態を更新しただけでは、Claude Codeの画面は自動的には変わりません。新しいカウント数や取得したデータを画面のインターフェースに反映させるには、再描画の仕組みを活用する必要があります。
たとえば、ツールの実行回数が増えたときに画面の表示を更新するには、状態を変更した直後に$.ui.invalidate('ui.render')というメソッドを呼び出します。これにより、Claude Codeに対して「表示するべきデータが変わったので、UIを再描画してください」というリクエストが送られます。
再描画の要求を受け取ると、Claude Codeは画面を描画するためのui.renderイベントを発火させます。
作成したMod側でこのイベントをフックしておけば、更新された最新の変数の値を使ってインターフェースを組み立て直すことができます。
既存のスピナーに文字を付け足したり、新しいペインへテキストやボタンを配置したりできます。
画面の拡張では、「状態の変更」「invalidateによる再描画要求」「ui.renderフックでの描画」をつなぎます。
これらの「前後の処理を包むnext関数」「正確な型定義」「状態管理」「再描画のサイクル」を組み合わせることで、単なる自動化スクリプトの枠を超えた、対話的で高度な自分専用のツールを構築できるようになります。
Modの権限を確認し、動かない時は切り分ける

Claude Modsはユーザーと同じ権限でファイル操作やネットワーク通信を行うため、動作不良の原因は単なるコードの文法エラーにとどまらず、権限の制限やシステム側の安全装置による介入など多岐にわたります。作成したModが期待通りに動かない場合や、インストールしたModの挙動がおかしい場合は、順を追って原因を切り分けることが重要です。
読み込みの前提条件と権限を確かめる
そもそもModが読み込まれていないケースがあります。たとえば、初めて開くディレクトリでClaude Codeを起動した場合、提示される「信頼の確認(トラストプロンプト)」に合意するまでModは起動しません。
また、Modの開発中や他者のModをインストールする前には、対象のディレクトリでclaude plugin validate ./対象のディレクトリを実行し、マニフェストファイルに記述ミスがないかを確認してください。
このコマンドは記述を検証し、反応するイベント(hooks)と要求する操作(calls)をリストアップします。
たとえば、$.fs.readはファイルの読み取り、$.process.runはプログラム起動、$.http.fetchはネットワーク通信を表します。
強力な権限がどのように使われるかを事前に把握するうえで、この検証は欠かせません。
設定の問題で動かないこともあります。
会社などの組織では、管理者の設定で利用者のModを止める場合があります。
disableAllHooksはフックを止める設定、allowManagedModsOnlyは組織管理のModだけを許可する設定です。
何もしていないのにModが動かないときは、Modが含まれない別のディレクトリでclaude plugin testコマンドを実行してみてください。
hooks modules are turned off hereなら設定による制限、no hooks module to loadならテスト対象がない状態です。
ただし、この確認ではallowManagedModsOnlyによる拒否までは検出できません。読み込み時のデバッグログにある、refused by cc-plugin-sec-defaultに続く理由も確認してください。
デバッグログによるエラーの特定と復旧
Modが読み込まれているはずなのに機能しない場合は、デバッグログを確認します。ターミナルでclaude --debug(あるいは--debug-file ./mod-debug.logを指定してファイルに出力)を付けて起動すると、Claude Codeの背後で起きている出来事の詳細を追うことができます。
開発中のfirst-modを調べる場合は、読み込み先も指定して起動します。
claude --plugin-dir ./first-mod --debugModの内部で例外エラーが起きたり、処理が10秒の制限時間を超えてタイムアウトしたり、想定外の形式で結果を返したりすると、デバッグログにはhook skippedと記録されます。このとき、Claude Code本体の動作は止まらず、エラーを起こしたModの処理だけがスキップされるため、一見すると「何も起きていない」ように見えてしまいます。
また、インストールされたModは独立した1つのワーカースレッドを共有して動いています。
無限ループなどで非同期の待機が行われず、このワーカーが応答しなくなったりクラッシュしたりすると、原因と特定されたModはメモリから降ろされます。
原因のModを特定できずワーカーが3回クラッシュすると、Claude Codeは安全のために組み込み以外のすべてのModを強制的に停止させます。
この状態になった場合は、コードのエラーを修正したうえで/reload-pluginsコマンドを実行するか、セッションを再起動して再度読み込ませる必要があります。
問題の原因がMod自体にあるのか、それともClaude Codeの別の設定にあるのかを素早く切り分けたい場合は、claude --safe-modeで起動してください。セーフモードではインストール済みのModがすべて無効化されるため、インストールしたModを止めた状態の動作を確認できます。組み込みのModは引き続き動きます。
フェイルクローズの実装と描画トラブルへの対処
先ほど触れた「エラー時にフックがスキップされる」という仕様は、Modの不具合によってユーザーの作業全体が止まるのを防ぐためのデフォルト動作(フェイルオープン)です。しかし、危険なツールの実行を監視してブロックするModなどでは、エラーが発生した際にそのまま制限をすり抜けてツールが実行されてしまう危険があります。
チェック失敗時に実行を止めたい場合は、イベントの登録時に.catchをつなぎ、拒否を返す(フェイルクローズの)処理を実装してください。
これはnext(e)を呼ぶ前のチェック失敗に対する処理です。実行後の結果処理で失敗しても、すでに行われたツールの操作は取り消せません。
on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
// エラーやタイムアウトが起きた場合に実行をブロックする
return { deny: 'Modのチェック処理が失敗したため、このコマンドの実行を拒否しました: ' + next.error.kind };
});画面描画に関するトラブルも、デバッグログで原因を突き止めることができます。
ペインを開こうとしたのに何も表示されない場合、ターミナルの幅が狭すぎて指定されたUIを配置できないか、存在しない要素や誤ったプロパティを指定してバリデーションにはじかれているケースがほとんどです。
この場合、ログにはui.render (Pane) refusedというメッセージとともに、具体的なプロパティの間違い(例:Box prop "flexDirection" must be one of...)が記録されます。
権限の確認とログの読み方を身につけることで、Modがなぜその挙動をしているのかが手に取るようにわかるようになります。これらの切り分け手順を押さえ、予期せぬエラーにも対応できる安定した拡張機能へと育てていってください。
よくある質問
Q1. Modを開発するためにNode.jsなどのビルド環境は必要ですか?
A. 不要です。Claude CodeはJavaScript(.js)やTypeScript(.ts)のファイルを直接読み込んで実行します。そのため、Node.jsのインストールやバンドラーによる処理、ビルドステップなどを準備する必要はありません。指定のディレクトリにテキストエディタでファイルを作成するだけで、すぐに開発を始められます。
Q2. Claude自身にModのコードを書かせることはできますか?
A. 可能です。Claude Codeには、Modの作成を支援する「plugin-authoring」というスキルが標準で備わっています。対話セッションのなかで「現在のGitブランチ名をプロンプト上部に表示するModを作って」のように指示を出せば、Claudeが専用のフォルダにファイルのひな型やコードを出力してくれます。
Q3. Claude DesktopのWSLセッションでModは利用できますか?
A. Claude DesktopアプリからWSLセッションを開いた場合、現在の仕様ではプラグインの仕組み自体がサポートされていないため、Modも動作しません。
Q4. 最初から入っている組み込みのModを削除することはできますか?
A. 組み込みのMod(Built-in mods)をアンインストールしたり、手動でアップデートしたりすることはできません。
ただし、/pluginコマンドを実行して開く画面の「Installed」タブから、機能ごとに無効化(Disable)することは可能です。
たとえば、/diffコマンドの画面を提供するModや利用統計(テレメトリー)を送るModなどは無効にできます。
ただし、組織のセキュリティポリシーを適用する一部のMod(cc-plugin-sec-defaultなど)は利用者が無効化できないようになっています。
調査手法について
こちらの記事はグラフAIリサーチプラットフォームのSnorbeを使って作られています。Snorbeは研究開発・新規事業向けの調査テーマに応じた幅広い項目のオートリサーチや、ナレッジグラフの構築、構造化レポートの生成ができるAIリサーチツールです。

Screenshot
調査したいテーマを入力するだけで、AIが深堀りすべき観点や広げるべき調査項目をレコメンドしながら、自動でリサーチを進めます。収集した情報はナレッジグラフとして蓄積され、未調査領域(ホワイトスペース)を可視化しながら調査の網羅性を高めていけます。
また、観点マトリクスを30秒・構造化レポートを10分で自動生成する機能があり、出典付きのレポートをMarkdown/PDF形式でエクスポートできます。調査の元データも保存されるため、ファクトチェックや社内共有も容易です。
ご利用をご希望の方は、こちらよりお申し込みください。
また、グラフAIを活用した社内ナレッジ管理や、研究開発・新規事業のリサーチ支援、セルフホスト導入のご相談も受け付けています。お困りの方はお気軽にご連絡ください。
市場調査やデスクリサーチの生成AIエージェントを作っています 仲間探し中 / Founder of AI Desk Research Agent @deskrex , https://deskrex.ai
