Show HN: agent-usage-guard – Claude Codeの利用時間ウィンドウを保護するClaude Code用MOD
Show HN: agent-usage-guard – a Claude Code mod to protect your usage window (github.com)
要約
agent-usage-guardは、Claude Codeの利用時間ウィンドウの超過を防ぐためのMODです。リアルタイムの利用状況を監視し、サブエージェントの大量起動、コンテキストの頻繁な更新、リトライループなどを検知して、ユーザーに確認を求めたり、処理を制限したりします。これにより、意図しない高額な利用料金の発生を防ぎます。
全文翻訳
agent-usage-guard
Claude Codeが5時間の利用時間ウィンドウを10分で使い切るのを止めます。
agent-usage-guardはClaude CodeのMODです。Claude Code内で実行され、高額な利用が発生する前にそれを抑制します。プランのリアルタイム利用状況を読み取り、サブエージェントのファンアウト、重いコンテキストの切り替え、リトライループを抑制します。
ガードがロードされたClaude CodeのインタラクティブUIから録画されました。スクリプト化されたローカルAPIがClaudeの代わりを務めるため、セッションとトークンカウントはステージングされており、利用料金は発生しません。画面上のすべての質問はガード自身のものです。Northstarフィクスチャから再構築できます。
利用料金が発生した後ではなく、その前に動作します。エージェントが開始される前、プロンプトが送信される前、またはツール呼び出しが実行される前です。エージェントの制限は、マシン上のすべてのClaude Codeセッションで維持され、ファンアウトと重いコンテキストは、制限に近い場合だけでなく、あらゆる利用レベルでキャップされます。キーボード操作中は、Claude Code独自の質問ダイアログでユーザーに尋ねます。誰も答えられない場合、拒否してClaudeにその理由を伝え、モデルが待機、バッチ処理、または停止できるようにします。/agent-guard reportは、その動作を表示します。
- プラン認識。 Claude Codeが報告する5時間および週ごとの使用率を読み取り、ウィンドウの終盤をユーザーのために確保します。
- 1回の回答でしばらく持続。 承認は、リセットまたはタイムアウトするまでその条件を解除しないため、同じ質問が繰り返し行われることはありません。
- ローカルでプライバシーを最小限に。 ネットワークなし、プロセスなし。カウントと大まかなバケットを保存し、プロンプトテキスト、ツール入力、またはモデル出力は決して保存しません。
- フェイルオープン。 フックのいずれかが失敗した場合、イベントは続行されます。壊れたガードがセッションを壊すことはありません。唯一の例外は、時間内に判断できなかったエージェントで、拒否されるためClaudeが再開します。
インストール
Claude Code v2.1.287以降でこれらのコマンドを実行してください:
/plugin marketplace add rbartoli/agent-usage-guard
/plugin install agent-usage-guard@agent-usage-guard
/reload-plugins
その後、/agent-guardを実行して、ガードが何を見ているかを確認します。MODはデフォルトでオンになっています。概要にMODのオン/オフを切り替える設定がリストされています。
なぜこれが存在するのか
ある午後、私はClaude Codeに最大負荷でリサーチプロンプトを与えました。それは394件のサブエージェント呼び出しを生成し、そのうち341件が同時に実行され、10分間で84MのコンテキストトークンをAPIに送信しました。セッション終了: "Claude利用制限に達しました。"ウィンドウがリセットされるまでロックアウトされました。
それは一度きりの出来事ではありませんでした。私自身の60日間のログには、166回の10分間のウィンドウでのエージェントバーストと12回のロックアウトがありました。失敗モードは増幅します: 大きなコンテキスト × 高速なツールループ × 並列エージェント × ブラインドリトライ。以下の各保護機能は、1つの要因を削除します。
そしてそれは私だけではありません: 単一プロンプトからの339件のサブエージェント、週ごとのMaxプランの半分を再帰的スポーニングで消費、およびチャットセッションの約15倍のトークンを使用するマルチエージェント実行。
何をするか
| エリア | ルール | デフォルト | 実行内容 |
|---|---|---|---|
| プランウィンドウ | ウィンドウがこれだけいっぱいになると、新しいエージェントは承認が必要 | 80% | 質問する; 承認はウィンドウがリセットされるまで有効 |
| ウィンドウがこれだけいっぱいになると、新しいエージェントは拒否される | 95% | 拒否する | |
| 5時間ウィンドウがこれだけ速く上昇すると、新しいエージェントは承認が必要 | 10分あたり20ポイント | 質問する | |
| エージェント | マシン全体で同時に実行されているエージェント | 4 | 質問する |
| このマシンでウィンドウあたりに開始または再開されたエージェント | 12 | 質問する | |
| このマシンでウィンドウあたりに処理されたサブエージェントトークン | 10M | 質問する | |
| サブエージェントはそれ自身のサブエージェントを開始できない | 深さ1 | 拒否する | |
| コンテキスト | Claudeは一度だけ、ターンを制限するように指示される | 300kトークン | プロンプトに注釈を追加する |
| これだけのコンテキストを再読み込みするプロンプト | 500kトークン | 質問する: コンパクトにしてから送信、それでも送信、またはキャンセル | |
| 会話またはエージェントがこれだけの量を持っている間に10分あたりのツール呼び出し | 400kで20コール | 質問する: 続行、このターン後にコンパクト化、または停止 | |
| キャッシュが期限切れになるほど長時間アイドル状態だった重いセッション | 150kトークン、1時間アイドル | キャッシュを再書き込みする前に質問する | |
| ループ | 他の呼び出しがないまま、同じツール呼び出しが繰り返し失敗する | 3回の同一失敗 | 同一のリトライを拒否する |
| 10分以内に拒否されたエージェント呼び出し | 5 | 10分間エージェントのスポーンを一時停止する |
エージェントには、サブエージェント、エージェントチームのチームメイト、ワークフローエージェント、およびSendMessageで再開された完了したサブエージェントが含まれます。各ツール呼び出しは、それを生成したループのコンテキストで判断されるため、小さなサブエージェントはメイン会話のサイズを継承しません。
質問する場合。 質問はClaude Code独自のダイアログに表示され、Claudeがユーザーに何かを尋ねる際に使用するもので、呼び出しは回答を待ちます。並列で開始されたエージェントは、開いている間は保留され、ユーザーが回答するとClaudeが再開します。許可した場合、その条件はしばらく有効です。プランウィンドウはリセットされるまで、重いコンテキストは縮小するまで(ツール呼び出しの場合は最大1時間)、エージェントカウントは10分間有効です。拒否または閉じた場合、Claudeは次の10分間(AGENT_GUARD_WINDOW_SECONDS)エージェントを開始しないように指示され、その間は再度尋ねられません。入力された単語はClaudeに届くため、「代わりに俳句エージェントを使用する」と答えることができます。
誰も答えられない場合。 claude -p、Agent SDK、およびdontAskモードでは、エージェントまたはツールゲートが質問する代わりに拒否します。重いプロンプトは理由とともに保留され、マシン全体で10分あたり1つの制限に達したアイドル状態の重い再開も同様です。Claudeは各拒否をツールの結果として読み取ります。同じ条件の繰り返し拒否は、毎回異なる言葉でエスカレートします。2回目は何も変わっていないと伝え、別の方法を試すように指示します。3回目はターンを終了するように指示します。/goalのようなStopフックがターンを再開し続ける場合、拒否はユーザーが決定する必要があると伝えます。
何もしないこと。 バックグラウンドタスクの通知や他のセッションのメッセージは、結果を失うため、保持しません。利用制限後にプロンプトをブロックすることはなくなりました。v2.1.234以降、Claude Codeは制限で待機し、リセット時に自動的に続行します(autoContinueAtUsageLimit)。ガードの仕事は、ユーザーが制限に達しないようにすることであり、そのジャーナルは防止できなかったロックアウトをカウントします。
コマンド
/agent-guard [status] ガードが現在見ているもの
/agent-guard allow [agents|context] [minutes] このセッションの制限を解除(デフォルト: 全て、10分)
/agent-guard pause [minutes] allowと同じ、全ての制限に対して
/agent-guard resume allowを早期に終了し、エージェントの一時停止を解除し、拒否された質問を再度尋ねられるようにする
/agent-guard report [days] このマシンで何をしたか(デフォルト: 7日)
/agent-guard help これらのコマンド
/agent-guardは即座に実行され、ターン中でもモデルターンを開始しないため、Claudeはオーバーライドを見ることができず、それを許可とみなすことはできません。マーカーとして[allow-usage-guard]または[allow-agent-burst]のみをプロンプトとして送信すると、/agent-guard allowまたはallow agentsと同じ効果があります。
見ることができるものと見ることができないもの
Claude Code v2.1.295でチェック済み:
| パス | カバレッジ |
|---|---|
| サブエージェント、チームメイト、ワークフローエージェント | 開始前に保留(agent.spawn) |
新しい作業で送信された完了したサブエージェント(SendMessage) | 再開前に保留され、開始としてカウントされる |
/subtaskフォーク、およびagent.spawnなしで開始されるその他のもの | 開始時にカウントされ、決して保留されない: Claude Codeはそれらを実行する前にイベントを提供しない。Agentツールを介してClaudeが開始するフォークは、他のエージェントと同様に保留される |
| Claude Codeの内部エージェント(プロンプト提案、コンパクト化) | カウントされない |
| プランウィンドウのパーセンテージ | サブスクリプションの最後のAPI応答から、claude -pでも取得。APIキーセッションは何も報告しないため、トークンとカウントの予算のみが適用される |
| 他のターミナルペインで実行されているチームメイト | 表示されない: それらのループは他のプロセスで実行される |
| 他のマシンでのセッション | カウントされない: クロスセッションレコードはこのマシンのMODストアに存在する |
| API自体が実行するツール(アドバイザーなど) | 保留できない: それらのためのツールイベントは発生しない |
MODはターミナル内のclaude、デスクトップアプリのCodeタブ、claude -p、およびAgent SDKで実行されます。デスクトップアプリのWSLセッションでは実行されません(MODの実行場所)。
ネイティブ制限は依然として重要です。 Claude Codeはセッションを20の同時サブエージェント(CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS)と3層のネスト(CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH)に制限します。セッションが開始するエージェントの総数に制限はありません。ガードのデフォルトはより厳しくセッション全体に及びますが、ネイティブキャップはガードがカウントするパスの外部壁として残ります。
何をしたかを見る
/agent-guard report 30
レポートは、利用制限によるロックアウト(各ロックされたウィンドウごとに1回)、プランウィンドウのしきい値超過、およびルールごとの各質問と拒否、回答とともにカウントします。このマシン上の各セッションのジャーナルを読み取り、決して離れることはありません。記録を停止するにはAGENT_GUARD_JOURNAL=0を設定してください。
セキュリティとプライバシー
MODはユーザーの権限でClaude Code内で実行されます。インストールする前にMODが何にアクセスできるかを読んでください。これは約2,400行のTypeScriptで依存関係はありません。claude plugin validate .は、呼び出すすべてのAPIと読み取るすべての環境変数をリストします:
- ネットワークリクエストを行わず、プロセスも開始しません。
- 上記のルールで説明されていることのみを決定します。エージェントが開始されるか、プロンプトが送信されるか、ツール呼び出しが実行されるかです。回答できる場合はユーザーに尋ね、拒否する場合は理由を伝えます。権限モードを読み取りますが、変更せず、設定も書き込みません。
- 唯一送信するプロンプトはユーザー自身のものです。"Compact, then send"の後、コンパクト化が完了したら、変更されていないユーザーが入力したプロンプトを送信します。
- プロンプトフックは、プロンプトをそのまま渡します。コンテキストが300kを超えた場合は一度だけClaudeへの注釈を追加するか、まずユーザーに尋ねるためにプロンプトを保留します(誰も答えられない場合は、代わりに理由を伝えます)。
SessionStartフックは何も変更しません。 - 状態はMODストアに保存されます。これは
~/.claude/plugins/store/の下のJSONファイルです。各セッションは独自のカウント(実行中のエージェント、最近の開始とアイドル再開、分あたりのサブエージェントトークン、最新の5時間読み取り)、最後にアクティブだった時間(30日間保持されるため、再開されたセッションはアイドル状態だった時間を認識します)、およびジャーナル行(時間、セッションIDプレフィックス、ルール、ツール名、コンテキストバケット(例:400-500k)、プランウィンドウとパーセンテージ、拒否番号、およびユーザーの回答)を書き込みます。 - プロンプトテキスト、ツール入力、エラーテキスト、またはモデル出力は決して保存しません。ツール呼び出しは13文字のフィンガープリントに削減されます。エージェント名はメモリ内に保持され、決して書き込まれません。
- 90日より古いジャーナルは削除されます(
AGENT_GUARD_JOURNAL_DAYS)。 - 上記のGIFをビルドする
demo/は、実行される部分ではありません。一時的なホームディレクトリで、スクリプト化されたローカルAPI用の架空のAPIキーを使用してClaude Codeを起動し、ユーザーの認証情報は一切読み取りません。
アンインストールせずに無効にするには、AGENT_GUARD=0を設定します。
設定
これらを環境変数として設定するか、~/.claude/settings.jsonのenvの下に設定します。時間は秒単位です。数値の範囲外の値はデフォルトを維持し、/agent-guardがそれを表示します。
| 変数 | 説明(デフォルト) |
|---|---|
AGENT_GUARD | 0、false、off、またはnoはガードを無効にします(1) |
AGENT_GUARD_JOURNAL | 0はジャーナルを停止します(1) |
AGENT_GUARD_JOURNAL_DAYS | 保存されるジャーナルの日数(90) |
AGENT_GUARD_WINDOW_SECONDS | 予算、消費、拒否のためのローリングウィンドウ(600) |
AGENT_GUARD_AGENT_MAX | このマシンで同時に実行されるエージェント(4) |
AGENT_GUARD_ROLLING_MAX | このマシンでウィンドウあたりのエージェントの開始と再開(12) |
AGENT_GUARD_AGENT_TOKENS_MAX | このマシンでウィンドウあたりのサブエージェントトークン(10000000) |
AGENT_GUARD_DEPTH_MAX | メイン会話の下のエージェントレイヤー(1) |
AGENT_GUARD_LIMIT_ASK_PERCENT | 新しいエージェントが質問を始めるプランウィンドウのパーセンテージ(80) |
AGENT_GUARD_LIMIT_DENY_PERCENT | 新しいエージェントが拒否されるプランウィンドウのパーセンテージ(95) |
AGENT_GUARD_BURN_PERCENT | 新しいエージェントが質問を始めるウィンドウあたりの消費ポイント(20) |
AGENT_GUARD_CONTEXT_WARN | Claudeに一度だけターンを制限するように指示するコンテキスト(300000) |
AGENT_GUARD_CONTEXT_HARD | プロンプトが送信される前に質問するコンテキスト(500000) |
AGENT_GUARD_TOOL_CONTEXT | ツール呼び出しがツール予算にカウントされるコンテキスト(400000) |
AGENT_GUARD_TOOL_MAX | そのコンテキストの上でのウィンドウあたりのツール呼び出し(20) |
AGENT_GUARD_DORMANT_SECONDS | 重いセッションのキャッシュが期限切れと見なされるまでのアイドル時間(3600) |
AGENT_GUARD_DORMANT_CONTEXT | アイドルセッションが重いと見なされるコンテキスト(150000) |
AGENT_GUARD_DORMANT_MAX | 誰も質問できない場合の、このマシンでのウィンドウあたりの重いアイドル再開(1) |
AGENT_GUARD_TOOL_FAILURE_MAX | 同一のリトライが拒否される前の、同一の失敗回数(3) |
AGENT_GUARD_FUSE_MAX | スポーンを一時停止するフューズ期間あたりの拒否されたエージェント呼び出し(5) |
AGENT_GUARD_FUSE_SECONDS | フューズ期間、および一時停止が続く時間(600) |
AGENT_GUARD_PEER_TTL_SECONDS | 他のセッションのカウント、または活動の兆候がないエージェントがカウントされ続ける時間(900) |
休止状態のデフォルトは、プラン利用量内でサブスクリプションが得る1時間のプロンプトキャッシュを想定しています。APIキーまたは追加利用量がある場合、キャッシュは5分間持続するため、AGENT_GUARD_DORMANT_SECONDS=300を設定してください。
Claude Code以外
ルールはハーネスに依存しないコア(core/)にあり、I/Oを実行しません。Claude Code MODはその最初のアダプターです。docs/architecture.mdは、アダプターが維持する契約と、各ルールを処理するために他のエージェントハーネスが提供する必要があるものについて説明しています。
テスト
claude plugin validate . --strict
claude plugin test
claude plugin testは、Claude Code独自のテストキット内でテストスイートを実行します。コアの単体テストと、セッション、モデル、ネットワークなしで、実際のClaude Codeイベントをフックモジュールに発行するテストです。TESTING.mdは、レイヤーと各テストが何を証明するかをカバーしています。
ライセンス
MIT