
FIELD TEST
Claude Modsの使い方、AIの危険操作を画面で止める新機能をhooksと比べて試した
2026.09.15
家事と子育てのスキマで経営する3方よしAI共創コンサルタントの田中啓之、ひろくん(@passion_tanaka)です。
Claude Code に「Claude Mods」って新機能が来ました。
AIが危ない操作をする直前に、画面で「止める?通す?」と聞いてくれる。しかも、数を覚えていて、再起動しても忘れない。
これ、今までの hooks では出来なかったんです。
で、私は動画のURLを送ったその日に試しました。正確に言うと、AI秘書の凛ちゃんに「試したい」と伝えました(動かしたのは凛ちゃんです)。
この記事に書くのは、動いた画面とログだけ。動画の受け売りは書きません。
AIに仕事を渡し始めたけれど、まだ怖くて見張っている。そんなあなたに向けて書きます。
今回は「Claude Mods は hooks と何が違うのか」を、私の環境で自作の Mod を1本動かして確かめました。書くのは、動いた画面とログだけです。
3行でわかるポイント
- hooks は毎回起動して終わる。Mods は生き続ける。専用ワーカーの TypeScript が、画面を描き、人に聞き、数を覚える。フラグ1つと –plugin-dir で今日試せる
- 危険コマンドを画面で「止める/通す」。tool.call で捕まえて $.ui.ask で聞く。「止める」でAIにエラーが返り、「通す」で本物が走った。claude -p でも deny が効いた
- 料理に例えると、hooks は引き出しの貼り紙。Mods は包丁を出す瞬間に「本当に使う?」と隣で聞いてくれる相棒
AIの「今」を毎日シェアしてる無料コミュニティやってます
GPTs研究会に参加する(無料)
きっかけは動画。「hooks の次」が来た、と思った

2026年9月15日の夜でした。
まさおAIじっくり解説chの動画「【新ハーネス】ClaudeCodeの新機能『Claude Mods』が登場!」です。10分46秒。
このURLをAI秘書の凛ちゃんに送りました。添えた言葉は一言。
「ClaudeCode新機能試したい。よければブログにしたい。」
私は Claude Code を hooks で囲って使ってきました。危ない操作は settings.json の決めごとで止める。その運用です。
でも hooks には、ずっと引っかかりがありました。
止めるか通すかを、事前に全部決めておかないといけない。その場で人に聞いてはくれない。
動画では、その壁を越えた「Mods」が紹介されていました。
AI秘書の凛ちゃんは、まず一次資料を探しに行きました。
見つけたのは GitHub の Issue #91870。「Mods né function hooks」というタイトルで、2026年9月3日に起票されたものです。
そこに書いてあった一文が、なかなか正直でした。
「コミュニティの反応次第で、出荷するかどうかが決まる」。
つまり、まだ正式機能ではない。試すなら今のうち、って話です。
Issue には短い動画が9本ぶら下がっていました。「A hook as a function」「A hook that says no」「Plugins can draw now」。タイトルだけで、やれることの輪郭が見えます。
ソースも公開されています。anthropics/claude-code の mods ディレクトリに、組み込みの Mod が3本(sec-default diff telemetry)と、10,736行の型定義。
手元の Claude Code は v2.1.263。バイナリを strings で覗いたら、CLAUDE_CODE_ENABLE_FUNCTION_HOOKS が7件、ui.render が65件、tool.call が56件ありました。
入っている。動くはずです。
従来の hooks と Mods は何が違うのか。「毎回起動して終わる」から「生き続ける」へ

先に結論を言います。
hooks は、毎回起動して終わる門番。
Mods は、セッションの間ずっと生き続ける相棒。
これが一番の違いです。
従来の hooks は、イベントのたびにプロセスが立ち上がって、仕事をして、終わります。だから「前回の続き」を知りません。
Mods は違います。プラグインの hooks/hooks.json に1行足すだけ。
{
"modules": ["./register.ts"]
}
この TypeScript のモジュールが、専用のワーカーでセッション中ずっと生きています。
モジュールが出すのは register という関数1つ。中で on('イベント名', {絞り込み}, ($, e, next) => ...) と登録していきます。
ここで登場人物を紹介します。
$ はエンジンの窓口。画面を描く $.ui、値を覚える $.store、ファイルを触る $.fs などが並んでいます。
e はイベントの中身。Bash なら、実行しようとしているコマンドがそのまま入っています。
next(e) は「自分より内側を実行して結果をもらう」関数。
で、ここが面白いところ。
next(e) を呼ばずに return すると、本体の代わりに自分が答えられるんです。
{ deny: '理由' } を返せば拒否。{ result } を返せば自前の回答。入力を書き換えて next に渡すこともできます。
ワーカーには Node も fs も network もありません。全部 $ 経由です。
型定義を数えたら、エンジンのイベントは20種類ありました。tool.call ui.render session.start turn.complete など、名前は全部「名詞.動詞」です。
画面の部品も14種類。AskUserQuestion ToolUse Spinner AbovePrompt など、本体が描く部品ごとに ui.render が飛んできます。
Mod はそこに、Box や Text や Button を、プレーンなデータの木として返す仕組みです。
あと1つ、人に聞く窓口があります。$.ui.ask(質問, 選択肢2〜4)。本体の AskUserQuestion のダイアログで聞いて、選んだラベルが文字列で返ってきます。
読んだだけでは絵が浮かばない(私もでした)。だから動かしました。
Claude Mods の使い方①:起動したら、プロンプトの上に自分のバンドが出た

AI秘書の凛ちゃんが作った Mod の名前は「凛ちゃんmod」。TypeScript で約90行です。
ファイルは3つだけ。
.claude-plugin/plugin.json(名前と説明)hooks/hooks.json(さっきのmodules1行)hooks/register.ts(本体)
起動コマンドはこれ。
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude --plugin-dir ../rin-mod
環境変数のフラグ1つと --plugin-dir。それだけです。
私の環境は Claude Code v2.1.263。モデルは Sonnet 5、Claude Max、macOS(arm64)です。
起動すると、まず画面にログが出ました。
そしてプロンプトの上に、マゼンタの枠が出たんです!

凛ちゃんmod が登録しているフックは4つ。AI秘書の凛ちゃんが、最小で組んでくれました。
session.start: 起動ログを出し、前回までの Bash 累計を$.storeから読み戻すtool.call(Bash だけ): 回数を数え、危ないコマンドなら画面で聞くui.render(AbovePrompt だけ): プロンプトの上にバンドを描くturn.complete: 1ターンの集計をトーストで出す
バンドは ui.render の AbovePrompt に登録した関数が描いています。
やっていることは単純です。
まず await next(e) で元の表示をもらう。次に $.ui.resolve(e) から Box・Text・Button を借りる。最後に自分の枠と元の表示を縦に並べて返す。
プロンプトの上に自分の状態表示が住み着く。それを見た時、hooks とは別物だと分かりました。
(正直に言うと、最初の一撃で出たわけではありません。その話は後で書きます)
Claude Mods の使い方②:AIの危険操作を tool.call で捕まえて、「止める/通す」を画面で聞く

ここが本題です。
tool.call に { tool: 'Bash' } の絞り込みで登録します。Bash が走る直前に、必ずこの関数を通ります。
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
const cmd = String(e.command ?? '')
if (DANGEROUS.test(cmd)) {
let answer = '止める'
try {
answer = await $.ui.ask(`凛ちゃんmod: 再帰削除コマンドを実行しますか? → ${cmd}`, {
options: ['止める', '通す'],
header: '凛ちゃんmod',
})
} catch {
answer = '止める'
}
if (answer !== '通す') {
return { deny: '凛ちゃんmod: 再帰削除(rm -r系)はこのセッションでは禁止です。' }
}
}
return next(e)
})
rm -r 系のコマンドなら $.ui.ask で聞く。「止める」なら deny を返して、本物の Bash は走らせない。
で、実際にやってみました。
1回目。echo hello-from-rin。これは普通に通りました。
2回目。rm -rf ./nonexistent-dir-xyz。
画面にダイアログが出ました。

1. 止める
2. 通す
Claude Code 本体の AskUserQuestion と同じ見た目です。Mod が本体の窓口を借りて聞いている。
「止める」を選びました。
すると、モデルには拒否文がそのままエラーとして返りました。
モデルは「拒否された」と正しく報告。バンドは「Bash実行 1回 / 止めた 1回」に変わりました。右下にはトーストで「ターン完了(Bash 1回・止めた 1回)」。
止めた回数が画面に残る。これが地味に効きます。

では「通す」を選んだらどうなるか。
本物の rm -rf ./nonexistent-dir-xyz が実行されました。存在しないディレクトリなので何も起きず、exit 0。モデルの報告も「exit code 0」でした。
つまり、こういう絵です。
危ない操作の直前に、AIが私に聞いてくる。私が「止める」と言えば止まる。「通す」と言えば本物が走る。
hooks でも止めることは出来ました。でも、その場で人に聞き返すのは出来なかった。
ここが変わったんです。
$.store は再起動をまたいで残った。Button は素の JSON だと断られた

覚える方の話です。
$.store.set('bashCalls', 数) で Bash の回数を保存しています。起動時に $.store.get で読み戻す。
セッションを3回立ち上げ直しました。
起動ログの累計は、0 → 2 → 3 と増えていきました。
プラグイン単位でディスクに残っている。hooks では毎回ゼロからだったものが、続きから始まる。
で、格好悪い方も書きます。
Button です。
最初、AI秘書の凛ちゃんは素の JSON で { type: 'Button' } と置きました。
起動したら、こう断られたんです。
しかも、バンド全体が消えました(1行の Button のせいで枠ごと!)。
検証に通らない木は「本体が自分で描く」に落ちる。--plugin-dir で起動していると、その理由が画面に出る。型定義に書いてあった通りの挙動でした。
直し方は、部品を $.ui.resolve(e) から借りること。
const { Box, Text, Button } = await $.ui.resolve(e)
Button({ key: 'reset', label: 'カウンタをリセット', hotkey: '9', onPress: reset })
これで「[ カウンタをリセット ]」が描かれました。
空のプロンプトで 9 を押すと、3回 → 0回に戻る。トーストで「カウンタをリセットしました」。

拒否の理由が画面に出る、って設計は親切だと思います。黙って消えたら、私は一晩悩んでいたかな。
claude -p(非対話)でも deny は効いた

あと1つ、確かめたかったことがあります。
人がいない時はどうなるのか。
claude -p は非対話モードです。画面で聞くことが出来ません。型定義にも「-p では $.ui.ask は reject される」と書いてあります。
だから AI秘書の凛ちゃんは、凛ちゃんmod の中で catch を使い、「止める」に倒しています。聞けないなら止める。
同じ rm -rf を claude -p で投げてみました。
結果の JSON には、モデルの報告としてこう入っていました。
AI秘書の凛ちゃんが書いた deny 文「凛ちゃんmod: 再帰削除(rm -r系)はこのセッションでは禁止です」。そして「フックにより拒否(denied)」。
deny 文がそのまま届いている。人が見ていなくても止まった。
このときのコストは 0.176 ドル、3ターンでした。
無人で動かす時こそ、止める一手が要ります。そこで効いたのは大きい!
注意書き。EARLY ACCESS で、試していないことも多い

ここは正直に書きます。
まず、Claude Mods は EARLY ACCESS です。公式に「API はリリース間で予告なく変わる」とあります。この記事は v2.1.263 での実測です。
公式のドキュメントページ(code.claude.com/docs/en/mods)は、2026年9月15日時点で 404 でした。まだ公開されていません。
出荷されるかどうかも、コミュニティの反応次第。Issue にそう書いてあります。
私が試していないことも、そのまま書いておきます。
Pane(/diffのような横ペイン)InputとSelect$.http.fetchと$.model.completeengine.createで$に名詞を足すこと- Desktop アプリでの表示
prompt.submitの書き換え- Mod を2つ以上同時に載せた時の入れ子順(README の「first registered wraps the rest」は読んだだけ)
あと1つ。公式の README には claude plugin test というコマンドが載っています。
でも手元の v2.1.263 では unknown command 'test' でした。
推測: リポジトリの main は、手元の版より新しい。これは確かめていません。
試したことと、試していないこと。分けて書くのが、この記事の約束です。
よくある質問
Q. hooks を使っていれば、Mods は要らない?
A. 止めるだけなら hooks で足ります。その場で人に聞く、画面に状態を出す、再起動をまたいで覚える。それが要るなら Mods です。AI秘書の凛ちゃんの実測では、全部が動きました。
Q. 今すぐ試せる?
A. Claude Code v2.1.263 で、CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 と --plugin-dir で動きました。ただし EARLY ACCESS です。API は予告なく変わると公式が言っています。
Q. claude -p(非対話)でも止まる?
A. 止まりました。$.ui.ask は非対話だと reject されるので、catch で「止める」に倒しています。deny 文がモデルの報告にそのまま入っていました。
Q. Mod の中で Node や fs は使える?
A. 使えません。ワーカーには Node も fs も network も無く、全部 $ 経由です。画面の部品も $.ui.resolve(e) から借ります。素の JSON で Button を置いたら断られました。
Q. 出荷は確定している?
A. 確定していません。Issue #91870 に「コミュニティの反応次第」と書いてあります。公式ドキュメントページも 2026年9月15日時点で 404 でした。
まとめ。門番が、相棒になる

hooks は、仕事が終わると消える門番でした。
Mods は、画面を描く。人に聞く。数を覚える。
セッションの間ずっと隣にいる相棒です。
私の環境で動いたのは、この4つ。
- 起動したら、プロンプトの上に自分のバンドが出た
rm -rfの直前に「止める/通す」を画面で聞かれ、止めたら本物は走らなかった- Bash の累計が、再起動をまたいで 0 → 2 → 3 と残った
claude -pでも deny が効いた
止める一手が、画面の中に入った。
AIに仕事を渡すのが怖いのは、見えないからです。何をしようとしているか、止められるか、覚えているか。
それが画面に出るなら、あなたも少しは手を離せるかな、と思います。
私は AI秘書の凛ちゃんに頼んで、その日のうちに動かしてもらいました。19時08分に頼んで、19時20分には一通り動いていた。12分です。
EARLY ACCESS なので、明日には変わるかもしれません。
でも「hooks の次」の形は、はっきり見えました。
追伸。
この実験中、サンドボックスの中の Claude が自分を「Rinとして」と名乗りました。
グローバルの CLAUDE.md に書いた AI秘書の凛ちゃんの設定が、--plugin-dir のセッションにも普通に効いていたんです。
Mods とは関係ない話です。でも、自分の設定が思ったより遠くまで届いていて、ちょっと笑いました(設定は見直します)。
COLUMN
包丁を出す瞬間に、隣で聞いてくれる

台所で例えます。
hooks は、引き出しに貼った紙です。「包丁はこの引き出しから出さない」。決めごとを先に書いておく。
守ってはくれます。でも、紙は聞き返してくれない。
Mods は、隣に立っている相棒です。包丁を出す瞬間に「本当に使う?」と聞いてくれる。
私が「使う」と言えば渡す。「やめる」と言えばしまう。そして、今日何回聞いたかを覚えている。
貼り紙と相棒。どちらが安心かは、あなたが決めることです。
私は、相棒の方に一歩寄りました。理由は単純で、一人で見張るのに疲れたからです。
AIに委ねて、人は積み減らす。そのために、止める一手を AI の側に持たせる。
hooks で囲ってきた1年の、次の一手がこれでした。
分身AIひろくんの話は https://bunshin-ai.com/ にまとめています。
関連記事
hooks で囲う運用の元記事。今回の「前提」はここ
自分の環境で実測する、という同じ型の記事
AI秘書チームを組む側の手順
参考リンク
公式アナウンス。動画9本と設計の説明
組み込み Mod 3本と型定義(10,736行)
🧪 今回の検証環境
| 実測日 | 2026年9月15日(JST) |
| Claude Code | v2.1.263(EARLY ACCESS の Claude Mods を CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 で有効化) |
| 実行モデル | Sonnet 5(Claude Max)/ macOS(arm64) |
| きっかけ動画 | 【新ハーネス】ClaudeCodeの新機能『Claude Mods』が登場!(まさおAIじっくり解説ch) |
| 一次資料 | Issue #91870 / anthropics/claude-code/mods |
🎁 無料プレゼント
Aiport(ClaudeCode AIエージェント実践会)
ClaudeCodeでAI秘書+分身AI+AIカンパニーが無料で作れるキット&解説動画をプレゼント!
▶ 無料で入会してキットを受け取る🤖 AI生成コンテンツについて
この記事はAIツール(Claude Code)を活用して制作しています。構成・文章生成にAIを使用し、最終的な内容の確認・編集・公開判断はひろくん(田中啓之)本人が行っています。「分身AIひろくん」(bunshin-ai.com)とは別のコンテンツです。
AI氣道 — 三方よしのAI活用
家事と子育てのスキマで経営する、ひろくんのAIブログ
📺 毎朝無料LIVE配信中!見逃しても大丈夫、アーカイブも完全無料。
記事も完全無料。見逃しても大丈夫!
YouTubeチャンネル: @AIKIDO-GPTs
| 曜日 | 時間 | メインホスト | ゲスト | テーマ |
|---|---|---|---|---|
| 月 | 7:00〜 | ひろくん | ただっち | AI最新ニュース・実験 |
| 月 | 13:00〜 | ひろくん | れんくん(戸野塚蓮) | AI経営術LIVE |
| 火 | 6:30〜 | ひろくん | 公ちゃん | 共感ストーリー×分身AI |
| 水 | 6:30〜 | ひろくん | 高崎さん・たくみくん | AI×開発・教育 |
| 木 | 7:00〜 | ただっち | ともみん | AI×デザイン |
| 金 | 7:00〜 | ただっち | 友くん | AIツール最前線 |
| 土 | 7:00〜 | ただっち | ゆきちゃん | AI×起業・発信 |
| 日 | 7:00〜 / 7:30〜 | WACAコラボ | ひろくん+仲間たち | 生成AI最新ニュースまとめ |
📍 日曜7:00〜のLIVEは無料視聴、7:30〜のZOOM LIVEは登録制です。詳細・登録はこちら
🔥 火曜15:00〜 社長モテる化計画LIVEもやってるよ!