Stop Claude Code before your plan usage runs out.
Halts the turn at a percentage you choose, says how much is left, and waits for you to decide.
What it does · Install · Commands · The ceiling · The heads-up · When it resets · The three actions · Running cheaper · Config
Your plan has two usage windows: a 5-hour one and a 7-day one. Claude Code shows the percentages, and then does nothing with them. 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
StopFailure handler that resumes after a rate limit is 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.
You set a line. Usage crosses it. 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.
The reset time is printed in your own locale, on a 24-hour clock.
Nothing runs until you answer. /cclimit go stands down until the window resets,
so you are asked once per crossing, not once per tool call.
Subagent launches say so explicitly, because a Task call is not one tool
call; it is a whole session's worth of them starting at once.
cclimit is listed in Anthropic's plugin directory. In Claude Code v2.1.287 or
later, run /plugin directory, find cclimit, install it, and then run:
/cclimit install
The directory serves a reviewed version pinned to one commit, so it can trail this repository. To follow every release as it ships, install from this repository's own marketplace instead:
/plugin marketplace add epogonii/cclimit
/plugin install cclimit@cclimit
/cclimit install
Install it one way, not both: two copies run every hook twice.
/cclimit install is not optional, and it is worth knowing what it does.
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. 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/.
settings.json is backed up to settings.json.cclimit-backup first, your
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, install adds a minimal one showing 5h 42% · 7d 11%.
/cclimit uninstall puts the original back and deletes the wrapper.
/cclimit status |
where usage stands, what the lines are, whether anything is being held |
/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; off removes it |
/cclimit notice 5h 75 |
say something at 75% without blocking anything; off removes it |
/cclimit reserve 5 |
keep subagent launches 5 points clear of the ceiling; off removes it |
/cclimit go |
continue until the current window resets |
/cclimit action stop|ask|warn |
what a crossing does; see below |
/cclimit downgrade sonnet |
past the line, run subagents cheaper instead of stopping; off removes it |
/cclimit alert bell|notify|off |
how loud an interruption is; bell by default |
/cclimit config |
every setting and the command that changes it |
/cclimit on / /cclimit off |
reinstate / disable, without uninstalling anything |
/cclimit install / /cclimit uninstall |
wire the collector into the statusline, or remove it |
/cclimit status is the one worth looking at:
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.
Claude Code namespaces plugin commands, so each of these is really
/cclimit:status, /cclimit:go and so on, which is what the / menu shows
and completes. The two-word form above works because Claude Code reads the
first word after the plugin name as the command. /cclimit on its own does
not resolve to anything; use /cclimit status.
All of them are yours to type and Claude's to leave alone. The command files are
marked as not model-invocable, and the gate exempts only a prompt that starts
with /cclimit, never a tool call, so the model can neither call the commands
nor reach the binary behind them. It cannot raise the line, snooze, or switch
the plugin off. Deciding to spend past the line is the one thing this plugin
exists to keep in your hands.
One line gives you two answers and no third: stop, or /cclimit go, which
lifts the line for the rest of the window. Answering "let me finish this" costs
you every percent between here and 100.
A ceiling is that third answer:
/cclimit 5h 85 the line: work stops here and asks
/cclimit ceiling 5h 99 the ceiling: work stops here and does not ask
go still means carry on, and now it carries on to 99 rather than to the end of
the plan.
| line | ceiling | |
|---|---|---|
| What crossing it does | depends on action |
always stops |
/cclimit go |
lifts it until the window resets | says it still stands |
Under action warn |
says something, blocks nothing | stops anyway |
| Reachable by the model | no | no |
| Set by default | 85% / 90% | none until you set one |
Removing one is /cclimit ceiling 5h off.
What this buys is unattended work. Without a ceiling a long task either waits
for you at the line or, once you have said go, runs to the end of the plan
while you are not watching. With one, you can leave.
While a ceiling is set, the stop at the line says how much room is left:
cclimit: 5h usage hit 85% of your plan (your limit: 85%).
Stopped before running Bash. Window resets Aug 26, 14:20 (in 42m).
Your ceiling is 99%, about 14m away at the current rate.
That estimate is measured, not guessed: cclimit keeps the last few dozen readings and divides. No trail, a flat one, or a window that has just reset: the sentence simply ends after the ceiling. The model is never asked to predict anything, and could not act on it if it were.
A line stops the turn wherever the turn happens to be, which is rarely a good place. A notice is the same number said early, before anything is at stake:
/cclimit notice 5h 75 say something at 75%
/cclimit 5h 80 stop at 80%
At 75% one line appears above the answer and nothing else changes:
cclimit: 5h usage is at 76% of your plan. Work stops at 80%, about 8m away at the current rate. Window resets Aug 26, 14:20 (in 42m).
Nothing is blocked — this is the heads-up, said once per window.
Once per window is the whole design. It is recorded against the window's reset
time, so the next window says it again and the current one does not say it
twice; a warning repeated at every tool call is a warning nobody reads. Under
/cclimit go it stays quiet: you have already said you know.
There is none until you set one, it has to sit below the line, and it decides nothing; it is the only number here that exists purely to be read.
The window that stopped you turns over on its own, and the last thing cclimit said about it was that it was full. So it says one more thing when it is not:
cclimit: the 5h window reset — usage is at 4% of your plan. It was at 91% before the reset.
Nothing is being held. Work stops again at 85%. The new window resets Aug 26, 18:00.
Said once, on the first prompt after the reset, however many hours later that is. A window nobody was waiting on, one that never reached its notice or its line, resets in silence.
Every open session renders its own statusline, so they all write to the same trail, and a session sitting idle keeps rendering the usage it last saw, which can be hours old. Usage inside a window only ever climbs, and only a real reset moves the reset time, so a reading that comes back lower in the same window, or that belongs to a window which has already turned over, is dropped rather than allowed to stand in for the live one.
| 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 (default): the turn halts outright and the reason is shown. One
interruption per crossing, and nothing runs after it until you say so. 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. If
losing the turn is the part you mind, ask is the action that keeps it.
ask: the tool call is routed to the normal permission prompt: the box at
the bottom of the terminal, answered with the arrow keys, with the reason for
the stop printed inside it. You get allow/deny in the moment. Be aware of what this costs: a permission answer
applies to that one call. The next tool call asks again. That is a property of
the permission system, not a bug here; it is why stop is the default.
warn: nothing is blocked. A line appears above the answer saying where
usage stands. For people who want the heads-up and not the brakes.
All three describe what happens at the line. A ceiling always stops.
/cclimit alert bell ring the terminal bell (the default)
/cclimit alert notify ring it and raise a desktop notification
/cclimit alert off say nothing to the terminal
An interruption arrives in the middle of a turn, which is exactly when you have
gone to do something else. That is the situation the plugin is for, and a
message nobody is looking at is not much better than no message. So a stop, an
ask and a warn all ring the bell on their way out. A blocked prompt
doesn't: you pressed enter a second ago and are still watching the screen.
Neither does a heads-up, which is not an interruption.
A warn rings once a window rather than once a tool call. It blocks nothing, so
the same warning comes back on the next call and the one after that; saying it
every time is the point of the action, but ringing every time would be the
interruption you chose warn to avoid. A stop ends the turn and an ask waits
for an answer, so neither can repeat faster than you can act on it.
The bell works everywhere. notify adds a desktop notification on the terminals
that have one:
| OSC 9 | iTerm2, WezTerm, Windows Terminal, ConEmu |
| OSC 99 | kitty |
| OSC 777 | Ghostty, Warp, foot, urxvt |
Anything else gets the bell alone, because a terminal sent a sequence it does not recognise can print the payload as text instead of swallowing it. That includes macOS Terminal.app, Alacritty, xterm, Konsole, and GNOME Terminal and the rest of the VTE family. OSC 777 reached VTE as a distribution patch rather than upstream, so the same terminal answers it on one machine and ignores it on the next, and a hook has no way to tell which. Inside tmux or screen it is the bell as well: passing an OSC through to the outer terminal needs a wrapper that is not on the allowlist.
The plugin never writes to the terminal itself; hooks have no terminal to write
to. It hands the sequence to Claude Code, which emits it. Claude Code only does
this in an interactive session, so nothing rings under claude -p.
/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. A ceiling still stops everything; that is what a ceiling is for.
It needs a Claude Code new enough to take a model on a subagent launch, since
that is the field being rewritten. If launches start erroring once it is on,
/cclimit downgrade off puts them back.
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 is anyway; this is the part worth automating.
/cclimit ceiling 5h 95 the ceiling
/cclimit reserve 5 no subagent may start on the last 5 points in front of the ceiling
/cclimit reserve off back to launching right up to the ceiling (the default)
A ceiling stops work at a number, and it can only stop the work it is asked about. There are exactly two moments it gets asked: when you send a prompt, and before a tool call runs. A subagent is neither. It is one tool call to start and a whole session's worth of spending afterwards, in a context the gate never sees, and it keeps spending after everything in your session has been stopped. Eight of them running at once is how a 95% ceiling ends the window at 108%.
So a reserve is room the launch has to leave. With reserve 5 and a 95%
ceiling, a launch at 89% is fine and one at 91% is refused:
cclimit: 5h usage is at 91% and your ceiling is 95% — 4% of room, no more than the 5 points
a subagent launch has to leave.
Not started. One launch is a whole session's worth of tool calls, and they go on spending
after everything here has been stopped. Window resets Aug 26, 14:20 (in 42m).
The same work done in this session spends the same room one call at a time, which is the
pace the ceiling can stop.
Only the launch is refused — the turn carries on. That is the point: the work is not cancelled, it is moved back into this session, where it spends the same room one tool call at a time and the ceiling gets a say before each one. Every other tool call passes untouched until a real line or ceiling is crossed.
The calls it holds are Task, the Agent name for the same thing, and
Workflow, whose script fans out into as many agents as it asks for. All three
start work that never comes back past this gate.
It needs a ceiling on that window and does nothing without one, since it is
measured against that number and not against the line. /cclimit go does not
lift it, for the same reason it does not lift the ceiling. Past the line it
comes first, before the action and before downgrade: a cheaper subagent is
still a subagent, and a whole session of them still lands on the ceiling.
Off unless you set it, because it refuses something that used to be allowed. Five points is a reasonable start; raise it if your work fans out widely.
One thing it cannot catch: several launches issued in the same turn all see the
same reading, so reserve 5 at 89% lets a batch of them through together. The
reserve is a floor under a launch, not a budget across a batch — size it for the
fan-out you actually use.
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, the numbers past your line cost money, so set them lower than feels necessary.
~/.claude/cclimit/config.json, written by the commands above:
{
"enabled": true,
"action": "stop",
"thresholds": { "five_hour": 85, "seven_day": 90 },
"ceilings": { "five_hour": null, "seven_day": null },
"notices": { "five_hour": null, "seven_day": null },
"reserve": null,
"downgrade": null,
"alert": "bell",
"snoozeUntil": null,
"maxStaleSeconds": 120
}Also in that directory: limits.json (the last reading), history.json (the
trail behind it, for the climb rate and the sparkline), breach.json (present
only while a line is being held), notice.json (which windows have had their
heads-up), resume.json (a reset waiting to be announced),
statusline-wrap.sh (written by install). Delete the directory to reset.
The plugin is free and stays free. If it saved you a bill:
| GitHub Sponsors | github.com/sponsors/epogonii, monthly or one time |
| PayPal | paypal.me/pogonii |
| Bitcoin | bc1qe6fjj3uv23e2yx2ry3wwhyrl7s2pqshau7mga3 |
| Ethereum | 0xDC9e1EfA0F8FAE71377F4018d4ff7D123369438e |
| Solana | 3sYQyR27CVz1VcwCfoDLUioaAHk8jspQaSDHXEvBALxg |
MIT. See LICENSE.
