Pace Claude Code against your 5-hour and weekly limits: fewer lockouts, fewer compactions, and an audit of what you waste.
Python
0
2 commits
updated Oct 5, 2026
Paces Claude Code against your 5-hour and weekly plan limits, so you get locked out less and see what you waste. It does three things:
Paces your usage. A hook watches your 5-hour and weekly usage. When you're on track to run out ("hot": a window is at least 50% used and on pace to hit its limit), it:
claude -p, or sessions working in a temp directory) until the window resets.When usage cools down, it restores your model and advisor settings. Your interactive sessions are never held.
Compacts later. On 1M-window models, sessions auto-compact at about 830k tokens instead of about 570k, so you keep more context and compact less.
Audits your usage. What pacing would have saved, what you wasted (compacting, lockouts, unused weekly and Fable allowance), and how full your limits get, as text or a stats page.
Formerly autocompact-gate; state in ~/.claude/state/autocompact-gate moves to ~/.claude/state/cc-limit-pacer on first run.
Python 3.9+, standard library only.
Before you start
python3 (3.9+) on your PATH. The hooks and commands run Python.git clone https://github.com/RahulBalakavi/cc-limit-pacer has to work for you first (for example gh auth login, or access granted to your GitHub account).1. Install. From a terminal:
claude plugin marketplace add RahulBalakavi/cc-limit-pacer
claude plugin install cc-limit-pacer@cc-limit-pacer
Or from inside Claude Code:
/plugin marketplace add RahulBalakavi/cc-limit-pacer
/plugin install cc-limit-pacer@cc-limit-pacer
Restart Claude Code (or start a new session) so the hooks and commands load.
2. Check it's installed.
claude plugin details cc-limit-pacer@cc-limit-pacer
cc-limit-pacer 0.1.1
Component inventory
Skills (6) backtest, calibrate, setup, simulate, status, uninstall
Hooks (2) SessionStart, UserPromptSubmit (harness-only — no model context cost)
Projected token cost
Always-on: ~233 tok added to every session
3. Set it up inside Claude Code.
/cc-limit-pacer:calibrate 36 24 "2026-10-09 11:00"
/cc-limit-pacer:simulate
/cc-limit-pacer:setup
/cc-limit-pacer:status
Run them in that order. The calibrate numbers are your 5-hour %, your weekly %, and the weekly reset time, all from /usage.
| Command | What it does | Changes anything? |
|---|---|---|
/cc-limit-pacer:calibrate <5h%> <weekly%> "<weekly reset>" | learns your budget from one /usage reading | writes its own state only |
/cc-limit-pacer:simulate [--days N] | replays your last month under each policy, so you can see if it helps you | no |
/cc-limit-pacer:backtest [--days N] | lists every real lockout in your transcripts and replays each one | no |
/cc-limit-pacer:setup [--compact-at TOKENS] | sets autoCompactWindow so sessions compact at about 830k, after backing up settings.json | yes, one setting |
/cc-limit-pacer:status | shows whether you're hot or cool, which levers are active, held runs, and lockouts per week before vs. since install | no |
/cc-limit-pacer:audit [--days N | --since YYYY-MM-DD] [--fable-pct P] | over the last 23 days by default, or from a fixed start date: what the pacer would have saved (compactions, lockouts, hours locked), what you wasted (compacting, lockouts, unused weekly and Fable allowance, advisor), and how full your limits get | no |
/cc-limit-pacer:stats [--days N | --since YYYY-MM-DD] [--fable-pct P] | the same as a stats page, published as an artifact (or opened locally) | no |
/cc-limit-pacer:report [--hours N] | bug checklist: errors, slow runs, missed lockouts, sensor drift, settings changes | no |
/cc-limit-pacer:verbose [on|off] | log every hook run in full (for trials and debugging); off by default | its own config only |
/cc-limit-pacer:uninstall | restores autoCompactWindow and any model or advisor setting the pacer changed | yes, restores |
autoCompactWindow themselves, which is why setup exists.Update
claude plugin marketplace update cc-limit-pacer
claude plugin update cc-limit-pacer@cc-limit-pacer
Then restart Claude Code. Your calibration and logs live in ~/.claude/state/cc-limit-pacer/, so updates keep them.
Uninstall
/cc-limit-pacer:uninstall
claude plugin uninstall cc-limit-pacer@cc-limit-pacer
claude plugin marketplace remove cc-limit-pacer
Run /cc-limit-pacer:uninstall first. Once the plugin is removed, its command to restore your settings is gone too.
Install from a local checkout (to try changes before pushing):
git clone https://github.com/RahulBalakavi/cc-limit-pacer ~/cc-limit-pacer
claude plugin marketplace add ~/cc-limit-pacer
claude plugin install cc-limit-pacer@cc-limit-pacer
After editing, bump version in .claude-plugin/plugin.json, then run the two update commands above. claude plugin validate . checks the manifest.
Troubleshooting
marketplace add fails with an auth or "not found" error: you don't have access to the private repo yet, or git isn't signed in to GitHub.python3 limit_pacer.py install without --plugin). Run python3 limit_pacer.py install --plugin once; it removes the duplicate hooks from settings.json and keeps the plugin's.LIMIT_PACER_ALLOW=1 to let it through, or wait for the reset time in the message.The outputs below are sample numbers; yours will differ.
Every step before install is read-only.
1. Get the code.
git clone https://github.com/RahulBalakavi/cc-limit-pacer && cd cc-limit-pacer
2. Check it works on your machine. This uses a fake ~/.claude in a temp directory and touches nothing real.
python3 test_pacer.py
ok
pacer ok
3. Teach it your budget. Take the numbers from /usage in the CLI, or from the usage card in the app.
python3 limit_pacer.py calibrate --five-hour 36 --weekly 24 --weekly-reset "2026-10-09 11:00"
budgets (API-equivalent $): {'five_hour': 150.0, 'seven_day': 1100.0}
local estimate now: {'five_hour': '36%', 'seven_day': '24%'} (should match what you entered)
4. Replay your last month under each policy. This is the main evidence.
python3 simulate.py --days 32
41210 events over 4.3 weeks; budgets from calibration (5h=150, week=1.1e+03)
real lockouts found in transcripts: 5 5h, 1 weekly
real compactions leave a median 100k context; the simulation compacts to that
policy compactions/wk 5h lockouts weekly hours locked usage held back
today 18.0 4 1 74.0 100% $0
compact@830k 11.5 4 1 81.0 103% $0
830k + pacer 13.0 2 1 38.0 98% $62
How to read the rows:
today is the sanity check. It replays what actually happened, and its lockout counts should roughly match the real ones on the line above (here 4 vs 5 five-hour, 1 vs 1 weekly).compact@830k gives about a third fewer compactions, but the extra usage brings lockouts sooner.830k + pacer is what install sets up: 28% fewer compactions and about half the hours locked. In exchange, $62 of batch work waits during hot stretches.5. Replay each real lockout one by one.
python3 backtest.py --days 32
2410 sessions; 6 lockouts found
lockout (local time) locked 500k if hot 250k if hot result
5h Sep 14 21:10 1.4h 99% 86% no help
5h Sep 19 16:05 1.8h 103% 95% no help
week Sep 20 11:40 60.1h 98% 89% 0.4h later
...
5h Sep 30 22:15 0.2h 101% 91% no help
locked out 71.0h total; gate would have given back ~0.5h
if every session compacted at 500k: 3% less usage over 32d (only 41 of 2410 sessions ever passed 500k)
This is why compaction alone is the wrong knob.
6. Install.
python3 limit_pacer.py install
installed: compaction at ~830k (autoCompactWindow=862000); pacer on SessionStart, UserPromptSubmit; hook=~/.claude/hooks/limit_pacer.py
Add --compact-at 700000 to compact earlier.
7. Check on it. The lockouts-per-week line is the number that proves the value over time.
python3 ~/.claude/hooks/limit_pacer.py status
usage-source=local-estimate state=cool
five_hour used= 12.0% pace=0.50 resets in 3.0h
seven_day used= 39.0% pace=0.80 resets in 91.0h
80 hook runs; hot on 0; held 0 automated prompts
lockouts: 6 in the 30d before install (1.4/wk); 0 since install (0.0/wk over 1.0d)
8. Undo everything.
python3 limit_pacer.py uninstall
install backs up ~/.claude/settings.json, sets autoCompactWindow, and adds a SessionStart and a UserPromptSubmit hook. Each runs in about 0.2s.model one tier down and advisorModel: "off" into your settings, so new sessions pick them up. It shows a one-line notice when it switches state.holding automated run … retry after Mon 04:40. When a held run needs to go now, set LIMIT_PACER_ALLOW=1.~/.claude/state/cc-limit-pacer/pacer.jsonl.Config (~/.claude/state/cc-limit-pacer/config.json) | Default | |
|---|---|---|
levers | true | switch model and advisor while hot |
hold_batch | true | hold automated runs while hot |
use_statusline | true | trust the statusline's rate_limits. Set false if several accounts share one ~/.claude |
Logs live in ~/.claude/state/cc-limit-pacer/ and rotate at 5 MB.
errors.jsonl, always on. Any exception is written with its full traceback, and the prompt still goes through. A bug in this plugin never blocks your session.pacer.jsonl, quiet by default. It logs only runs where something happened: a hot↔cool switch, a settings change by the levers (or a restore skipped because you changed it yourself), or a held prompt./cc-limit-pacer:verbose on # or: python3 limit_pacer.py verbose on
/cc-limit-pacer:verbose off
LIMIT_PACER_VERBOSE=1 claude ... # verbose for one process only
/cc-limit-pacer:report # or: python3 limit_pacer.py report --hours 24
cc-limit-pacer 0.3.0 — last 24h: 29 logged hook runs, 0 errors
latency p50=96ms p95=155ms max=155ms (12 timed runs)
usage source {'local-estimate': 29}
now cool {'five_hour': '12% (pace 0.5)', 'seven_day': '39% (pace 0.8)'}
OK — nothing to look at
report exits 1 and lists what needs a look when it finds any of these. The latency, sensor and coverage checks need verbose logs.
model or advisorModel while hot, so the pacer left your choice in place.UserPromptSubmit runs were logged.
Sample data (python3 docs/sample_stats.py); your page shows your own numbers.
/cc-limit-pacer:audit # or: python3 audit.py --fable-pct 0
/cc-limit-pacer:stats # or: python3 audit.py --html stats.html
WHAT IT WOULD HAVE SAVED (replay of your sessions)
policy compactions/wk 5h lockouts weekly hours locked usage held back
today 18.0 4 1 74.0 100% $0
compact@830k 11.5 4 1 81.0 103% $0
830k + pacer 13.0 2 1 38.0 98% $62
→ -5.0 compactions/wk, -2 lockouts, -36h locked
WHAT YOU WASTED
compacting 70 auto-compactions ≈ $58 API-equivalent (1.3% of your usage)
locked out 4 session + 1 weekly lockouts, 71h unable to work
advisor $170 (4% of usage) on advisor consults
Fable 0% used this week — the whole Fable allowance is going unused
HOW MUCH OF EACH LIMIT YOU USE
Sep 25 – Oct 02 91%
Oct 02 – Oct 09 38% (so far)
5h windows 70 used; median 34%, p90 78%; 4 ran ≥90%, 26 stayed under 25%
simulate replay. Its credibility line compares the replay's lockouts with your real ones; a big gap means the calibration is off./usage reports. Pass --fable-pct with the "Weekly · Fable" %; the commands read it for you when Claude has a usage tool.stats writes ~/.claude/state/cc-limit-pacer/stats.html: current meters, the savings table, the waste ledger, weekly and 5h usage charts, and pacer activity (usage over time needs verbose logs).model in settings during a run doesn't affect it. advisorModel: "off" turns the advisor off; null and "" do not.claude -p run returns the hold message as its result and exits 0. Batch scripts should check the result text.autoCompactWindow. If one turn jumps past the model's real window, the session ends with Prompt is too long and nothing recovers it.status numbers drift from /usage.| File | What |
|---|---|
limit_pacer.py | the pacer hook, plus the install / uninstall / calibrate / status commands |
.claude-plugin/, hooks/, commands/ | the plugin: manifest, the two hooks, and the /cc-limit-pacer:* commands |
audit.py | the audit and the stats page |
docs/sample_stats.py | renders the stats page from sample data, for the screenshot |
simulate.py | replays a month of your history under each policy and lever |
backtest.py | lockout finder and per-window replay |
test_pacer.py | python3 test_pacer.py, uses a fake ~/.claude in a temp directory |
Pace Claude Code against your 5-hour and weekly limits: fewer lockouts, fewer compactions, and an audit of what you waste.
Python
0
2 commits
updated Oct 5, 2026
Paces Claude Code against your 5-hour and weekly plan limits, so you get locked out less and see what you waste. It does three things:
Paces your usage. A hook watches your 5-hour and weekly usage. When you're on track to run out ("hot": a window is at least 50% used and on pace to hit its limit), it:
claude -p, or sessions working in a temp directory) until the window resets.When usage cools down, it restores your model and advisor settings. Your interactive sessions are never held.
Compacts later. On 1M-window models, sessions auto-compact at about 830k tokens instead of about 570k, so you keep more context and compact less.
Audits your usage. What pacing would have saved, what you wasted (compacting, lockouts, unused weekly and Fable allowance), and how full your limits get, as text or a stats page.
Formerly autocompact-gate; state in ~/.claude/state/autocompact-gate moves to ~/.claude/state/cc-limit-pacer on first run.
Python 3.9+, standard library only.
Before you start
python3 (3.9+) on your PATH. The hooks and commands run Python.git clone https://github.com/RahulBalakavi/cc-limit-pacer has to work for you first (for example gh auth login, or access granted to your GitHub account).1. Install. From a terminal:
claude plugin marketplace add RahulBalakavi/cc-limit-pacer
claude plugin install cc-limit-pacer@cc-limit-pacer
Or from inside Claude Code:
/plugin marketplace add RahulBalakavi/cc-limit-pacer
/plugin install cc-limit-pacer@cc-limit-pacer
Restart Claude Code (or start a new session) so the hooks and commands load.
2. Check it's installed.
claude plugin details cc-limit-pacer@cc-limit-pacer
cc-limit-pacer 0.1.1
Component inventory
Skills (6) backtest, calibrate, setup, simulate, status, uninstall
Hooks (2) SessionStart, UserPromptSubmit (harness-only — no model context cost)
Projected token cost
Always-on: ~233 tok added to every session
3. Set it up inside Claude Code.
/cc-limit-pacer:calibrate 36 24 "2026-10-09 11:00"
/cc-limit-pacer:simulate
/cc-limit-pacer:setup
/cc-limit-pacer:status
Run them in that order. The calibrate numbers are your 5-hour %, your weekly %, and the weekly reset time, all from /usage.
| Command | What it does | Changes anything? |
|---|---|---|
/cc-limit-pacer:calibrate <5h%> <weekly%> "<weekly reset>" | learns your budget from one /usage reading | writes its own state only |
/cc-limit-pacer:simulate [--days N] | replays your last month under each policy, so you can see if it helps you | no |
/cc-limit-pacer:backtest [--days N] | lists every real lockout in your transcripts and replays each one | no |
/cc-limit-pacer:setup [--compact-at TOKENS] | sets autoCompactWindow so sessions compact at about 830k, after backing up settings.json | yes, one setting |
/cc-limit-pacer:status | shows whether you're hot or cool, which levers are active, held runs, and lockouts per week before vs. since install | no |
/cc-limit-pacer:audit [--days N | --since YYYY-MM-DD] [--fable-pct P] | over the last 23 days by default, or from a fixed start date: what the pacer would have saved (compactions, lockouts, hours locked), what you wasted (compacting, lockouts, unused weekly and Fable allowance, advisor), and how full your limits get | no |
/cc-limit-pacer:stats [--days N | --since YYYY-MM-DD] [--fable-pct P] | the same as a stats page, published as an artifact (or opened locally) | no |
/cc-limit-pacer:report [--hours N] | bug checklist: errors, slow runs, missed lockouts, sensor drift, settings changes | no |
/cc-limit-pacer:verbose [on|off] | log every hook run in full (for trials and debugging); off by default | its own config only |
/cc-limit-pacer:uninstall | restores autoCompactWindow and any model or advisor setting the pacer changed | yes, restores |
autoCompactWindow themselves, which is why setup exists.Update
claude plugin marketplace update cc-limit-pacer
claude plugin update cc-limit-pacer@cc-limit-pacer
Then restart Claude Code. Your calibration and logs live in ~/.claude/state/cc-limit-pacer/, so updates keep them.
Uninstall
/cc-limit-pacer:uninstall
claude plugin uninstall cc-limit-pacer@cc-limit-pacer
claude plugin marketplace remove cc-limit-pacer
Run /cc-limit-pacer:uninstall first. Once the plugin is removed, its command to restore your settings is gone too.
Install from a local checkout (to try changes before pushing):
git clone https://github.com/RahulBalakavi/cc-limit-pacer ~/cc-limit-pacer
claude plugin marketplace add ~/cc-limit-pacer
claude plugin install cc-limit-pacer@cc-limit-pacer
After editing, bump version in .claude-plugin/plugin.json, then run the two update commands above. claude plugin validate . checks the manifest.
Troubleshooting
marketplace add fails with an auth or "not found" error: you don't have access to the private repo yet, or git isn't signed in to GitHub.python3 limit_pacer.py install without --plugin). Run python3 limit_pacer.py install --plugin once; it removes the duplicate hooks from settings.json and keeps the plugin's.LIMIT_PACER_ALLOW=1 to let it through, or wait for the reset time in the message.The outputs below are sample numbers; yours will differ.
Every step before install is read-only.
1. Get the code.
git clone https://github.com/RahulBalakavi/cc-limit-pacer && cd cc-limit-pacer
2. Check it works on your machine. This uses a fake ~/.claude in a temp directory and touches nothing real.
python3 test_pacer.py
ok
pacer ok
3. Teach it your budget. Take the numbers from /usage in the CLI, or from the usage card in the app.
python3 limit_pacer.py calibrate --five-hour 36 --weekly 24 --weekly-reset "2026-10-09 11:00"
budgets (API-equivalent $): {'five_hour': 150.0, 'seven_day': 1100.0}
local estimate now: {'five_hour': '36%', 'seven_day': '24%'} (should match what you entered)
4. Replay your last month under each policy. This is the main evidence.
python3 simulate.py --days 32
41210 events over 4.3 weeks; budgets from calibration (5h=150, week=1.1e+03)
real lockouts found in transcripts: 5 5h, 1 weekly
real compactions leave a median 100k context; the simulation compacts to that
policy compactions/wk 5h lockouts weekly hours locked usage held back
today 18.0 4 1 74.0 100% $0
compact@830k 11.5 4 1 81.0 103% $0
830k + pacer 13.0 2 1 38.0 98% $62
How to read the rows:
today is the sanity check. It replays what actually happened, and its lockout counts should roughly match the real ones on the line above (here 4 vs 5 five-hour, 1 vs 1 weekly).compact@830k gives about a third fewer compactions, but the extra usage brings lockouts sooner.830k + pacer is what install sets up: 28% fewer compactions and about half the hours locked. In exchange, $62 of batch work waits during hot stretches.5. Replay each real lockout one by one.
python3 backtest.py --days 32
2410 sessions; 6 lockouts found
lockout (local time) locked 500k if hot 250k if hot result
5h Sep 14 21:10 1.4h 99% 86% no help
5h Sep 19 16:05 1.8h 103% 95% no help
week Sep 20 11:40 60.1h 98% 89% 0.4h later
...
5h Sep 30 22:15 0.2h 101% 91% no help
locked out 71.0h total; gate would have given back ~0.5h
if every session compacted at 500k: 3% less usage over 32d (only 41 of 2410 sessions ever passed 500k)
This is why compaction alone is the wrong knob.
6. Install.
python3 limit_pacer.py install
installed: compaction at ~830k (autoCompactWindow=862000); pacer on SessionStart, UserPromptSubmit; hook=~/.claude/hooks/limit_pacer.py
Add --compact-at 700000 to compact earlier.
7. Check on it. The lockouts-per-week line is the number that proves the value over time.
python3 ~/.claude/hooks/limit_pacer.py status
usage-source=local-estimate state=cool
five_hour used= 12.0% pace=0.50 resets in 3.0h
seven_day used= 39.0% pace=0.80 resets in 91.0h
80 hook runs; hot on 0; held 0 automated prompts
lockouts: 6 in the 30d before install (1.4/wk); 0 since install (0.0/wk over 1.0d)
8. Undo everything.
python3 limit_pacer.py uninstall
install backs up ~/.claude/settings.json, sets autoCompactWindow, and adds a SessionStart and a UserPromptSubmit hook. Each runs in about 0.2s.model one tier down and advisorModel: "off" into your settings, so new sessions pick them up. It shows a one-line notice when it switches state.holding automated run … retry after Mon 04:40. When a held run needs to go now, set LIMIT_PACER_ALLOW=1.~/.claude/state/cc-limit-pacer/pacer.jsonl.Config (~/.claude/state/cc-limit-pacer/config.json) | Default | |
|---|---|---|
levers | true | switch model and advisor while hot |
hold_batch | true | hold automated runs while hot |
use_statusline | true | trust the statusline's rate_limits. Set false if several accounts share one ~/.claude |
Logs live in ~/.claude/state/cc-limit-pacer/ and rotate at 5 MB.
errors.jsonl, always on. Any exception is written with its full traceback, and the prompt still goes through. A bug in this plugin never blocks your session.pacer.jsonl, quiet by default. It logs only runs where something happened: a hot↔cool switch, a settings change by the levers (or a restore skipped because you changed it yourself), or a held prompt./cc-limit-pacer:verbose on # or: python3 limit_pacer.py verbose on
/cc-limit-pacer:verbose off
LIMIT_PACER_VERBOSE=1 claude ... # verbose for one process only
/cc-limit-pacer:report # or: python3 limit_pacer.py report --hours 24
cc-limit-pacer 0.3.0 — last 24h: 29 logged hook runs, 0 errors
latency p50=96ms p95=155ms max=155ms (12 timed runs)
usage source {'local-estimate': 29}
now cool {'five_hour': '12% (pace 0.5)', 'seven_day': '39% (pace 0.8)'}
OK — nothing to look at
report exits 1 and lists what needs a look when it finds any of these. The latency, sensor and coverage checks need verbose logs.
model or advisorModel while hot, so the pacer left your choice in place.UserPromptSubmit runs were logged.
Sample data (python3 docs/sample_stats.py); your page shows your own numbers.
/cc-limit-pacer:audit # or: python3 audit.py --fable-pct 0
/cc-limit-pacer:stats # or: python3 audit.py --html stats.html
WHAT IT WOULD HAVE SAVED (replay of your sessions)
policy compactions/wk 5h lockouts weekly hours locked usage held back
today 18.0 4 1 74.0 100% $0
compact@830k 11.5 4 1 81.0 103% $0
830k + pacer 13.0 2 1 38.0 98% $62
→ -5.0 compactions/wk, -2 lockouts, -36h locked
WHAT YOU WASTED
compacting 70 auto-compactions ≈ $58 API-equivalent (1.3% of your usage)
locked out 4 session + 1 weekly lockouts, 71h unable to work
advisor $170 (4% of usage) on advisor consults
Fable 0% used this week — the whole Fable allowance is going unused
HOW MUCH OF EACH LIMIT YOU USE
Sep 25 – Oct 02 91%
Oct 02 – Oct 09 38% (so far)
5h windows 70 used; median 34%, p90 78%; 4 ran ≥90%, 26 stayed under 25%
simulate replay. Its credibility line compares the replay's lockouts with your real ones; a big gap means the calibration is off./usage reports. Pass --fable-pct with the "Weekly · Fable" %; the commands read it for you when Claude has a usage tool.stats writes ~/.claude/state/cc-limit-pacer/stats.html: current meters, the savings table, the waste ledger, weekly and 5h usage charts, and pacer activity (usage over time needs verbose logs).model in settings during a run doesn't affect it. advisorModel: "off" turns the advisor off; null and "" do not.claude -p run returns the hold message as its result and exits 0. Batch scripts should check the result text.autoCompactWindow. If one turn jumps past the model's real window, the session ends with Prompt is too long and nothing recovers it.status numbers drift from /usage.| File | What |
|---|---|
limit_pacer.py | the pacer hook, plus the install / uninstall / calibrate / status commands |
.claude-plugin/, hooks/, commands/ | the plugin: manifest, the two hooks, and the /cc-limit-pacer:* commands |
audit.py | the audit and the stats page |
docs/sample_stats.py | renders the stats page from sample data, for the screenshot |
simulate.py | replays a month of your history under each policy and lever |
backtest.py | lockout finder and per-window replay |
test_pacer.py | python3 test_pacer.py, uses a fake ~/.claude in a temp directory |