Monitorのpersistentが廃止され30分で監視が切れる理由
Claude CodeのMonitorはv2.1.271でpersistentを廃止し、最長30分のデッドラインと再アーム通知に変わりました。スキーマ上限との食い違いと回避策も扱います。
Claude CodeのMonitorツールから、期限なしで監視を続けられるpersistent: trueが消えました。v2.1.271で、Monitorの監視はすべて最長30分(-p実行では10分)のデッドラインを持ち、期限が来るとClaudeに再アームを促す通知が届く仕組みに変わっています。公式の仕様変更であって不具合ではありませんが、GitHub issueではtimeout_msのスキーマ上限が実際の挙動と食い違ったままだと報告されています。
Monitorのpersistentは何が変わったか
Monitorツールは、Claudeがログの監視やCIステータスのポーリングをバックグラウンドで続け、変化があったときだけ会話に割り込んで知らせる仕組みです。基本的な使い方とWebSocketソースの仕様はClaude Code Monitorツールの使い方で扱っています。
v2.1.271より前は、persistent: trueを指定すればtimeout_msの期限が来ても監視が終了せず、TaskStopで明示的にキャンセルするまで動き続けました。v2.1.271の公式changelogは、この変更を次のように説明しています。Monitorの監視を常にデッドライン付きにし(最長30分、単発の-p実行では10分)、Claudeに再アームを促す通知を送る形に変更しました。期限なしのpersistentオプションは、この変更で置き換えられています。persistentはコマンド実行版・WebSocket版のどちらからも消えました。
現行の公式ドキュメントによれば、Monitorが持つ期限は既定で5分、Claudeが延長を求めても最長30分、-pでの単発実行では最長10分です。期限に達すると監視はいったん終了し、Claudeは通知を1回受け取ります。まだ必要なら、そこから改めて監視を立ち上げ直す運用になります。
同じv2.1.271のchangelogには、もう一つ関連する項目が並んでいます。auto mode下のサンドボックスで、Bash・PowerShellに加えてMonitorにもコマンド単位のallowed_domainsが追加されました。監視コマンドが必要とするホストだけをその場でレビューし、それ以外のホストへの接続は拒否する仕組みです。persistentの廃止と同じリリースで、権限まわりの見直しも同時に進んでいたことがうかがえます。
30分デッドラインとtimeout_msスキーマの食い違い
問題は、timeout_msの入力スキーマがこの30分という実際の上限に追随していないことです。issue #94393の報告者は、まずtimeout_ms: 86400000(24時間)を指定する例を試しています。この値はInputValidationError: timeout_ms must be <= 3600000で即座に拒否されました。上限値の3600000(60分)まで下げると呼び出し自体は成功するものの、確認メッセージは「30分で期限切れ」と表示される現象を報告しています。
同じ現象は特定のプラットフォームに限った話ではないようです。hulm1818gmのコメントによれば、Anthropic API経由ではなくClaude Codeサブスクリプション経由、Windows 11上でも同じ挙動が再現しました。実行基盤や契約形態を問わず起きる可能性があります。
コメント欄では、v2.1.272にバンドルされた型定義sdk-tools.d.tsの内容も引用されています。timeout_msのdocstringは「既定値は300000ms。1800000ms(30分)を超える指定は1800000msに切り詰められる」と実態通りに更新済みでしたが、バリデーションのmaximumは3600000のままでした。受け付けられる値と実際に守られる値が、同じ型定義の中でずれています。加えてMonitorInputからpersistentフィールド自体が削除されている一方、MonitorOutput側には「persistentのときtimeoutMsは0」という説明が残っています。意図的な廃止というより、削除し忘れに近い状態です。
セッションの一時停止とは別の話
issue #94393の報告者は、セッションの一時停止やidle状態でバックグラウンドタスクが失われる既知の別issue(#63023、#65968)を挙げています。そのうえで、今回の報告はそれらとは切り分けて読んでほしいと述べています。報告に含まれる状況では、セッションは数時間にわたって継続的に稼働しており、Monitor自身が生成する期限切れ通知を30分おきに受け取り続けていました。つまりセッションがidleになっていたわけではなく、稼働中であっても同じ30分の上限が適用され続けたという内容です。idle判定によるタスクの喪失とは別に、Monitorの監視そのものに無条件の寿命上限が組み込まれているのではないか、という切り分けになっています。
同時期に追加されたWebFetchの期限にはオプトアウトがある
利用者の報告でpersistentが効かなくなったとされるv2.1.268のchangelogにも、Monitorに触れた項目はありません。ただしWebFetchについては、「応答を返さないまま接続を開き続けるサーバーへの対策として、300秒でフェッチを打ち切るようにした」という項目があります。この機能にはCLAUDE_CODE_WEBFETCH_DEADLINE_MSという環境変数が用意されており、0を指定すれば期限そのものを無効化できます。
issueのコメントでは、同じリリースで追加された類似の期限のうち、WebFetch側にはこうしたオプトアウトが用意されている点が指摘されています。一方でMonitorのpersistentには、それに相当する選択肢がありません。継続的な監視が必要な利用者にとっては、期限を受け入れるか、期限のない別の手段(後述するプラグインのmonitors)に切り替えるかの二択になっている状態です。
いつから起きていたか — changelogと利用者の体感のずれ
changelogが仕様変更を明記したのはv2.1.271ですが、コメント欄の複数の報告を突き合わせると、利用者が体感した変化はそれより前から始まっていたようです。
| バージョン | 報告されている状態 |
|---|---|
| v2.1.267 | 報告されている状態persistentが有効に機能し、無期限の監視が実際に動作したとの報告 |
| v2.1.268〜v2.1.270 | 報告されている状態persistentがエラーを出さずに無視され、期限+再アームの挙動に切り替わっていたとの報告。この間のchangelogにMonitor関連の記載はない |
| v2.1.271 | 報告されている状態changelogで正式に仕様変更として明記。デッドライン+再アーム通知に統一 |
| v2.1.272 | 報告されている状態型定義のdocstringは30分上限に追随したが、スキーマのmaximumは3600000のまま |
| v2.1.280 | 報告されている状態同じ食い違いが再現したとの報告。issueはopenのまま |
v2.1.268からv2.1.270までのchangelogを見ても、Monitorやpersistentに触れた項目は見当たりません。それでも複数の利用者が、v2.1.268あたりからpersistentが効かなくなったと報告しており、公式なアナウンスより先に挙動が変わっていた可能性があります。v2.1.267に固定して検証したという報告では、そのバージョンでは無期限の監視が実際に30分を超えて動いたともあります。
再アーム前提が引き起こす副作用
デッドライン+再アームという設計は、Claudeが定期的に「まだ必要か」を判断し直す機会にもなります。一方で、コメント欄では次のような副作用が報告されています。
- イベントの取りこぼし: 外部プロセスが追記するログファイルをtailするような監視では、期限切れから再アームまでの間に書き込まれた行を拾えません。監視が追いつく手段がないため、その間の変化はそのまま失われます
- トークンコストの増加: イベントの有無にかかわらず一定間隔で再アームが発生し、イベント通知そのものより再アームの往復コストが上回るケースがあります
- 再アームが確実に行われるとは限らない: Claudeが期限切れの通知を受け取っても、別の作業を優先して再アームを後回しにすることがあります
コメント欄は、これらを避ける実務上の回避策として、終了条件を自前で持つコマンドをBashのrun_in_backgroundで起動する方法を挙げています。プロセスの終了そのものがセッションを再度呼び出すきっかけになるため、常時ストリームを受け取り続ける代わりに、1回の起動につき1回の通知を受け取る形になります。実際にissueのコメントで比較に使われたのは、一定時間後に完了を出力するだけのコマンドでした。
# 指定時間だけスリープしたあとdoneを出力し、プロセス自体が終了する
sleep 2400; echo doneログファイルの追記を待つような監視をこの形にするなら、tailをそのままパイプにつなぐのではなく、完了マーカーが出るまでポーリングして自分で抜けるループにする必要があります(tail | headの組み合わせはhead側が先に終了してもtail側は書き込み待ちで残り続けるため、run_in_backgroundの完了通知は次の書き込みまで来ません)。
Bashのバックグラウンド実行の仕組み自体はClaude Codeバックグラウンド実行で扱っています。
回避策 — プラグインのmonitorsは期限を持たない
Monitorツールとは別に、プラグインがmonitors/monitors.jsonで宣言する監視の仕組みがあります。公式ドキュメントは、このcommandを「セッションの作業ディレクトリで常駐実行するシェルコマンド」と説明しており、Monitorツールのような期限は明記されていません。設定方法・whenトリガー・変数展開の詳細はmonitors.jsonでプラグインにバックグラウンド監視を組み込むで扱っています。
experimental.monitorsの各エントリはname・command・descriptionが必須、whenは省略時"always"(セッション開始時に起動)です。最小構成は次のようになります。
{
"experimental": {
"monitors": [
{
"name": "ci-watch",
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/watch-ci.sh",
"description": "CIステータスの変化",
"when": "always"
}
]
}
}issueのコメントでは、hassaansがv2.1.280上での比較検証も報告しています。「2400秒スリープしてからdoneを出力する」という同じコマンドを、Monitorツール(timeout_ms: 3600000)とプラグインのmonitorsの両方で走らせています。Monitorツール側は30分で期限切れとなり、doneは出力されませんでした。一方のプラグインのmonitorsは30分32秒の時点でも生きており、40分00秒でdoneを出力して正常終了したとのことです。
ただし回避策としての制約もあります。公式ドキュメントによれば、プラグインのmonitorsは対話的なセッションでのみ動作し、-p実行では使えません。Amazon Bedrock、Google CloudのAgent Platform、Microsoft Foundryの各基盤でも動作しないと明記されています。コマンドはmonitors.jsonにあらかじめ書いておく固定のものなので、Claudeが会話の流れの中で監視対象を都度決めて起動する、という使い方はできません。
| 用途 | 向く仕組み | 理由 |
|---|---|---|
| その場の調査で一時的に監視したい | 向く仕組みMonitorツールへの対話依頼 | 理由すぐ始められるが、最長30分で期限切れになる |
| 数時間以上、無期限に監視を続けたい | 向く仕組みプラグインのmonitors | 理由期限の記載はないが、対話的セッション専用でBedrock/Google Cloud Agent Platform/Microsoft Foundryでは動かない |
-p実行中に監視したい | 向く仕組みMonitorツール(最長10分) | 理由プラグインのmonitorsは対話的セッション専用 |
まとめ
Claude CodeのMonitorツールはv2.1.271でpersistentオプションを廃止し、最長30分・-p実行では最長10分のデッドライン制に一本化されました。GitHub issue #94393では、2つの点が報告されています。timeout_msのスキーマ上限が3600000のまま実際の挙動(30分)と食い違っている点と、persistentフィールドが入力側からだけ削除されている点です。issueはopenのままで、修正の見通しは示されていません。外部イベントを取りこぼしなく長時間監視したい場合は、期限の記載がないプラグインのmonitors.jsonが回避策になります。ただし対話的セッション専用で-pでは使えない制約もあるため、用途に応じてMonitorツールと使い分ける必要があります。