agent-usage-guard:防止 10 分钟耗尽使用额度的 Claude Code 守护插件
英文标题:🔶 Show HN: agent-usage-guard – a Claude Code mod to protect your usage window
针对 Claude Code 在复杂任务或多 Agent 并发中可能在十分钟内耗尽 5 小时套餐额度的问题,开发者推出了开源本地 Mod 插件 agent-usage-guard。该插件通过实时监测用量,在调用发生前拦截子 Agent 泛滥、大上下文缓存重写以及工具死循环重试,并在需要时通过原生弹窗向用户请求确认。插件采用纯本地 TypeScript 开发、无网络请求且严格保护隐私,发生异常时采用故障开放策略。对于深度使用 Claude Code 进行自动化工程任务的开发者而言,该工具有效解决了递归生成与并发调用导致的快速锁死难题,为套餐额度提供了关键的安全护栏。
1.5 KB
98.2 KB
中文
防止 Claude Code 在十分钟内耗尽你五小时的使用窗口。
agent-usage-guard 是一个 Claude Code mod(插件):它在 Claude Code 内部运行,并在失控开销发生前将其制止。它会读取你套餐的实时用量,并限制子 Agent 泛滥衍生、高上下文损耗以及重试循环。
以上内容录制自加载了守卫的 Claude Code 交互界面。一个脚本化本地 API替代了真实的 Claude,因此会话与 token 计数均为模拟场景,未产生实际消耗。屏幕上的每个询问均由守卫本身发起。可通过 Northstar 测试夹具并运行 重建脚本 进行重现。
它在产生消耗之前介入,而非事后拦截:在 Agent 启动、提示词发送或工具调用执行前进行限制。Agent 限制适用于你机器上的所有 Claude Code 会话,并且无论处于何种用量阶段(不仅是接近上限时),都会对并发泛滥与超大上下文进行封顶。当你在键盘前操作时,它会通过 Claude Code 自带的问题对话框向你询问;当无人应答时,它会予以拒绝并告知 Claude 原因,以便模型等待、批处理工作或终止运行。运行 /agent-guard report 可以查看它的拦截记录。
- 感知套餐配额(Plan-aware): 读取 Claude Code 上报的 5 小时与每周用量百分比,为你守住窗口末期的可用额度。
- 一次授权管一阵(One answer covers a while): 一旦批准,该限制条件将被解除,直到重置或超时,因此同一个问题不会在每次调用时反复弹出。
- 纯本地且隐私开销极小(Local and privacy-minimal): 无网络请求,不启动额外进程。仅记录计数与粗粒度分桶数据,从不存储提示词文本、工具输入或模型输出。
- 故障开放(Fails open): 若某个钩子(hook)运行失败,事件将照常放行:插件故障绝不会导致你的会话崩溃。唯一的例外是未能及时做出判决的 Agent 会被拒绝,以便 Claude 稍后重新发起。
在 Claude Code v2.1.287 或更高版本中运行以下命令:
bash /plugin marketplace add rbartoli/agent-usage-guard /plugin install agent-usage-guard@agent-usage-guard /reload-plugins
然后运行 /agent-guard 查看其监控的数据状态。Mods 功能默认开启;概览文档中列出了关闭 Mods 的相关配置项。
某天下午,我向 Claude Code 提交了一个最大精度的研究提示词。它衍生出了 394 次子 Agent 调用,其中 341 个并发运行,并在十分钟内向 API 推送了 8400 万 context tokens。 会话随即终结:"Claude usage limit reached." 直接被锁定,直到用量窗口重置。
这绝非偶然个案。在我个人 60 天的日志中,记录了 12 次额度锁死 以及 166 个经历过 Agent 爆发式调用的 10 分钟窗口。这种失效模式往往是乘积式叠加的:超大上下文 × 快速工具循环 × 并行 Agent × 盲目重试。下面的每一条保护规则,正是为了移除其中一个乘数因子。
受到困扰的也不止我一人:单次提示词催生 339 个子 Agent、递归衍生消耗了半周的 Max 套餐额度,以及多 Agent 运行消耗了相当于聊天会话约 15 倍的 token。
| 领域 | 规则 | 默认值 | 触发行为 |
|---|---|---|---|
| 套餐窗口 (Plan windows) | 当用量窗口达到此比例时,新 Agent 需要批准 | 80% | 弹出询问;批准后有效性持续至该窗口重置 |
| 当用量窗口达到此比例时,直接拒绝新 Agent | 95% | 拒绝执行 | |
| 提示每个会话完成当前步骤并说明剩余工作 | 95% | 在下一条提示词中追加说明备注 | |
| 当 5 小时窗口用量上升过快时,新 Agent 需要批准 | 20 点 / 10 分钟 | 弹出询问 | |
| Agent 限制 (Agents) | 当前机器所有会话中同时运行的 Agent 数量 | 4 | 弹出询问 |
| 当前机器每 10 分钟内启动或恢复的 Agent 数量 | 12 | 弹出询问 | |
| 当前机器每 10 分钟内子 Agent 处理的 Token 数量 | 10M | 弹出询问 | |
| 禁止子 Agent 自行衍生子 Agent | 深度 1 (depth 1) | 拒绝执行 | |
| 上下文 (Context) | 提示 Claude 控制本轮对话规模 | 300k tokens | 在提示词中追加说明备注 |
| 提示词将重新读取如此庞大的上下文时 | 500k tokens | 弹出询问:压缩后发送、直接发送,或取消 | |
| 当对话或 Agent 携带此量级上下文时的 10 分钟内工具调用数 | 400k 下调用 20 次 | 弹出询问:继续、本轮后压缩,或停止 | |
| 重度会话空闲时间过长导致其提示词缓存失效 | 150k tokens,空闲 1 小时 | 重写缓存前弹出询问 | |
| 循环检测 (Loops) | 相同的工具调用反复失败,且中间没有其他调用 | 3 次相同失败 | 拒绝相同的重试 |
| 10 分钟内被拒绝的 Agent 调用次数 | 5 次 | 暂停 Agent 衍生 10 分钟 |
Agent 的统计覆盖了子 Agent(subagents)、agent-team 团队成员、工作流 Agent(workflow agents)以及通过 SendMessage 恢复的已结束子 Agent。每次工具调用均根据发起该调用的循环上下文进行评判,因此小型子 Agent 不会继承主对话的上下文体积。
询问时机(When it asks): 问题会直接出现在 Claude Code 自带的交互对话框中(即 Claude 向你询问确认的对话框),调用过程会暂停以等待你的回答。在此期间并行启动的 Agent 会被挂起,一旦你作出应答,Claude 会重新启动它们。如果你选择允许,该条件的放行状态将维持一段时间:套餐窗口直到重置为止,大上下文直到体积缩减为止(工具调用最多放行 1 小时),Agent 计数放行 10 分钟。如果你拒绝或忽略该问题,系统会告知 Claude 在接下来的 10 分钟(AGENT_GUARD_WINDOW_SECONDS)内不要启动 Agent,且在这段时间内不会再次弹窗。你输入的回复文字能够直接传达给 Claude,因此你可以输入诸如“改用 haiku agents”等指令。
无人应答时(When nobody can answer): 在 claude -p、Agent SDK 以及 dontAsk 模式下,遇到 Agent 或工具拦截门槛时会直接拒绝而非询问。过大的提示词会连同原因一起被挂起,当达到整机每 10 分钟 1 次的上限时,休眠的大会话恢复也会被拦截。Claude 会将每次拒绝视作工具的执行结果。针对同一条件的重复拒绝在措辞上会逐步升级:第二次会提示状态未变、请尝试其他方法,第三次则会要求直接结束本轮对话。如果有诸如 /goal 等 Stop 钩子不断重新打开轮次,拒绝信息会明确提示必须由用户做出决定。
不予干预的情形(What it leaves alone): 它绝不拦截后台任务的通知或跨会话的消息,因为这会导致结果丢失。它不再在达到用量上限后阻止提示词:自 v2.1.234 起,Claude Code 在达到上限时会主动等待并在窗口重置时自动继续(autoContinueAtUsageLimit)。守卫的核心职责是防止你触碰上限,其日志会记录未能力挽狂澜的锁定事件。在接近用量上限时,它仅添加提示信息:自 95% 起,各会话的下一条提示词会建议 Claude 完成当前步骤、不要启动大型任务,并在结束本轮时汇报已完成与剩余事项,确保即使发生锁定,所有会话也能干净整洁地停步。
空闲压缩(Idle compaction): 自 v2.1.299 起,Claude Code 会在约 54 分钟时自动压缩处于空闲状态、达到或超过 200k tokens 的对话,以赶在一小时提示词缓存过期之前完成(idleCompaction,默认开启)。守卫能读取压缩后的大小,因此不会针对这类会话发起询问。它的休眠拦截机制恰好补足了空闲压缩未覆盖的死角:150k 到 200k tokens 之间的对话、claude -p 及其他非终端会话、在 54 分钟节点处于休眠状态的机器,以及关闭了空闲压缩或自动压缩的环境配置。
bash /agent-guard [status] 查看守卫当前监控到的各项状态 /agent-guard allow [agents|context] [minutes] 针对当前会话临时解除限制(默认:全部,10 分钟) /agent-guard pause [minutes] 效果同 allow,针对所有限制项生效 /agent-guard resume 提前结束 allow,解除 Agent 暂停,并允许重新弹出被拒绝的问题 /agent-guard report [days] 查看当前机器上的拦截报告(默认:7 天) /agent-guard help 查看这些命令的帮助说明
/agent-guard 可以立刻运行,甚至在轮次进行中也可以执行,且从不启动模型轮次,因此 Claude 永远不会看到你的手动覆写操作,也不会将其误当成许可指令。单独发送 [allow-usage-guard] 或 [allow-agent-burst] 作为提示词(早期版本的标记格式),其效果与 /agent-guard allow 或 allow agents 相同。
能监控与无法监控的范围 (What it can and cannot see)
基于 Claude Code v2.1.295 版本核对:
| 路径 | 覆盖情况 |
|---|---|
| 子 Agent、团队成员及工作流 Agent | 在启动前被拦截(agent.spawn) |
通过 SendMessage 被分派新工作的已结束子 Agent |
在恢复前被拦截,并被计为一次启动 |
| 从磁盘恢复的团队成员(Claude Code 2.1.299 或更高版本) | 在恢复前被拦截,并被计为一次启动 |
/subtask 分支,以及其他不通过 agent.spawn 启动的内容 |
仅在启动时进行计数,从不拦截:Claude Code 未提供启动前的事件钩子。而 Claude 通过 Agent 工具启动的分支则能像普通 Agent 一样被拦截 |
| Claude Code 的内部 Agent(提示词建议、上下文压缩) | 不计入统计 |
| 套餐窗口百分比 | 取自订阅套餐的最新 API 响应,同样适用于 claude -p。API Key 会话不返回此项,因此仅应用 Token 与计数预算 |
| 在独立终端分屏中运行的团队成员 | 不可见:其循环运行在其他进程中 |
| 其他机器上的会话 | 不计入统计:跨会话记录保存在本地机器的 Mod 存储区中 |
| API 自主运行的工具(例如 advisor) | 无法拦截:API 未为此类工具触发工具调用事件 |
Mods 可以在终端中的 claude、桌面应用的 Code 标签页、claude -p 以及 Agent SDK 中运行。它们无法在桌面应用的 WSL 会话中运行(参见Mods 运行环境说明)。
原生限制依然重要(Native limits still matter): Claude Code 单会话默认上限为 20 个并发子 Agent(CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS)以及 3 层嵌套深度(CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH)。但它对单会话启动的 Agent 总数没有设限。守卫的默认配置更为严格并横跨多个会话;对于守卫仅能计数的路径,原生配额构成了最外层的安全兜底防线。
报告会统计用量上限锁定次数(每个锁定窗口仅记录一次)、套餐窗口阈值跨越次数、收尾提示备注,以及根据各条规则统计的提问和拒绝次数连同你的应答。它仅读取本台机器上每个会话的日志,数据绝不外泄。设置 AGENT_GUARD_JOURNAL=0 即可关闭日志记录。
Mod 在 Claude Code 内部以你的用户权限运行;安装前请先参阅Mod 权限范围说明。本项目仅由约 2400 行零依赖的 TypeScript 代码构成,运行 claude plugin validate . 可以列出其调用的每一个 API 和读取的每一个环境变量:
- 它不发起任何网络请求,也不启动任何系统进程。唯一读取的文件是其自身的
plugin.json,用于获取/agent-guard status显示的版本信息。 - 它仅根据上述规则做出裁决:是否允许启动 Agent、发送提示词或执行工具调用。只要你能应答,它就会发起询问;而在拒绝时会给出具体原因。它会读取权限模式但绝不修改权限,也不会写入任何配置项。
- 它提交的唯一提示词就是你自己的输入:在选择“压缩后发送(Compact, then send)”后,它会在压缩完成后原封不动地发送你输入的提示词。
- 它的提示词钩子会将你的提示词原样传递;当上下文超过 300k 或套餐窗口达到 95% 时,它会为 Claude 附带一条一次性提示备注;或者挂起提示词优先询问你(在无人应答模式下,它会改用提示原因)。它的
SessionStart钩子不会改变任何内容。 - 它将自身状态保存在 Mod 存储区中,即位于
~/.claude/plugins/store/下的 JSON 文件。每个会话会写入自身的统计数据(正在运行的 Agent、近期的启动与休眠恢复、子 Agent 每分钟 Token 消耗、其最新的 5 小时用量读取值)、最后活动时间(保留 30 天,以便恢复的会话掌握其空闲了多久),以及其日志条目(时间戳、会话 ID 前缀、命中规则、工具名称、400-500k等上下文区间、套餐窗口与百分比、拒绝序号,以及你的回答)。 - 它绝不存储提示词文本、工具输入、错误详情或模型输出内容。工具调用会被哈希压缩为一个 13 字符的指纹。Agent 名称仅保留在内存中,绝不落盘写入。
- 超过 90 天的日志数据会被自动清除(
AGENT_GUARD_JOURNAL_DAYS)。 - 用于生成上方动图的
demo/目录不属于运行时模块。它在临时家目录中启动 Claude Code,并配合本地模拟 API 生成虚拟 API Key,绝不会读取你的任何个人凭据。
设置 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 |
本机同时运行的 Agent 最大数(默认 4) |
AGENT_GUARD_ROLLING_MAX |
本机每个窗口内启动与恢复的 Agent 最大数(默认 12) |
AGENT_GUARD_AGENT_TOKENS_MAX |
本机每个窗口内子 Agent 消耗 Token 上限(默认 10000000) |
AGENT_GUARD_DEPTH_MAX |
主对话下允许的 Agent 嵌套层级(默认 1) |
AGENT_GUARD_LIMIT_ASK_PERC |
触发询问确认的套餐窗口使用率阈值百分比(默认 80) |
English / 原文
Stops Claude Code from spending your five-hour usage window in ten minutes.
agent-usage-guard is a Claude Code mod: it runs inside Claude Code and holds runaway spend before it happens. It reads your plan's live usage, and it holds subagent fan-out, heavy-context churn and retry loops.
Recorded from Claude Code's interactive UI with the guard loaded. A scripted local API stands in for Claude, so the sessions and token counts are staged and no usage is spent. Every question on screen is the guard's own. Rebuild it from the Northstar fixture.
It acts before the spend, not after it: before an agent starts, a prompt is sent, or a tool call runs. Agent limits hold across every Claude Code session on your machine, and fan-out and heavy context are capped at any usage level, not only near the limit. When you are at the keyboard it asks you, in Claude Code's own question dialog. When nobody can answer, it refuses and tells Claude why, so the model can wait, batch the work, or stop. /agent-guard report shows what it did.
- Plan-aware. It reads the 5-hour and weekly percentages Claude Code reports, and keeps the end of the window for you.
- One answer covers a while. An approval lifts its condition until it clears or times out, so the same question does not come back call after call.
- Local and privacy-minimal. No network, no processes. It stores counts and coarse buckets, never prompt text, tool inputs or model output.
- Fails open. If one of its hooks fails, the event goes ahead: a broken guard never breaks your session. The one exception is an agent it could not judge in time, which is refused so that Claude starts it again.
Run these commands inside Claude Code v2.1.287 or later:
/plugin marketplace add rbartoli/agent-usage-guard
/plugin install agent-usage-guard@agent-usage-guard
/reload-plugins
Then run /agent-guard to see what it sees. Mods are on by default; the overview lists the settings that turn them off.
One afternoon I gave Claude Code a research prompt at max effort. It spawned 394 subagent calls, 341 of them running at once, and pushed 84M context tokens through the API in ten minutes. Session over: "Claude usage limit reached." Locked out until the window reset.
That wasn't a one-off. Sixty days of my own logs held 12 lockouts and 166 ten-minute windows with agent bursts. The failure mode multiplies: a large context × rapid tool loops × parallel agents × blind retries. Each protection below removes one factor.
And it's not just me: 339 subagents from a single prompt, half a weekly Max plan consumed by recursive spawning, and multi-agent runs using ~15× the tokens of a chat session.
| Area | Rule | Default | What happens |
|---|---|---|---|
| Plan windows | New agents need approval once a window is this full | 80% | asks; approval lasts until that window resets |
| New agents are refused once a window is this full | 95% | refuses | |
| Each session is told once to finish its step and say what is left | 95% | adds a note to the next prompt | |
| New agents need approval when the 5-hour window rises this fast | 20 points / 10 min | asks | |
| Agents | Agents running at once, across every session on this machine | 4 | asks |
| Agents started or resumed per 10 minutes, across this machine | 12 | asks | |
| Tokens processed by subagents per 10 minutes, across this machine | 10M | asks | |
| Subagents may not start their own agents | depth 1 | refuses | |
| Context | Claude is told once to keep the turn bounded | 300k tokens | adds a note to the prompt |
| A prompt that would re-read this much context | 500k tokens | asks: compact then send, send anyway, or cancel | |
| Tool calls per 10 minutes while a conversation or agent carries this much | 20 calls at 400k | asks: keep going, compact after this turn, or stop | |
| A heavy session idle long enough for its prompt cache to expire | 150k tokens, 1 h idle | asks before re-writing the cache | |
| Loops | The same tool call failing again and again, with no other call in between | 3 identical failures | refuses the identical retry |
| Refused agent calls within 10 minutes | 5 | pauses agent spawns for 10 min |
Agents covers subagents, agent-team teammates, workflow agents, and finished subagents resumed with SendMessage. Each tool call is judged on the context of the loop that makes it, so a small subagent never inherits the main conversation's size.
When it asks. The question appears in Claude Code's own dialog, the one Claude uses to ask you something, and the call waits for your answer. Agents started in parallel while it is open are held back, and Claude starts them again once you answer. If you allow it, that condition stays allowed for a while: a plan window until it resets, a heavy context until it shrinks (for tool calls, an hour at most), the agent counts for 10 minutes. If you decline or dismiss the question, Claude is told not to start agents for the next 10 minutes (AGENT_GUARD_WINDOW_SECONDS), and is not asked again in that time. Typed words reach Claude, so you can answer "use haiku agents instead".
When nobody can answer. In claude -p, the Agent SDK and dontAsk mode, an agent or tool gate refuses instead of asking. A heavy prompt is held with the reason, and so is a dormant heavy resume once the machine-wide cap of one per 10 minutes is reached. Claude reads each refusal as the tool's result. Repeat refusals of the same condition are worded differently each time and escalate: the second says nothing has changed and to try something else, the third says to end the turn. If a Stop hook such as /goal keeps reopening the turn, the refusal says the user has to decide.
What it leaves alone. It never holds a background task's notification or another session's message, because that would lose the result. It no longer blocks prompts after a usage limit: since v2.1.234, Claude Code waits at a limit and continues at reset on its own (autoContinueAtUsageLimit). The guard's job is to keep you from reaching the limit, and its journal counts the lockouts it did not prevent. Near the limit it only adds a note: from 95%, each session's next prompt tells Claude 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.
Idle compaction. Since v2.1.299, Claude Code compacts a conversation of 200k tokens or more that sits idle for about 54 minutes, before its one-hour prompt cache expires (idleCompaction, on by default). The guard reads the compacted size, so it does not ask about that session. Its dormant question covers what idle compaction leaves out: conversations from 150k to 200k tokens, claude -p and other non-terminal sessions, a machine that was asleep at the 54-minute mark, and setups with idle compaction or auto-compaction turned off.
/agent-guard [status] what the guard sees right now
/agent-guard allow [agents|context] [minutes] lift its limits for this session (default: all, 10 min)
/agent-guard pause [minutes] the same as allow, for every limit
/agent-guard resume end an allow early, lift the agent pause, and let declined questions ask again
/agent-guard report [days] what it did on this machine (default: 7 days)
/agent-guard help these commands
/agent-guard runs at once, even mid-turn, and never starts a model turn, so Claude never sees an override and cannot take one as permission. Sending [allow-usage-guard] or [allow-agent-burst] alone as a prompt, the markers of earlier versions, does the same as /agent-guard allow or allow agents.
What it can and cannot see
Checked against Claude Code v2.1.295:
| Path | Coverage |
|---|---|
| Subagents, teammates and workflow agents | Held before they start (agent.spawn) |
A finished subagent sent new work with SendMessage |
Held before it resumes, and counted as a start, once |
| A teammate brought back from disk (Claude Code 2.1.299 or later) | Held before it resumes, and counted as a start |
/subtask forks, and anything else that starts without agent.spawn |
Counted when they start, never held: Claude Code offers no event before they do. Forks Claude starts through the Agent tool are held like any agent |
| Claude Code's internal agents (prompt suggestions, compaction) | Not counted |
| Plan-window percentages | From the last API response on a subscription, in claude -p too. API-key sessions report none, so only the token and count budgets apply |
| Teammates running in their own terminal panes | Not visible: their loops run in other processes |
| Sessions on other machines | Not counted: the cross-session records live in this machine's mod store |
| Tools the API runs itself, such as the advisor | Not holdable: no tool event fires for them |
Mods run in claude in a terminal, in the Desktop app's Code tab, in claude -p and the Agent SDK. They don't run in a Desktop-app WSL session (where mods run).
Native limits still matter. Claude Code caps a session at 20 concurrent subagents (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS) and three layers of nesting (CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH). It has no limit on the total number of agents a session starts. The guard's defaults are stricter and span sessions; the native caps remain the outer wall for the paths the guard only counts.
The report counts usage-limit lockouts (each locked window once), plan-window threshold crossings, wind-down notes, and every question and refusal by rule, with what you answered. It reads every session's journal on this machine and never leaves it. Set AGENT_GUARD_JOURNAL=0 to stop recording.
A mod runs inside Claude Code with your permissions; read what a mod can reach before you install one. This one is about 2,400 lines of TypeScript with no dependencies, and claude plugin validate . lists every API it calls and every environment variable it reads:
- It makes no network requests and starts no processes. The only file it reads is its own
plugin.json, for the version/agent-guard statusshows. - It decides only what the rules above describe: whether an agent starts, a prompt is sent, or a tool call runs. It asks you whenever you can answer, and gives the reason when it refuses. It reads permission modes but never changes them, and it writes no settings.
- The only prompt it submits is your own: after "Compact, then send", it sends the prompt you typed, unchanged, once compaction finishes.
- Its prompt hook passes your prompt on unchanged, adds a one-time note for Claude when the context passes 300k or a plan window reaches 95%, or holds the prompt to ask you first (when nobody can answer, it says why instead). Its
SessionStarthook changes nothing. - It keeps its state in the mod store, a JSON file under
~/.claude/plugins/store/. Each session writes its own counts (running agents, recent starts and dormant resumes, subagent tokens per minute, its latest 5-hour reading), when it was last active (kept 30 days, so a resumed session knows how long it sat idle), and its journal rows (time, a session-id prefix, rule, tool name, context bucket such as400-500k, plan window and percentage, refusal number, and your answer). - It never stores prompt text, tool inputs, error text or model output. A tool call is reduced to a 13-character fingerprint. Agent names stay in memory and are never written.
- Journal days older than 90 days are deleted (
AGENT_GUARD_JOURNAL_DAYS). demo/, which builds the GIF above, is not part of what runs. It starts Claude Code in a temporary home directory with a made-up API key for a scripted local API, and reads none of your credentials.
Set AGENT_GUARD=0 to turn it off without uninstalling it.
Set these as environment variables, or under env in ~/.claude/settings.json. Times are in seconds; a value that isn't a number in range keeps its default, and /agent-guard says so.
| Variable | Meaning (default) |
|---|---|
AGENT_GUARD |
0, false, off or no turns the guard off (1) |
AGENT_GUARD_JOURNAL |
0 stops the journal (1) |
AGENT_GUARD_JOURNAL_DAYS |
Days of journal kept (90) |
AGENT_GUARD_WINDOW_SECONDS |
Rolling window for budgets, burn and refusals (600) |
AGENT_GUARD_AGENT_MAX |
Agents running at once on this machine (4) |
AGENT_GUARD_ROLLING_MAX |
Agent starts and resumes per window on this machine (12) |
AGENT_GUARD_AGENT_TOKENS_MAX |
Subagent tokens per window on this machine (10000000) |
AGENT_GUARD_DEPTH_MAX |
Agent layers below the main conversation (1) |
AGENT_GUARD_LIMIT_ASK_PERCENT |
Plan-window percentage from which new agents ask (80) |
AGENT_GUARD_LIMIT_DENY_PERCENT |
Plan-window percentage from which new agents are refused and each session is told to wind down (95) |
AGENT_GUARD_BURN_PERCENT |
5-hour-window points per window that make new agents ask (20) |
AGENT_GUARD_CONTEXT_WARN |
Context at which Claude is told once to keep the turn bounded (300000) |
AGENT_GUARD_CONTEXT_HARD |
Context at which a prompt asks before it is sent (500000) |
AGENT_GUARD_TOOL_CONTEXT |
Context above which tool calls count against the tool budget (400000) |
AGENT_GUARD_TOOL_MAX |
Tool calls per window above that context (20) |
AGENT_GUARD_DORMANT_SECONDS |
Idle time after which a heavy session's cache counts as expired (3600) |
AGENT_GUARD_DORMANT_CONTEXT |
Context at which an idle session counts as heavy (150000) |
AGENT_GUARD_DORMANT_MAX |
Heavy dormant resumes per window on this machine when nobody can be asked (1) |
AGENT_GUARD_TOOL_FAILURE_MAX |
Identical failures before the identical retry is refused (3) |
AGENT_GUARD_FUSE_MAX |
Refused agent calls per fuse period that pause spawns (5) |
AGENT_GUARD_FUSE_SECONDS |
The fuse period, and how long the pause lasts (600) |
AGENT_GUARD_PEER_TTL_SECONDS |
How long another session's counts, or an agent with no sign of activity, still count (900) |
The dormant default assumes the one-hour prompt cache that subscriptions get within plan usage. With an API key or extra usage, the cache lasts five minutes, so set AGENT_GUARD_DORMANT_SECONDS=300.
The rules live in a harness-agnostic core (core/) that performs no I/O. The Claude Code mod is its first adapter. docs/architecture.md describes the contract an adapter keeps and what another agent harness must offer to carry each rule.
claude plugin validate . --strict
claude plugin test
claude plugin test runs the suite inside Claude Code's own test kit: unit tests of the core, and tests that fire real Claude Code events through the hooks module with no session, model or network. TESTING.md covers the layers and what each test proves.
MIT
