skill
usage-cap
Know you'll run out of Claude Code usage before you run out. Forecasts your 5-hour and weekly limits from burn rate, warns early, and blocks new prompts before you get locked out mid-task.
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/MohammedNihal03/usage-cap itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 23, 2026usage-cap
Know you'll run out of Claude Code usage before you run out.
A Claude Code plugin that caps your usage against the 5-hour session limit and
the 7-day weekly limit (the same two bars /usage shows), so you get warned
early and don't get hard-locked in the middle of something.
- Tells you when you'll run out — tracks your burn rate and says "at this rate you hit your cap in ~4h, a day before the window resets", often long before you'd have noticed
- Warns once usage crosses a threshold you set (default 80%)
- Blocks new prompts once usage crosses a hard cap you set (default 95%), so a runaway task can't burn your last few percent and lock you out for hours
- Can stop subagent fan-outs mid-turn (opt-in), the one runaway that can burn a whole window inside a single turn
- Hands your prompt back when it blocks, so a blocked prompt isn't a lost one
/usage-captells you whether it's actually working, instead of leaving you to trust that silence means everything's fine — and/usage-cap setchanges any threshold without hand-editing JSON- Optional statusline showing both bars every turn, colour-coded to your own thresholds
It never blocks SessionStart — only new prompts — so you can always open
Claude Code to check where you stand, even when you're capped.
Requires Node 18+. Cross-platform: Windows, macOS, Linux.
Install
/plugin marketplace add MohammedNihal03/usage-cap
/plugin install usage-cap
Then restart Claude Code — hooks are read at startup — and run
/usage-cap. It'll tell you if anything isn't wired up.
A usage cap only helps if it's active in every project. Installing the plugin
does that already, but if you'd rather skip plugins, add this to
~/.claude/settings.json with an absolute path (${CLAUDE_PLUGIN_ROOT} only
expands for installed plugins):
{
"hooks": {
"UserPromptSubmit": [
{ "matcher": "", "hooks": [ { "type": "command", "command": "node",
"args": ["/absolute/path/to/usage-cap/hooks/check-usage.js"], "timeout": 10 } ] }
],
"SessionStart": [
{ "matcher": "", "hooks": [ { "type": "command", "command": "node",
"args": ["/absolute/path/to/usage-cap/hooks/check-usage.js"], "timeout": 10 } ] }
]
}
}
You won't get the /usage-cap command this way; run
node /absolute/path/to/usage-cap/scripts/doctor.js directly instead.
Is it working?
/usage-cap # health check
/usage-cap set weekly-cap 70 # change a threshold
/usage-cap preset secondary 50 # apply a multi-device policy
The health check matters more than it sounds. The plugin fails open on every error — malformed payload, no network, no usage data, a schema that stopped matching — because it should never be the reason a prompt fails to send. The cost of that choice is that a broken install and a healthy one look identical from the outside: both are silent.
So the hook records every run, and /usage-cap reads it back:
usage-cap doctor
Hook activity
✅ Last ran just now (UserPromptSubmit)
✅ Data source: rate_limits on stdin (the good path)
• Last session reading: 41%
• Last weekly reading: 73%
Burn rate
• Weekly: 12 points ahead of pace (73% spent, ~61% expected by now).
• Weekly (7d) ▅▅▅▆▆▆▇ ↗ 4.3%/h
⚠️ Weekly (7d) reaches your 95% cap in ~3h 55m — before the window resets.
Verdict
✅ Healthy — caps are being enforced.
If the hook has never fired, if the payload schema changed, or if a threshold in your config is unreachable, it says so.
Knowing before you run out
A percentage tells you where you are. It doesn't tell you whether you're going to make it to Sunday. So the plugin keeps a rolling log of readings and works out two things from it.
Burn rate and forecast. From the slope of recent readings it projects when you'll reach your cap, and compares that against when the window actually resets:
📈 usage-cap: current burn rate won't last the window.
Weekly: burning 4.3%/h — reaches your 95% cap in ~3h 55m, 1d 2h before the window resets.
The useful part is that this fires below your warn threshold. The example above is from a session sitting at 78% with an 80% warning — by the time a plain threshold alert goes off, there's usually nothing left to do about it. It's throttled to once per session per window, so it's a heads-up rather than a nag, and it says nothing at all when you're on track to finish the window under your cap.
Pace. Separately, it compares what you've spent against an even spend of the window — "73% spent, ~61% expected by now". Burn rate is about the last few hours; pace is about the whole window. They can disagree, and that's informative: on pace overall but burning hot right now is a real situation and worth seeing.
Forecasts need at least two readings 5 minutes apart in the same window —
below that a slope is noise pretending to be information, so the plugin says
"not enough history yet" instead of making something up. Readings are grouped
by their resets_at value, so a window rollover starts a clean slate rather
than averaging last week into this one.
History lives in ~/.claude/usage-cap-history.json (last 1000 readings, 14
days). Turn the whole thing off with "showForecast": false.
Subagent guard
Blocking UserPromptSubmit stops the next prompt. It can't stop the turn
that's already running — and a fan-out of a dozen subagents inside one turn is
exactly the runaway most likely to eat your remaining window.
This is off by default. Denying a tool call mid-turn is more intrusive than refusing a prompt you typed — you didn't ask for that particular call, and a refusal you didn't expect is easy to misread as something else going wrong. Turn it on when you want it:
{ "subagentGuardPct": 90 }
With that set, spawning subagents at or above 90% is denied:
usage-cap: Task blocked — session (5h) at 92%, at or over your 90% subagent
guard. Spawning subagents here could burn the rest of your window in one turn.
Carry on single-threaded, or: "/usage-cap set guard 95" to raise it,
"/usage-cap set guard off" to turn the guard off.
This covers the Task, Agent, and Workflow tools. Ordinary tool calls are
never touched — the hook is matched to those three tool names, so it doesn't
even run for anything else.
Two deliberate limits:
- It reads the figure recorded at your last prompt, because
PreToolUseinput doesn't carry usage data. That's up to one turn stale, which is the right granularity anyway. - A reading older than 30 minutes is ignored entirely rather than acted on. A stale number is worse than no number.
90% sits between the warning (80%) and the prompt block (95%) on purpose:
warn → stop fanning out → stop entirely. Set it back to null to turn the
guard off again.
Configure your thresholds
Use the command — it validates what you type, shows the result, and won't let you save something that would silently revert to a default.
Every command
| Command | What it does |
|---|---|
/usage-cap | Health check — is it working, what did it last read, are you on track |
/usage-cap set <setting> <value> | Change one setting |
/usage-cap preset primary | This machine warns but never blocks |
/usage-cap preset secondary [pct] | This machine stops at pct (default 50) |
/usage-cap preset default | Back to 80% warn / 95% block |
/usage-cap snooze <duration> | Pause for a while, then resume automatically |
/usage-cap off | Turn everything off until you turn it back on |
/usage-cap on | Turn it back on (also cancels a snooze) |
Every setting
| Setting | Also accepts | Values | Default | What it controls |
|---|---|---|---|---|
session-warn | warnSessionPct | 0–100 | 80 | Warn at this much of the 5-hour window |
session-cap | hardCapSessionPct | 0–101 | 95 | Block new prompts at this much of the 5-hour window |
weekly-warn | warnWeeklyPct | 0–100 | 80 | Warn at this much of the 7-day window |
weekly-cap | hardCapWeeklyPct | 0–101 | 95 | Block new prompts at this much of the 7-day window |
guard | subagentGuardPct | 0–100, off | off | Deny subagent spawns at this level |
forecast | showForecast | on / off | on | Burn-rate tracking, forecasts, trend arrow |
label | deviceLabel | text | — | Name shown in warnings, handy with two machines |
green | greenBelowPct | 0–100 | 50 | Where the statusline turns 🟢 → 🟡 |
echo | echoBlockedPrompt | on / off | on | Hand your prompt back when blocking |
oauth | oauthFallback | on / off | off | OAuth fallback |
A cap of 101 means "never block" — that's how preset primary works.
Keep each warn below its matching cap, or the warning can never fire; the
command tells you if you get that wrong.
Examples
/usage-cap set weekly-cap 70 # stop me at 70% for the week
/usage-cap set guard 90 # also stop subagent fan-outs at 90%
/usage-cap set label "Work laptop" # name this machine in warnings
/usage-cap snooze 2h # not right now — resume by itself later
/usage-cap set forecast off # just caps, no predictions
Or edit ~/.claude/usage-cap.json directly (created automatically on first
run):
{
"warnSessionPct": 80,
"hardCapSessionPct": 95,
"warnWeeklyPct": 80,
"hardCapWeeklyPct": 95
}
| Key | Default | Meaning |
|---|---|---|
warnSessionPct / warnWeeklyPct | 80 | Show a non-blocking warning at or above this. Keep it below the matching hard cap, or it can never fire — the block path returns first. /usage-cap flags this. |
hardCapSessionPct / hardCapWeeklyPct | 95 | Block new prompts at or above this. Set to 101 to disable blocking while keeping warnings. |
subagentGuardPct | null (off) | Deny Task/Agent/Workflow spawns at or above this. 90 is a good starting value. See Subagent guard. |
showForecast | true | Burn-rate tracking, forecasts, pace, and the statusline trend arrow. |
greenBelowPct | 50 | Where the statusline switches 🟢 → 🟡. |
deviceLabel | — | A name shown in warnings and on the statusline. Useful with more than one machine. |
echoBlockedPrompt | true | Include your typed prompt in the block message so you can paste it back. |
oauthFallback | false | See OAuth fallback. |
enabled | true | Master switch. false = the plugin does nothing. See Turning it off. |
snoozeUntil | null | ISO timestamp; enforcement pauses until it passes, then resumes by itself. |
With the subagent guard turned on, the thresholds form a ladder — warn, then stop fanning out, then stop entirely:
80% ──────── 90% ──────── 95%
warn subagent block
guard (opt-in) prompts
Thresholds must be plain integers; anything else falls back to the default and
gets reported by /usage-cap rather than silently ignored.
Set CLAUDE_CONFIG_DIR and the plugin follows it.
Turning it off
Nothing here is permanent, and you never have to uninstall to get out of the way.
| You want | Command | Effect |
|---|---|---|
| Stop blocking me for an hour | /usage-cap snooze 1h | Everything pauses, then resumes on its own |
| Stop blocking me, period | /usage-cap off | Everything pauses until you run on |
| Warnings but never blocking | /usage-cap preset primary | Still warns and forecasts, never blocks |
| Just the subagent guard off | /usage-cap set guard off | Caps and warnings unaffected (this is the default) |
| No forecasts, just caps | /usage-cap set forecast off | Keeps warning and blocking |
| Remove it entirely | /plugin uninstall usage-cap | Gone. Restart Claude Code — hooks load at startup |
Prefer snooze over off. A pause that undoes itself is safer than one you
have to remember to reverse — the whole point is being protected on the day you
forget you turned it off.
While paused, the plugin says so rather than looking normal:
📅⛔ Weekly 99% (resets in 5d) │ 💤 paused 1h 59m
and /usage-cap reports it as a problem, not a setting. That's deliberate: a
cap that's off and a cap that's working must never look the same.
Usage history keeps recording while paused, so forecasts are accurate the moment enforcement resumes.
Two devices on one account
The 5-hour and weekly limits are account-wide, not per-device. The utilization figure each machine receives already includes everything every other machine has spent, so capping works across devices with no coordination.
Because ~/.claude/usage-cap.json is per-machine, each device can hold its own
policy. To keep your main machine unrestricted while a second one stops at half:
Setup
| Run on | Command | Result |
|---|---|---|
| Main machine | /usage-cap preset primary | Warns at 80%, never blocks |
/usage-cap set label "Device A" | Names it in every message | |
| Second machine | /usage-cap preset secondary 50 | Warns at 40%, blocks at 50% |
/usage-cap set label "Device B" | Names it in every message |
Set the label — it appears in every warning and block, so you can tell at a glance which machine stopped you:
🔴 usage-cap [Device B]: prompt blocked — you're at or over a configured hard cap.
What that actually does
Both machines see the same account-wide number, and each compares it to its own cap:
| Account usage | Device A (cap 101) | Device B (cap 50) |
|---|---|---|
| 30% | ✅ works | ✅ works |
| 45% | ✅ works | ⚠️ warns |
| 62% | ✅ works | 🔴 blocked |
| 97% | ⚠️ warns, never blocks | 🔴 blocked |
Two things to understand
It's a reserve, not a quota. Device B stops when the account crosses 50%, not when B itself has spent 50%. If A burns 60% on its own, B is blocked having spent nothing at all. That's usually the point — "never let the second machine eat my last half" — but it is not "B gets its own half."
A true per-device quota isn't possible from this data: the payload reports account totals with no per-device attribution, so B cannot tell its own spend from A's.
Simultaneous use can overshoot a little. Each machine only learns the figure at the start of a turn, so two machines working at once are both reading the same pre-turn snapshot and can land a few percent past a cap before either notices. Fine at 95%. Don't set a cap to 99 and expect precision.
Optional: statusline
Add to ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "node \"/absolute/path/to/usage-cap/scripts/statusline.js\""
}
}
⏳🟡 Session 54% → (resets in 3h) │ 📅🔴 Weekly 91% ↗ (resets in 2d)
Bands come from the same config file the hook uses, so the colours always match
what the hook will actually do: 🟢 below greenBelowPct, 🟡 up to warn*Pct,
🔴 at or above warn*Pct (the hook is warning), ⛔ at or above hardCap*Pct
(the hook is blocking).
The arrow is your burn rate against a sustainable spend of that window: ↗ means you're burning faster than the window can absorb, → is roughly on track, ↘ is comfortable. It only appears once there's enough history to mean something.
How it works
Since Claude Code 2.1, the CLI passes a rate_limits object on stdin to hooks
and statusline commands for Pro/Max/Team accounts:
{
"rate_limits": {
"five_hour": { "utilization": 0.54, "resets_at": "2026-08-21T18:00:00Z" },
"seven_day": { "utilization": 0.91, "resets_at": "2026-08-23T00:00:00Z" }
}
}
Three things run off that:
| File | Runs on | Does |
|---|---|---|
hooks/check-usage.js | UserPromptSubmit, SessionStart | Compares the reading to your thresholds, logs it for the forecast, warns or blocks |
hooks/guard-tools.js | PreToolUse (Task/Agent/Workflow only) | Denies subagent spawns over the guard threshold — no-ops unless you opt in |
scripts/statusline.js | every turn, if you wire it up | Renders both bars with a trend arrow |
scripts/config.js | /usage-cap set / preset | Validates and writes your settings |
scripts/doctor.js | /usage-cap | Reports whether any of the above is actually working |
State the plugin keeps in your config directory:
usage-cap.json— your settings, the only file you editusage-cap-history.json— rolling readings, feeds the forecastusage-cap-state.json— last reading, so/usage-capand the guard can see itusage-cap-cache.json— only if the OAuth fallback is on
Output channels are deliberate. Blocking uses exit code 2 with a message on
stderr, which Claude Code shows you instead of sending the prompt. Warnings use
JSON systemMessage on stdout, because stderr from a hook that exits 0 goes to
the debug log only and is never displayed. Plain-text stdout is avoided on
purpose: on UserPromptSubmit it would be injected into Claude's context,
which is a strange thing for a plugin whose job is conserving usage.
Any computed percentage outside 0–100 is treated as a misread and discarded. A future schema change should make the plugin go quiet and say so, not start blocking you spuriously.
OAuth fallback (opt-in)
If rate_limits isn't on stdin — older CLI, or a plan without session bars —
the plugin can fall back to https://api.anthropic.com/api/oauth/usage using
the OAuth token in ~/.claude/.credentials.json.
This is off by default, on purpose. Reading your local credentials and
sending that token to an undocumented, unversioned endpoint is a reasonable
thing to choose, and not a reasonable default for a plugin you installed from
a marketplace. Turn it on with "oauthFallback": true.
Two things to know:
- The endpoint reports
utilizationon a 0–100 scale, while the stdin payload uses 0–1 for the identically named field. The plugin tracks which source a value came from and converts accordingly. Getting this wrong reads 72% as 7200% and blocks you instantly — if you touch that code, run the tests. - Responses are cached for 60 seconds. Without that, this fires on every single prompt.
- On macOS the OAuth token lives in Keychain rather than
.credentials.json, so this fallback generally won't find a token there.
Testing
node test/run-tests.js
80 cases, no dependencies, run against a throwaway config directory so your real
~/.claude is untouched. Covers blocking, warning, threshold handling,
fail-open behaviour, schema-drift detection, burn-rate and pace maths, the
subagent guard, config editing, pause/snooze, and the payload shapes that broke earlier versions.
To test the block path end-to-end inside Claude Code, temporarily set
hardCapWeeklyPct to 1 and send a prompt. Set it back afterwards.
Known limitations
- Only Claude Code ≥ 2.1 on Pro/Max/Team plans reliably gets
rate_limitson stdin. Other setups depend on the opt-in fallback above. - Prompt blocking applies only to
UserPromptSubmit, so it prevents the next prompt from starting. Mid-turn, the subagent guard can refuse a fan-out, but nothing here can stop work already in flight. - Forecasts are a straight-line projection from recent readings. They're useful for "am I going to make it to Friday", not for precision — a burst of heavy work will move the estimate a lot.
- Anthropic publishes no official schema for
rate_limitsor the OAuth usage endpoint, and Claude Code's hook system moves quickly. The plugin detects and reports drift rather than failing silently, but a shape change still needs a plugin update to fix. - Node 18+ is required. It ships with most developer setups, but it is a real
dependency;
/usage-capreports if it's missing or too old.
License
MIT — see LICENSE.