Claude Code Monitor Tool実践ガイド — sleep+ポーリングを卒業し、イベントドリブンな並行ワークフローを手に入れる
Monitor Toolとは何か — 30秒で掴む全体像
従来のBash sleep+ポーリングが抱える3つの問題
Claude Codeでバックグラウンドプロセスを走らせた経験があるなら、こんなパターンに覚えがあるだろう。
# ビルド完了をポーリングで待つ従来パターン
until grep -q 'Build completed' build.log; do sleep 5; done
このアプローチには3つの問題がある。
- 無駄なポーリング回数: 10分のビルドなら約20回のBash呼び出しが発生し、そのたびにコンテキストウィンドウを消費する
- 応答遅延: sleep間隔を長くすればトークンは節約できるが、完了検知が遅れる。短くすればその逆
- 並行作業ができない: ポーリングループの間、Claudeは他の作業を進められない
Monitor Toolが解決すること
v2.1.97で追加されたMonitor Toolは、コマンドのstdoutをストリーミング監視し、出力の各行をイベントとしてClaudeに通知する。Claudeはイベント到着まで別の作業——ファイル編集やコードレビュー——を続行できる。
# After: Monitor Toolによるイベントドリブン監視
Monitor({
command: "tail -f build.log",
description: "ビルド完了待ち"
})
内部メカニズム — stdoutがイベントになるまで
パラメータ仕様
Monitor Toolは4つのパラメータを受け取る。
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
command | string | Yes | — | 監視対象のシェルコマンド |
description | string | Yes | — | 何を監視しているかの説明 |
timeout_ms | number | No | 300,000(5分) | 最大3,600,000(1時間) |
persistent | boolean | No | false | trueならTaskStopまで停止しない |
バッチングとstderr非通知の設計意図
stdoutの各行が1つのイベントになる。ただし、短時間に連続して到着した複数行は1つの通知にバッチされる。これはビルドログのように大量の行が短時間に流れるケースで、イベント洪水を防ぐための設計だ。
重要な点として、stderrは通知を発火しない。エラー出力も監視したい場合は2>&1でstdoutにマージする必要がある。
自動停止とpersistent:trueの使い分け
persistent: false(デフォルト)の場合、イベントが過剰に発生するとランタイムがMonitorを自動停止する。一方、persistent: trueに設定すると、TaskStopを明示的に呼ぶかセッションが終了するまで監視が継続する。
devサーバーのように常駐させたいプロセスにはpersistent: trueが適している。
Monitor({
command: "npm run dev 2>&1",
description: "Next.js devサーバー監視",
persistent: true
})
実践パターン4選 — 現場で使える並行ワークフロー
パターン1: devサーバー監視しながらバグ修正
最も日常的なユースケース。devサーバーをpersistent: trueで監視しておけば、コンパイルエラーが発生した瞬間に検知して修正に着手できる。
# 1. devサーバーをMonitorで起動
Monitor({
command: "npm run dev 2>&1",
description: "Next.js devサーバーのコンパイルエラー監視",
persistent: true
})
# 2. Claudeは通知を待ちつつ、別のファイルを編集できる
# 3. "Failed to compile" が出力された瞬間にイベント到着
# 4. エラー内容を見て即座に修正に着手
正直、この「編集したら勝手にエラーが飛んでくる」体験は、一度味わうと戻れなくなる。
パターン2: ビルドログをtailしながら次のステップを実装
ビルドをrun_in_backgroundで起動し、その出力をMonitorで監視する。ビルド待ちの間にドキュメント更新やリファクタリングを進められる。
# バックグラウンドでビルド実行
Bash({ command: "npm run build 2>&1 > build.log", run_in_background: true })
# ビルドログを監視(5分のデフォルトでは足りない場合がある)
Monitor({
command: "tail -f build.log",
description: "ビルド完了監視",
timeout_ms: 1800000
})
パターン3: テスト実行を監視して失敗時に即修正
テスト出力をMonitorで監視し、FAILが出た時点で修正に着手するパターン。ここで後述するgrep --line-bufferedの罠に注意が必要になる。
Monitor({
command: "npx vitest --reporter=verbose 2>&1",
description: "テスト実行監視 - FAIL検知で即修正"
})
パターン4: デプロイ後のヘルスチェック監視
デプロイ完了後、エンドポイントの応答を定期的に確認するuntilループをMonitorで包む。
Monitor({
command: "until [ \"$(curl -s -o /dev/null -w '%{http_code}' https://myapp.vercel.app)\" = '200' ]; do echo 'waiting...'; sleep 2; done; echo 'HEALTHY'",
description: "デプロイ後ヘルスチェック",
timeout_ms: 600000
})
実戦ハマりポイント5選
1. grep --line-bufferedを忘れると数分遅延する
これが最も多いハマりポイントだと思う。grepやawkをパイプで挟むと、デフォルトのフルバッファリングにより出力が溜め込まれ、数分間イベントが届かなくなる。
# NG: バッファリングで遅延
tail -f app.log | grep 'ERROR'
# OK: 行バッファリングに切り替え
tail -f app.log | grep --line-buffered 'ERROR'
# OK: stdbufでも同様に解決できる
tail -f app.log | stdbuf -oL grep 'ERROR'
2. stderrが通知されない罠と2>&1の注意点
前述のとおりstderrは通知を発火しない。さらに、リダイレクト順序を間違えるとstderrが漏れる。
# OK: コマンドのstderrをstdoutにマージしてからパイプ
command 2>&1 | grep --line-buffered 'pattern'
# NG: grepのstderrをマージしているだけ(commandのstderrは消失)
command | grep 2>&1 'pattern'
3. timeout_msのデフォルト5分で長時間ビルドが切れる
デフォルトのtimeout_msは300,000ms(5分)。CIやフルビルドでは余裕を持って設定する。
Monitor({
command: "npm run build 2>&1",
description: "フルビルド監視",
timeout_ms: 1800000 // 30分
})
4. イベント洪水による自動停止
大量のログを吐くプロセスをフィルタなしで監視すると、ランタイムがMonitorを自動停止する。対策は2つ。
- grepでフィルタしてから監視する(
grep --line-buffered 'ERROR|WARN') tail -n 0 -fで新規行のみを対象にする(既存ログの読み込みを防ぐ)
5. Plugin Monitor(monitors.json)の自動armバグ
v2.1.105で追加されたPlugin Monitor機能(monitors.jsonで宣言的にMonitorを定義する仕組み)には、v2.1.118時点で自動armが無音で失敗するバグが報告されている(GitHub Issue #52245)。Plugin Monitorを使う場合は、手動でarmすることで回避できる。
Monitor vs Hooks vs /loop — 使い分け早見表
| 観点 | Monitor Tool | Hooks | /loop |
|---|---|---|---|
| トリガー | プロセスのstdout出力行 | ツール呼び出しの前後 | 時間間隔 |
| ユースケース | ビルド監視、devサーバー、ログtail | ESLint自動実行、テスト自動実行 | デプロイ状況の定期チェック |
| Claudeの判断 | あり(イベント内容を見て対応) | なし(確定的に実行) | あり(状況に応じて次の行動を決定) |
| 並行作業 | 可能(イベント待ち中に別作業) | 不可(同期実行) | 不可(ループ占有) |
| 典型例 | tail -fでエラー検知→修正 | Edit後にフォーマッタ実行 | 5分ごとにCI結果を確認 |
使い分けの判断基準は3つ。
- トリガーは何か: プロセスの出力行ならMonitor、ツール呼び出しならHooks、時間経過なら/loop
- Claudeの判断が必要か: 出力内容に応じてアクションを変えるならMonitorか/loop。毎回同じ処理ならHooks
- プロセスのライフサイクルと一致するか: devサーバーのように常駐するプロセスに紐づくならMonitor(persistent: true)が最適
まとめ — ポーリング脳からイベントドリブン脳へ
Monitor Toolが変えるのはコードの書き方ではなく、思考モデルだ。「定期的に確認しに行く」から「通知が来たら反応する」へ。これはサーバーサイド開発で言えば、ポーリングAPIからWebSocketへの転換と同じ構造的な変化だ。
まずは1つの並行ワークフロー——devサーバーを監視しながらバグ修正——から試してみてほしい。grep --line-bufferedと適切なtimeout_ms設定さえ覚えておけば、ほとんどのハマりポイントは事前に回避できる。
「ビルド終わったかな?」と自分で確認しに行く時代は、もう終わりにしよう。
