A Claude Code plan has two usage windows: a rolling 5-hour one and a 7-day one. Claude Code shows you both percentages and then does nothing with them. I got tired of leaving the desk mid-run and coming back to a session that had either stopped dead or quietly spent money, so I wrote cclimit: a Claude Code usage limit you set yourself. It stops the turn at a percentage you choose, says how much is left, and waits for you to decide.
This post covers why the built-in behaviour is not enough, how the plugin gets at numbers a plugin is not really given, what the three actions do, and where I would put the line.

The Problem
When you run out, one of two things happens. The session stops and waits for the reset, or, if extra usage is enabled on the account, it keeps going and starts billing. Neither one asks you first.
The built-in machinery is all reactive: a failure handler that resumes after a rate limit has already been hit, a one-time consent prompt for extra usage, a monthly spend cap. Nothing watches the percentage climb and stops at a line you drew. That is the one thing I wanted, and it is the only thing cclimit does.
What I Built
A Claude Code usage limit here is one number: you set a line, usage crosses it, and the next thing Claude Code tries to do stops.
cclimit: 5h usage hit 87% of your plan (your limit: 85%).
Stopped before running Bash. Window resets Aug 26, 14:20 (in 42m).
/cclimit go continue until the window resets
/cclimit 5h 92 raise the line
/cclimit off turn cclimit off
The turn ends here either way: ask for the work again afterwards.Nothing runs until you answer. /cclimit go stands down until the window resets, so you are asked once per crossing rather than once per tool call.
Installation
Prerequisites
Node 18 or newer on PATH. Claude Code’s native installer does not ship a Node runtime, so check first:
node -vStep 1: install the plugin
/plugin marketplace add epogonii/cclimit
/plugin install cclimit@cclimitStep 2: run the third command, which is not optional
/cclimit installIt is worth knowing what this one does, because it edits your settings. The usage percentages exist in exactly one place a plugin can reach: the JSON payload Claude Code writes to the statusline command’s stdin. Hook payloads do not carry them at all. So install puts a collector in front of whatever statusline you already have:
node <plugin>/scripts/sink.mjs | your-existing-statusline-commandThe collector copies stdin through untouched, so your statusline looks exactly as it did, and writes the two percentages to ~/.claude/cclimit/. Your settings.json is backed up to settings.json.cclimit-backup first, padding is preserved, and refreshInterval is set to 10s if it was missing or slower than 30s, because a reading nobody refreshes goes stale and cclimit ignores stale readings. If you have no statusline at all, install adds a minimal one showing 5h 42% · 7d 11%. /cclimit uninstall puts the original back and deletes the wrapper.
Step 3: verify
/cclimit statusExpected result: two bars with percentages in them. If the percentages are missing, the collector is not being called, which means the statusline is not wired up.
Reading The Status
cclimit is on · action: stop
5h ███████████████████░░░░│░ 79% used
stop at 85% · ceiling 95% · notice at 70%
climbing 0.3%/min - 95% in about 61m · resets Aug 26, 13:00 (in 1h 2m)
at this rate about 97% by reset
last 60m ▃▃▂▂▄▅▅▇██▇▅▄▃▃▂▂▁▁▁▂▃▄▄▅▅▄▃▂▂
7d ████████░░░░░░░░░░░░░░│░░ 35% used
stop at 90% · no notice
resets Aug 30, 22:00 (in 105h 1m)The tick in the bar is where the work stops: the ceiling if you have one, the line otherwise. The climb rate only appears once there are enough readings behind it to mean something, and the projection under it only while the reset is close enough for the current pace to say anything about it, which is why the 7-day window rarely gets one. The sparkline is the last hour of spending, one cell per two minutes, drawn from what was spent inside each cell rather than the total it stood at.
The Three Actions
| Action | What a crossing does | You keep the turn |
|---|---|---|
stop (default) | halts the turn, once per crossing | no |
ask | routes the tool call to the permission prompt | yes, one call at a time |
warn | prints a line, blocks nothing | yes |
stop halts the turn outright and shows the reason. The turn is gone, not paused: /cclimit go lifts the line for what comes next, it does not resume what was interrupted, so ask for the work again afterwards.
ask routes the tool call to the normal permission prompt, with the reason printed inside it, so you get allow or deny in the moment and keep the turn. Know what it costs: a permission answer applies to that one call, and the next tool call asks again. That is a property of the permission system rather than a bug here, and it is why stop is the default.
warn blocks nothing and prints a line above the answer saying where usage stands. All three describe what happens at the line. A ceiling always stops, whatever the action is, and /cclimit go cannot lift it. That is the point of having one.
Running Cheaper Instead Of Stopping
/cclimit downgrade sonnet past the line, subagents run on sonnet
/cclimit downgrade off back to stopping (the default)Off unless you ask for it. With it on, crossing the line stops nothing: every subagent started from there on has its model rewritten to the cheaper one, and the prompt is told once that this is happening.
What it cannot do is move your session onto the cheaper model. A hook can rewrite the input of a tool call, which is where a subagent’s model lives, and nothing in the hook interface can change the model of the session itself. So the message says /model sonnet and leaves that key press to you. Subagents are where the fan-out spending goes anyway, which is the part worth automating.
The Commands
/cclimit 5h 85 stop at 85% of the 5-hour window
/cclimit 7d 90 stop at 90% of the 7-day window
/cclimit ceiling 5h 99 the number /cclimit go cannot lift
/cclimit notice 5h 75 say something at 75%, block nothing
/cclimit go continue until the current window resets
/cclimit action stop|ask|warn what a crossing does
/cclimit alert bell|notify|off how loud an interruption is
/cclimit on | off reinstate or disable, without uninstallingWhere A Claude Code Usage Limit Should Sit
The defaults are 85% of the 5-hour window and 90% of the 7-day one. The 5-hour window is the one that bites during a working session; the 7-day one is the one that ends your week early. If your account has extra usage enabled, every percent past your line costs money, so set them lower than feels necessary and put a ceiling behind them for the moment you tell yourself you will stop after just one more run.
Gotchas
- Without
/cclimit installthe plugin has no numbers to act on. The statusline is the only source. - A
refreshIntervalslower than 30s makes readings stale, and stale readings are ignored, soinstallsets 10s. stopends the turn rather than pausing it. Whatever was in flight has to be asked for again.askcosts a permission prompt per tool call, which gets old fast in a long turn.downgrademoves subagents only. Your own session’s model is yours to change.
Takeaways
- Claude Code knows your usage percentages and hands them to exactly one place: the statusline’s stdin. Anything that wants them has to sit in that pipe.
- Everything built in is reactive. A Claude Code usage limit you set in advance is a different thing from a limit you hit.
- Stopping the turn once per crossing beats asking once per tool call, which is why
stoprather thanaskis the default. - A hook can rewrite a tool call’s input but not the session’s model. That boundary decides what a plugin like this can and cannot automate.
Links
- Source and issues: github.com/epogonii/cclimit
- Licence: MIT. Zero dependencies, no network access.
- Free and staying free. If it saved you a bill: GitHub Sponsors or PayPal.
Status: the plugin is still in review. The marketplace commands above install it straight from the repository in the meantime.
