Claude Code 2.1.287(2026-10-01)で mod が入りました。changelog の1行目はこれです。
Added Claude Mods: plugins may now modify deeper behavior
mod はプラグインの中で動く JavaScript の関数です。設定ファイルの hook と違って
Claude Code のプロセスの中で動き、ツール呼び出し・プロンプト送信・画面描画に割り込めます。
1本書いて、21回測りました。
mod は何を捕まえたか ツール呼び出し・プロンプト送信・スピナー描画
どれも1行のフックで取れて、ファイルに書き出せた
動く版 Claude Code 2.1.286 3/3 動いた ← 公式は 2.1.287 以降と書いている
Claude Code 2.1.285 0/3
--safe-mode 3/3 止まった
検証環境: Windows 10 / Claude Code 2.1.282・283・285・286・287 を隔離導入 /
claude -p --plugin-dir/ 全ラン設定ディレクトリ使い捨て(コールド) / 測定は 2026-10-02
3ファイルで動く
mod はプラグインなので、必要なのは3つです。plugin.json(名前)、
hooks.json({ "modules": ["./register.js"] } の1行)、そして本体。
本体はこれだけです。ツール呼び出しとプロンプト送信を数え、ターンの終わりにファイルへ書くものです。
let calls = 0
let prompts = 0
export function register(on) {
// 実際にはこの前に session.start フックも1つ置いています(記録開始の印)
on('tool.call', async ($, e, next) => {
calls += 1
$.ui.invalidate('ui.render')
return next(e)
})
on('prompt.submit', async ($, e, next) => {
prompts += 1
return next(e)
})
on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
return next({ ...e, props: { ...e.props, suffix: ' / tool calls: ' + calls } })
})
on('turn.complete', async ($, e, next) => {
const r = await next(e)
await $.fs.write('mod-evidence.txt',
'tool.call=' + calls + '\nprompt.submit=' + prompts + '\n')
return r
})
}
$ が mods API です。next(e) を返せばそのまま流し、返さなければイベントを乗っ取れます。
読み込みは claude -p "..." --plugin-dir ./first-mod の1行です。
入れる前に、何をするか一覧できる
claude plugin validate は、実行せずに中身を読んで出します。
❯ ./register.js hooks: session.start, tool.call, prompt.submit, ui.render{component=Spinner}, turn.complete
❯ ./register.js calls: $.fs.write, $.ui.invalidate
hooks: が拾うイベント、calls: が呼ぶ API です。上の session.start は、本文に載せていないフックのぶんです。
$.process.run や $.http.fetch が並んでいたら、その mod はプログラムを起動し、ネットワークに出るということです。
公式も、mod について明確に書いています。
A mod is code that runs with your permissions. It can read and write your files,
start processes, and make network requests.
mod はサンドボックスされません。 他人の mod を入れる前に、この2行は見たほうがよいです。
測った結果
同じ課題(ファイルを読んで行数を答える)を各3回。判定はmod が書き出したファイルの中身です。
| Claude Code の版 | mod | 動いたか |
|---|---|---|
| 2.1.287 | あり | 3/3 |
| 2.1.287 | なし(対照) | 0/3 |
| 2.1.286 | あり | 3/3 |
| 2.1.285 | あり | 0/3 |
| 2.1.283 | あり | 0/3 |
| 2.1.282 | あり | 0/3 |
| 2.1.287 | あり+--safe-mode
|
0/3 |
mod は3回とも、ツール呼び出しとプロンプト送信を捕まえてファイルに書き出しました。
mod を外すと証拠ファイルは作られません。
公式が書いている対応版は、1つずれている
ドキュメントにはこう書かれています。
Mods require Claude Code v2.1.287 or later, and they're on by default.
Claude Code 2.1.286 でも3回とも動きました。 2.1.285 では動きません。
実際の開始は Claude Code 2.1.286 です。
changelog で「Added Claude Mods」と書かれたのは 2.1.287 のほうなので、
その1つ前では告知なしに動く状態だったことになります。
--safe-mode は効いた
公式が挙げている止め方のうち --safe-mode を試すと、3回とも動きませんでした。
他の設定も一緒に落ちるので、切り分けに使えます。
言えないこと
- 測ったのは 2026-10-02 の1日、各3回。 21ランとも一貫していましたが、ベンチマークではありません
-
Claude Code 2.1.286 で動いた理由は分かりません。 早期アクセスの環境変数
CLAUDE_CODE_ENABLE_FUNCTION_HOOKSが
ありましたが、測定ではCLAUDE_*を全て外しています。 それでも動きました -
止め方は
--safe-modeだけ試しました。disableAllHooksや組織向けの設定は未測定 -
--plugin-dirで読ませただけです。 マーケットプレイス経由の導入は試していません -
描画は未確認。
-pでは mod の描画が出ないと公式にあり、スピナーへの追記は目視していません - 使ったのは
$.fs.writeと$.ui.invalidateだけ。他の API は呼んでいません
まとめ
-
mod は3ファイルで動く。
plugin.jsonとhooks.jsonと本体1つ - ツール呼び出し・プロンプト送信・画面描画を、1行のフックで捕まえられた。 ファイルにも書き出せる
claude plugin validateが、入れる前に「拾うイベント」と「呼ぶ API」を一覧する- mod はサンドボックスされず、自分の権限で動く(公式の記述)
- 公式が書いている対応版は1つずれている。 実測では Claude Code 2.1.286 から動く
--safe-modeは3回とも止めた
設定ファイルの hook とは別物です。 hook は外でスクリプトが走りますが、
mod は Claude Code の中でイベントそのものを書き換えられます。
入れる前に中身を見る手順も要るようになりました。
関連記事
- スキルの名前を verify にするだけで、Claude Code はコミット前にそれを実行する — changelog とドキュメントの食い違いを測った回
- Claude Code のスキルを47本運用して測った、7つのこと — スキルを増やすと何が起きるかを測った回
JQITのエンジニアの95%以上は未経験からの採用です。
よければコーポレートサイトにも遊びに来てください。
エンジニア採用も行っています。もしご興味あれば覗いてみてください。
▶ 採用サイト