Context & memory·terminal · desktop·MIT
agent-usage-guard
Holds a burst of agents, a huge prompt or a retry loop before it eats your plan window.

agent-usage-guard steps in before the three things that drain a Claude Code usage window fastest: a burst of subagents, a prompt that re-reads a huge context, and a tool call that keeps failing the same way. It judges each agent, prompt and tool call before it runs, counts agents across every Claude Code session on your machine, and asks you in Claude Code’s own question dialog. The author built it after one max-effort research prompt fanned out into 394 subagent calls, 341 of them at once, and pushed 84 million context tokens through the API in ten minutes, ending in a lockout until the window reset.
budget-guard waits for a cost or plan-window figure to cross a limit you set. This one goes after the causes, and caps fan-out and heavy context at any usage level, not only near the limit.
What it does
Every rule has a default you can change (see How it works). “Per 10 minutes” is a rolling window.
It asks you first, and the call waits for your answer:
- A new agent near the limit: once the 5-hour or weekly plan window is 80% used, or when the 5-hour window climbs 20 points within 10 minutes.
- A new agent past a budget: more than 4 agents running at once, 12 started or resumed in 10 minutes, or 10 million tokens processed by subagents in 10 minutes. All three count every session on the machine.
- A heavy prompt: one that would re-read 500k tokens of context. You choose compact then send, send anyway, or cancel.
- A tool loop at heavy context: the 21st tool call within 10 minutes while the conversation or agent making it carries 400k tokens. You choose keep going, compact after this turn, or stop.
- A heavy session after a break: the first prompt to a session of 150k tokens or more that has sat idle for an hour, when its prompt cache has expired and the prompt would write all of it again.
It refuses on its own, and Claude reads the reason as the tool’s result:
- New agents once a plan window reaches 95%.
- A subagent starting agents of its own. One layer below the main conversation is the default.
- The same tool call after 3 identical failures with no other call in between.
- All agent spawns for 10 minutes, after 5 refused agent calls within 10 minutes.
- An agent it could not judge before its hook timed out, so that Claude starts it again.
It adds a note to the prompt, once: at 300k tokens of context, telling Claude to keep the turn bounded; and at 95% of a plan window, telling each session to finish the step in progress, start nothing large and end the turn with what is done and what is left, so a lockout finds every session at a clean stop.
“Agents” means subagents, agent-team teammates, workflow agents, forks started through the Agent tool, and finished subagents woken again with SendMessage. Each tool call is judged on the context of the loop that makes it, so a small subagent is not treated at the main conversation’s size.
An approval holds for a while, so the same question does not come back on every call: a plan window until it resets, a heavy context until it shrinks (an hour at most for tool calls), the agent counts for 10 minutes. Declining or dismissing tells Claude to start no agents for 10 minutes, and you are not asked again in that time. Words you type in the dialog reach Claude, so an answer such as “use haiku agents instead” works. Agents launched in parallel while a question is open are held back, and Claude starts them again once you answer.
When nobody can answer, in claude -p, the Agent SDK, dontAsk permission mode or a session without the AskUserQuestion tool, every question becomes a refusal. A heavy prompt is dropped with the reason, and a heavy idle resume passes only once per 10 minutes per machine. Repeat refusals of the same condition escalate: the second says nothing has changed and to try something else, the third tells Claude to end the turn.
/agent-guard controls it:
/agent-guardor/agent-guard statusshows what the guard sees right now, including any setting it rejected./agent-guard allow [agents|context] [minutes]lifts its limits for this session, all of them for 10 minutes by default./agent-guard pause [minutes]does the same for every limit./agent-guard resumeends an allow early, lifts the agent pause and lets declined questions ask again./agent-guard report [days]counts lockouts, plan-window crossings, wind-down notes and every question and refusal by rule, with what you answered, over 7 days by default.
The command runs at once, even mid-turn, and never starts a model turn, so Claude never sees an override and cannot take one as permission. AGENT_GUARD=0 turns the guard off without uninstalling it.
Install
Needs Claude Code 2.1.287 or later. The plan-window rules need a Claude subscription; on an API key only the agent, context and loop budgets apply.
claude plugin marketplace add rbartoli/agent-usage-guard
claude plugin install agent-usage-guard@agent-usage-guard
Run /reload-plugins or restart Claude Code, then /agent-guard to see what it sees. There is nothing to set up: the defaults apply at once.
How it works
The module hooks 16 events. agent.spawn fires before a subagent, teammate, workflow agent or Agent-tool fork starts, and that is where the agent rules run. tool.call sees every tool call: it catches a SendMessage that would wake a finished subagent, counts calls against the heavy-context budget, and reduces each call’s arguments to a 13-character fingerprint to spot an identical retry. prompt.submit runs the heavy-prompt and idle-session checks and attaches the notes.
The figures come from Claude Code itself. session.measure delivers the plan-window percentages and the main context size, turn.step the token counts of every API response for the main loop and each subagent separately, and $.session.usage() the context right before a prompt. Classic hooks fill the gaps: SubagentStart counts agents that start without agent.spawn, SessionStart and PostCompact notice compactions, clears and resumes, Stop notices a Stop hook reopening the turn, StopFailure records a usage-limit lockout, and UserPromptSubmit and PostToolUse follow the permission mode, which decides whether anyone can be asked. session.start, session.end, turn.complete and command.run handle setup, cleanup, compact-after-turn and /agent-guard. In an interactive session it also keeps a status line, redrawn when something on it runs out.
The cross-session counts live in the mod store, a JSON file under ~/.claude/plugins/store/. Each session writes its own record whenever an agent starts or ends, on a new plan reading, and at least once a minute while responses arrive: agents running, recent starts and idle resumes, subagent tokens per minute and its latest 5-hour reading. Before judging an agent or a prompt, a session reads the others’ records. A record not refreshed for 15 minutes stops counting, a session deletes its own when it ends, and leftovers older than a day are swept at the next start. A second key per session keeps when it was last active, for 30 days, so a resumed session knows how long it sat idle.
The journal behind /agent-guard report sits in the same store, one key per session per day. A row holds the time, the first 8 characters of the session id, the rule, the tool name, a context bucket such as 400-500k, the plan window and percentage, the refusal number and your answer. It never stores prompt text, tool inputs, error text or model output, and agent names stay in memory. Days older than 90 are deleted and the whole journal is kept under about 2 MB. AGENT_GUARD_JOURNAL=0 stops it and AGENT_GUARD_JOURNAL_DAYS changes the 90.
The mod makes no network requests, starts no processes and calls no model. The only file it reads is its own plugin.json, for the version /agent-guard prints. It reads permission modes but never changes them, and writes no settings. What reaches Claude is the one-time notes and the refusal reasons, a few lines of text. If you pick compact, it runs Claude Code’s own compaction. The only prompt it ever submits is yours: after “Compact, then send” it takes your prompt out of the input box, waits for the compaction and sends it unchanged, or puts it back in the box if compaction fails.
Since 2.1.299, Claude Code compacts an idle conversation of 200k tokens or more before its cache expires, and the guard sees the smaller size. Its idle question mostly covers sessions of 150k to 200k tokens, claude -p, a machine that slept through that point, and idle compaction turned off.
Each threshold is an environment variable, set in your shell or under env in ~/.claude/settings.json. The module reads them when a session starts. A value that is not a number in range keeps its default, and /agent-guard says so.
| Variable | Default | What it sets |
|---|---|---|
AGENT_GUARD_LIMIT_ASK_PERCENT | 80 | Plan-window use from which new agents ask |
AGENT_GUARD_LIMIT_DENY_PERCENT | 95 | Plan-window use from which new agents are refused and sessions wind down |
AGENT_GUARD_BURN_PERCENT | 20 | 5-hour points gained per window that make new agents ask |
AGENT_GUARD_AGENT_MAX | 4 | Agents running at once on the machine |
AGENT_GUARD_ROLLING_MAX | 12 | Agent starts and resumes per window on the machine |
AGENT_GUARD_AGENT_TOKENS_MAX | 10000000 | Subagent tokens per window on the machine |
AGENT_GUARD_DEPTH_MAX | 1 | Agent layers allowed below the main conversation |
AGENT_GUARD_CONTEXT_WARN | 300000 | Context that triggers the one-time “keep it bounded” note |
AGENT_GUARD_CONTEXT_HARD | 500000 | Context at which a prompt asks before it is sent |
AGENT_GUARD_TOOL_CONTEXT | 400000 | Context above which tool calls count toward the tool budget |
AGENT_GUARD_TOOL_MAX | 20 | Tool calls per window above that context |
AGENT_GUARD_DORMANT_CONTEXT | 150000 | Size at which an idle session counts as heavy |
AGENT_GUARD_DORMANT_SECONDS | 3600 | Idle seconds after which its cache counts as expired |
AGENT_GUARD_DORMANT_MAX | 1 | Heavy idle resumes per window on the machine when nobody can answer |
AGENT_GUARD_TOOL_FAILURE_MAX | 3 | Identical failures before the same retry is refused |
AGENT_GUARD_FUSE_MAX | 5 | Refused agent calls per fuse period that pause spawning |
AGENT_GUARD_FUSE_SECONDS | 600 | The fuse period, and how long the pause lasts |
AGENT_GUARD_WINDOW_SECONDS (600) is the rolling window behind every “per window” above, and AGENT_GUARD_PEER_TTL_SECONDS (900) is how long another session’s counts, or an agent with no sign of activity, keep counting. The idle default assumes the one-hour prompt cache that subscriptions get. On an API key or extra usage the cache lasts five minutes, so the author suggests AGENT_GUARD_DORMANT_SECONDS=300.
Limitations
- It fails open: a hook that throws or overruns lets the event go ahead. The one exception is an agent it could not judge in time.
/subtaskforks, and anything else that starts withoutagent.spawn, are counted when they start but never held. Claude Code’s internal agents, such as prompt suggestions and compaction, are not counted.- Teammates running in their own terminal panes are invisible, since their loops run in other processes. Sessions on other machines are not counted.
- Tools the API runs itself, such as the advisor, fire no tool event and cannot be held.
- API-key sessions report no plan-window percentages, so only the token and count budgets apply.
- It does not hold prompts after a usage limit, because Claude Code has waited and continued at reset on its own since 2.1.234. The report counts those lockouts instead. It never holds a background task’s notification or another session’s message.
- The README lists the terminal, the Desktop app’s Code tab,
claude -pand the Agent SDK as places it runs, and not a Desktop WSL session. The author checked its coverage against Claude Code 2.1.295.
Similar Claude Mods
Context Attachment Manager
Pick which past images go out with your next message; the rest become placeholders.
jevmem-pane
What jevmem recalled, what its guard decided and what it saved, beside the chat.
segmem
Long-term memory by kind and scope in one SQLite file. Wake at start, recall per prompt.
cache-tax
Keeps the prompt cache warm during breaks and stops a cold send once with its price.
Popular Claude Mods
The whole directory →claude-carbon
Estimated grams of CO2 for each answer and session, with a molecule and warming stripes.
inbox
Claude's questions, your tasks, its findings and your PRs, sorted in one pane.
xcode-mods
Xcode build, tests, console and SwiftUI previews in panes, plus a toolbar band.
filetree
Sidebar file tree with git status that lights up what Claude reads, edits and commits.







