商业产业 Hacker News Agent 2026-10-22T18:02 正文 ok 2388 words

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 进行自动化工程任务的开发者而言,该工具有效解决了递归生成与并发调用导致的快速锁死难题,为套餐额度提供了关键的安全护栏。
打开原文相关 6 · 机会 1
media1.5 KB media2.8 MB media98.2 KB

中文

防止 Claude Code 在十分钟内耗尽你五小时的使用窗口。

agent-usage-guard 是一个 Claude Code mod(插件):它在 Claude Code 内部运行,并在失控开销发生前将其制止。它会读取你套餐的实时用量,并限制子 Agent 泛滥衍生、高上下文损耗以及重试循环。

Claude Code 交互界面中的四个场景。该守卫在提示词试图重写空闲两小时后已过期的 486k-token 会话缓存前进行询问;在第五个并行 Agent 启动(上限为 4)前进行询问;在 433k 上下文下进行第 21 次工具调用前进行询问;并在子 Agent 累计处理 1090 万 token 后启动新 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.

Four scenes in Claude Code's interactive UI. The guard asks before a prompt re-writes the expired cache of a 486k-token session resumed after two hours, before a fifth parallel agent starts against a limit of four, before a twenty-first tool call at 433k context, and before a new agent once subagents have processed 10.9M tokens.

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 status shows.
  • 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 SessionStart hook 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 as 400-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