modで何ができるのか知りたくて作りました
2026年10月1日のClaude Code v2.1.287で、mod(フックを関数で書くプラグイン)が使えるようになりました。何ができるのか把握したかったので、まずClaudeにGitHubで公開されている事例を調べてもらいました。200件ほどあって、使用量やコストのメーター、ペットやゲーム、危ない操作を止めるガードあたりが多かったです。
その中で、実務でこういうのがあったら嬉しいかもと思ったのが「Claudeがコードベースのどこを見たかを見えるようにする」ことでした。Claudeに何か聞いて答えが返ってきたとき、そのファイルを読んだのか、grepで一致した数行を見ただけなのか、どこを一度も開いていないのかは、会話のログを追うか、聞いてみないとわかりません。
そこで作ったのがtouch-mapです。
この記事でわかること
- Claude Codeのmodでできること・できないこと
- Claudeが触ったファイルを「全部読んだ・一部だけ読んだ・名前だけ見た」に分けて表示するmod(touch-map)の作り方と、作るときに詰まったところ
- 実際に使ってみて、Claudeがどこまでコードを見ていたか
前提
- Claude Code v2.1.287以降(modが使えるバージョン)
- macOSのターミナルで動作を確認しています
modはClaude Codeの中で起きることに、自分の関数を差し込める仕組みです
ツールの呼び出しやプロンプトの送信、画面の描画が起きるたびに、自分で書いた関数が呼ばれます。
できること
- ツールの呼び出しやプロンプトを、見る・書き換える・代わりに処理する
- ペインやプロンプトの上の帯、スラッシュコマンドを足す
- Claude Code自身の画面の一部を描き直す
できないこと
- 許可を求める確認画面は変えられない
- 描画が出るのはターミナルとデスクトップアプリだけ(VS Codeのチャット欄などでは出ない)
- 描けるのは用意された部品(文字、ボタン、入力欄など)の組み合わせだけで、HTMLは使えない
- 画像はどこでも出せるわけではない
仕組みや作り方は、次の記事が詳しいです。
- Mods overview - Claude Code Docs
- Claude Code の mods とは? 画面もツール呼び出しも自分好みに変えられる新しい拡張
- Claude Code mods 入門、TypeScript で挙動と UI を拡張する
touch-mapが使っているのは、主にツールの呼び出しを見ることと、ペインを足すことです。
見たファイルを7つの状態に分けて、ツリーとマップに出します
Claudeがこのセッションで触ったファイルを、次の状態に分けて記録します。1つのファイルはいちばん深い状態で表示します。
| 状態 | 意味 |
|---|---|
| created | 作った |
| edited | 書き換えた |
| read | 全部読んだ |
| partial | 一部の行だけ読んだ(grepの一致行、行範囲を指定したRead) |
| listed | 名前だけ見た(ls、grep -l) |
| deleted | 消した |
| auto | CLAUDE.mdなどが自動で読み込まれた |
ペインには、ファイルのツリーとアクティビティマップの2つを出しています。
- ツリー:Claudeが触ったフォルダだけを開いて、中のファイルまで並べます。触っていないフォルダやファイルは、名前だけを1行にまとめます。一部しか読んでいないファイルには、どのあたりの行を読んだかを横線で示します
- アクティビティマップ:リポジトリのファイルを、エディタのファイル一覧と同じ順に小さな四角で並べたものです。Claudeがファイルに触ると、その四角が白く光り(サブエージェントのときは黄色)、少しして状態の色へ徐々に変わります
詰まったところ
- Bashのコマンドは、文字列と出力から推測するしかありません。ヒアドキュメントの
>やcdの先を取り違えたので、今いるディレクトリはClaude Codeが覚えているもの($.session.cwd())を使っています - Readは行範囲を指定できるので、結果に入っている開始行・行数・全体の行数で、全部読んだか一部かを判定しています
- Pythonなどのスクリプトでの書き換えは見えないので、実行後の
git statusで、更新時刻がコマンドの実行中だったファイルを拾っています - Claudeが
git worktreeで作った作業場所はリポジトリの外に見えるので、本体の同じパスとして数えています -
/clearでmodの状態が作り直されるので、セッションが終わるときのイベント(session.end)で保存しています - ボタンから開いたペインが人の操作として扱われず、狭い画面で表示されなかったので、ボタンが押されたイベント(
ui.press)の中で開いています
使ってみると、Claudeが見ている範囲は思ったより広かったです
個人で作っているUnityのゲームで試しました。「よく触っている部分でリファクタリングできそうなところを調べて」と頼んだときは、304ファイル中125ファイルに触れていて、全部読んだのが41、一部だけが44、名前だけが39、作ったのが1でした。
逆に、「ユニットの処理を書いているコードはどこ?」と聞いたときは、ファイルを1つも開かず、自動で読み込まれたAGENTS.mdの情報だけで答えていました。ペインにはnothing touched yetと◆auto 2だけが出ていました。
Claudeがどれだけの範囲でソースコードを見ているかは、非常にわかりやすくなりました。一方で、これだけ見ている範囲が広いと、目的のこのファイルは見たのかを画面から探すのは結構大変そうです。必ず見てほしいファイルがあるなら、表示で確かめるよりハーネス(CLAUDE.mdやフックの側)で担保するほうが良いと思いました。
パフォーマンスとデザインは、別のClaudeに任せました
ターミナルの画面分割にHerdrを使っていて、Claudeから別のペインのClaudeを起動して指示を出せます。パフォーマンスチューニングとデザインは、この方法で別のClaudeに任せました。
パフォーマンスチューニングは、指示書を渡して約40分で終わりました。5万ファイルのリポジトリを合成して測り、元の版と描画結果が変わらないかを35か所で突き合わせながら直していました。
| 対象 | 修正前 | 修正後 |
|---|---|---|
| 光る演出のタイマー1回 | 2.42ms | 0.18ms |
| 新しいファイルができた直後の描画 | 126.6ms | 19.0ms |
| ペインの描画1回 | 28.5ms | 18.4ms |
grep -rn 2万行の走査 |
50.4ms | 11.9ms |
デザインは/designを使って見た目の案を出してもらい、その中から今の表示に決めました。
正直、自分では時間や知識的に難しいところなので、結果だけ良くなればいいと思っていました。私くらいしか使わないものなら、この進め方でよかったと思います。実際良くなりました。
良かったら試してみてください
インストールはシェルから2行です。Claude Code 2.1.287以降が必要です。
claude plugin marketplace add y-hirakaw/claude-code-mods
claude plugin install touch-map@y-hirakaw-mods
新しいセッションで一度/touch-mapを実行すると、ペインが開きます。外部には何も送らず、実行するのはprintenv HOME・git ls-files・git worktree list・git statusだけです。
modは、Claude Codeの中で起きていることを自分の見たい形で出せるのが面白いと思いました。
(おまけ)仕組み:イベントで記録を更新し、記録が変わるとペインが描き直されます
作りを詳しく知りたい方向けに、データの流れをまとめておきます。コードはリポジトリのtouch-map/hooks/register.tsxです。
modの関数は、イベントごとに登録します(on('tool.call', ...)のように書きます)。ツールの呼び出しのイベントでは、ツールを実際に動かしたあとの結果を受け取れるので、Readなら結果に入っている行範囲を、Bashならコマンドと出力を見て状態を決めます。
決めた状態は、modの状態($.state)に書き込みます。ペインを描く関数はこの状態を読んで画面の部品を返すだけで、状態が書き換わると、それを読んでいる描画が自動でやり直されます。光る演出だけは毎回ペイン全体を描き直すと重いので、タイマーでマップの部分だけを塗り直しています。
| きっかけ(イベント) | 画面で起きること |
|---|---|
ツールの呼び出し(tool.call) |
触ったファイルの色が変わり、マップの四角が光る。nowの行が変わる |
@ファイルの添付(session.append) |
そのファイルが全部読んだ状態になる |
CLAUDE.mdなどの読み込み(classic.InstructionsLoaded) |
ペインの一番下の◆の行に出る |
/clear・終了(session.end)、compact |
記録を保存して、空から数え直す |
フォルダの▾・▸や、最小化した帯の[ open ]を押す(ui.press) |
フォルダを開閉する。ペインを開く |
この記事はZennにも投稿しています。
