{"slug": "pace-your-claude-code-to-avoid-hitting-limits", "title": "Pace your Claude-code to avoid hitting limits", "summary": "A Claude Code plugin called cc-limit-pacer, version 0.1.1, paces usage against 5-hour and weekly plan limits by dropping new sessions one model tier (Fable to Opus, Opus to Sonnet) with the advisor off once a window is at least 50% used and on pace to hit its limit, and by holding automated SDK or `claude -p` runs until the window resets. The plugin, formerly named autocompact-gate, also raises auto-compaction on 1M-window models from about 570k to about 830k tokens and audits wasted usage; it requires Python 3.9+ and a private GitHub repo clone, and adds roughly 233 tokens to every session.", "body_md": "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:\n\n1. \n**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:\n  - starts **new** sessions one model tier down (Fable → Opus, Opus → Sonnet) with the**advisor off** ;\n  - **holds automated runs** (SDK /`claude -p` , or sessions working in a temp directory) until the window resets.\n When usage cools down, it restores your model and advisor settings. Your interactive sessions are never held.\n2. starts \n3. \n**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.\n4. \n**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.\n\nFormerly `autocompact-gate`; state in `~/.claude/state/autocompact-gate` moves to `~/.claude/state/cc-limit-pacer` on first run.\n\nPython 3.9+, standard library only.\n\n**Before you start**\n\n- You need Claude Code with plugin support, and `python3` (3.9+) on your`PATH` . The hooks and commands run Python.\n- The repo is private. Claude Code clones it with your normal git credentials, so `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).\n\n**1. Install.** From a terminal:\n\n```\nclaude plugin marketplace add RahulBalakavi/cc-limit-pacer\nclaude plugin install cc-limit-pacer@cc-limit-pacer\n```\n\nOr from inside Claude Code:\n\n```\n/plugin marketplace add RahulBalakavi/cc-limit-pacer\n/plugin install cc-limit-pacer@cc-limit-pacer\n```\n\nRestart Claude Code (or start a new session) so the hooks and commands load.\n\n**2. Check it's installed.**\n\n```\nclaude plugin details cc-limit-pacer@cc-limit-pacer\ncc-limit-pacer 0.1.1\nComponent inventory\n  Skills (6)  backtest, calibrate, setup, simulate, status, uninstall\n  Hooks (2)  SessionStart, UserPromptSubmit  (harness-only — no model context cost)\nProjected token cost\n  Always-on:   ~233 tok   added to every session\n```\n\n**3. Set it up inside Claude Code.**\n\n```\n/cc-limit-pacer:calibrate 36 24 \"2026-10-09 11:00\"\n/cc-limit-pacer:simulate\n/cc-limit-pacer:setup\n/cc-limit-pacer:status\n```\n\nRun them in that order. The calibrate numbers are your 5-hour %, your weekly %, and the weekly reset time, all from `/usage`.\n\n| Command | What it does | Changes anything? | \n|---|---|---|\n| `/cc-limit-pacer:calibrate <5h%> <weekly%> \"<weekly reset>\"` | learns your budget from one `/usage` reading | writes its own state only | \n| `/cc-limit-pacer:simulate [--days N]` | replays your last month under each policy, so you can see if it helps *you* | no | \n| `/cc-limit-pacer:backtest [--days N]` | lists every real lockout in your transcripts and replays each one | no | \n| `/cc-limit-pacer:setup [--compact-at TOKENS]` | sets `autoCompactWindow` so sessions compact at about 830k, after backing up`settings.json` | yes, one setting | \n| `/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 | \n| `/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 | \n| `/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 | \n| `/cc-limit-pacer:report [--hours N]` | bug checklist: errors, slow runs, missed lockouts, sensor drift, settings changes | no | \n| `/cc-limit-pacer:verbose [on\\|off]` | log every hook run in full (for trials and debugging); off by default | its own config only | \n| `/cc-limit-pacer:uninstall` | restores `autoCompactWindow` and any model or advisor setting the pacer changed | yes, restores | \n\n- **The pacer hooks start with the plugin.** They change nothing until you've calibrated and your usage actually runs hot.\n- **Plugins can't change `autoCompactWindow` themselves** , which is why`setup` exists.\n\n**Update**\n\n```\nclaude plugin marketplace update cc-limit-pacer\nclaude plugin update cc-limit-pacer@cc-limit-pacer\n```\n\nThen restart Claude Code. Your calibration and logs live in `~/.claude/state/cc-limit-pacer/`, so updates keep them.\n\n**Uninstall**\n\n```\n/cc-limit-pacer:uninstall\nclaude plugin uninstall cc-limit-pacer@cc-limit-pacer\nclaude plugin marketplace remove cc-limit-pacer\n```\n\nRun `/cc-limit-pacer:uninstall` first. Once the plugin is removed, its command to restore your settings is gone too.\n\n**Install from a local checkout** (to try changes before pushing):\n\n```\ngit clone https://github.com/RahulBalakavi/cc-limit-pacer ~/cc-limit-pacer\nclaude plugin marketplace add ~/cc-limit-pacer\nclaude plugin install cc-limit-pacer@cc-limit-pacer\n```\n\nAfter editing, bump `version` in `.claude-plugin/plugin.json`, then run the two update commands above. `claude plugin validate .` checks the manifest.\n\n**Troubleshooting**\n\n- **`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.\n- **The commands don't appear:** restart Claude Code after installing or updating.\n- **The hooks fire twice:** you also ran the script install (`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.\n- **An automated run was \"held\":** that's the pacer protecting your limit. Set`LIMIT_PACER_ALLOW=1` to let it through, or wait for the reset time in the message.\n\nThe outputs below are sample numbers; yours will differ.\n\nEvery step before `install` is read-only.\n\n**1. Get the code.**\n\n```\ngit clone https://github.com/RahulBalakavi/cc-limit-pacer && cd cc-limit-pacer\n```\n\n**2. Check it works on your machine.** This uses a fake `~/.claude` in a temp directory and touches nothing real.\n\n```\npython3 test_pacer.py\nok\npacer ok\n```\n\n**3. Teach it your budget.** Take the numbers from `/usage` in the CLI, or from the usage card in the app.\n\n```\npython3 limit_pacer.py calibrate --five-hour 36 --weekly 24 --weekly-reset \"2026-10-09 11:00\"\nbudgets (API-equivalent $): {'five_hour': 150.0, 'seven_day': 1100.0}\nlocal estimate now: {'five_hour': '36%', 'seven_day': '24%'} (should match what you entered)\n```\n\n**4. Replay your last month under each policy.** This is the main evidence.\n\n```\npython3 simulate.py --days 32\n41210 events over 4.3 weeks; budgets from calibration (5h=150, week=1.1e+03)\nreal lockouts found in transcripts: 5 5h, 1 weekly\n\nreal compactions leave a median 100k context; the simulation compacts to that\n\npolicy         compactions/wk 5h lockouts  weekly hours locked  usage  held back\ntoday                    18.0           4       1         74.0   100%         $0\ncompact@830k             11.5           4       1         81.0   103%         $0\n830k + pacer             13.0           2       1         38.0    98%        $62\n```\n\nHow to read the rows:\n\n- **`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).\n- **`compact@830k`** gives about a third fewer compactions, but the extra usage brings lockouts sooner.\n- **`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.\n\n**5. Replay each real lockout one by one.**\n\n```\npython3 backtest.py --days 32\n2410 sessions; 6 lockouts found\n\nlockout (local time)    locked 500k if hot 250k if hot  result\n5h   Sep 14 21:10         1.4h         99%         86%  no help\n5h   Sep 19 16:05         1.8h        103%         95%  no help\nweek Sep 20 11:40        60.1h         98%         89%  0.4h later\n...\n5h   Sep 30 22:15         0.2h        101%         91%  no help\n\nlocked out 71.0h total; gate would have given back ~0.5h\nif every session compacted at 500k: 3% less usage over 32d (only 41 of 2410 sessions ever passed 500k)\n```\n\nThis is why compaction alone is the wrong knob.\n\n- **The percentage columns** are your usage at the moment of lockout, replayed with early compaction while hot, as a share of the limit.\n- **Compacting earlier barely moves them** , because only a few dozen sessions ever go past 500k.\n- **Lockouts come from volume.** That's what the pacer's other levers go after: holding batch runs and dropping a model tier.\n\n**6. Install.**\n\n```\npython3 limit_pacer.py install\ninstalled: compaction at ~830k (autoCompactWindow=862000); pacer on SessionStart, UserPromptSubmit; hook=~/.claude/hooks/limit_pacer.py\n```\n\nAdd `--compact-at 700000` to compact earlier.\n\n**7. Check on it.** The lockouts-per-week line is the number that proves the value over time.\n\n```\npython3 ~/.claude/hooks/limit_pacer.py status\nusage-source=local-estimate  state=cool\n  five_hour used= 12.0%  pace=0.50  resets in   3.0h\n  seven_day used= 39.0%  pace=0.80  resets in  91.0h\n80 hook runs; hot on 0; held 0 automated prompts\nlockouts: 6 in the 30d before install (1.4/wk); 0 since install (0.0/wk over 1.0d)\n```\n\n**8. Undo everything.**\n\n```\npython3 limit_pacer.py uninstall\n```\n\n- **Settings:**`install` backs up`~/.claude/settings.json` , sets`autoCompactWindow` , and adds a`SessionStart` and a`UserPromptSubmit` hook. Each runs in about 0.2s.\n- **While hot:** it writes`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.\n- **When it cools down:** it restores those settings, unless you changed them yourself in the meantime.\n- **Held runs:** automated prompts are refused with`holding automated run … retry after Mon 04:40` . When a held run needs to go now, set`LIMIT_PACER_ALLOW=1` .\n- **Logs:** every hook run is written to`~/.claude/state/cc-limit-pacer/pacer.jsonl` .\n- **What the replay leaves out:** quality loss from compacting or from cheaper models, and held work running later, so the lockout gains are optimistic.\n\n| Config ( `~/.claude/state/cc-limit-pacer/config.json` ) | Default |  | \n|---|---|---|\n| `levers` | `true` | switch model and advisor while hot | \n| `hold_batch` | `true` | hold automated runs while hot | \n| `use_statusline` | `true` | trust the statusline's `rate_limits` . Set`false` if several accounts share one`~/.claude` | \n\nLogs live in `~/.claude/state/cc-limit-pacer/` and rotate at 5 MB.\n\n- **`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.\n- **`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.\n- **Verbose mode** logs every hook run in full: session, entrypoint, cwd, the usage estimate and its source, time to reset, calibration age and budgets, and how long the hook took. Turn it on when you try the plugin or chase a bug, and off again afterwards:\n\n```\n/cc-limit-pacer:verbose on                    # or: python3 limit_pacer.py verbose on\n/cc-limit-pacer:verbose off\nLIMIT_PACER_VERBOSE=1 claude ...           # verbose for one process only\n/cc-limit-pacer:report                        # or: python3 limit_pacer.py report --hours 24\ncc-limit-pacer 0.3.0 — last 24h: 29 logged hook runs, 0 errors\n  latency  p50=96ms  p95=155ms  max=155ms  (12 timed runs)\n  usage source {'local-estimate': 29}\n  now  cool  {'five_hour': '12% (pace 0.5)', 'seven_day': '39% (pace 0.8)'}\n\nOK — nothing to look at\n```\n\n`report` exits 1 and lists what needs a look when it finds any of these. The latency, sensor and coverage checks need verbose logs.\n\n- **Hook errors** , with the latest error message.\n- **A slow hook:** p95 over 1s. Every prompt waits on it.\n- **A missed lockout:** a real lockout in your transcripts while the pacer was cool in the hour before it.\n- **Sensor drift:** the estimate read under 80% just before a lockout.\n- **No usable reading:** usage is uncalibrated, the calibration is more than 3 days old, or the sensor failed.\n- **A held interactive prompt** , meaning a prompt that wasn't batch work got held.\n- **A skipped restore:** you changed`model` or`advisorModel` while hot, so the pacer left your choice in place.\n- **Hooks not loaded:** no`UserPromptSubmit` runs were logged.\n\n*Sample data (`python3 docs/sample_stats.py`); your page shows your own numbers.*\n\n```\n/cc-limit-pacer:audit                         # or: python3 audit.py --fable-pct 0\n/cc-limit-pacer:stats                         # or: python3 audit.py --html stats.html\nWHAT IT WOULD HAVE SAVED (replay of your sessions)\n  policy         compactions/wk 5h lockouts  weekly hours locked  usage  held back\n  today                    18.0           4       1         74.0   100%         $0\n  compact@830k             11.5           4       1         81.0   103%         $0\n  830k + pacer             13.0           2       1         38.0    98%        $62\n  → -5.0 compactions/wk, -2 lockouts, -36h locked\n\nWHAT YOU WASTED\n  compacting      70 auto-compactions ≈ $58 API-equivalent (1.3% of your usage)\n  locked out      4 session + 1 weekly lockouts, 71h unable to work\n  advisor         $170 (4% of usage) on advisor consults\n  Fable           0% used this week — the whole Fable allowance is going unused\n\nHOW MUCH OF EACH LIMIT YOU USE\n  Sep 25 – Oct 02     91%\n  Oct 02 – Oct 09     38%  (so far)\n  5h windows      70 used; median 34%, p90 78%; 4 ran ≥90%, 26 stayed under 25%\n```\n\n- **Saved** reuses the`simulate` replay. Its credibility line compares the replay's lockouts with your real ones; a big gap means the calibration is off.\n- **Wasted** is measured from transcripts: the summary call plus cache rebuild of every auto-compaction, hours between each lockout and its reset, weekly allowance left at reset (full weeks only), advisor consults.\n- **Fable** has its own weekly allowance that only`/usage` reports. Pass`--fable-pct` with the \"Weekly · Fable\" %; the commands read it for you when Claude has a usage tool.\n- `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).\n\n- **Model and advisor changes only reach new sessions.** Changing`model` in settings during a run doesn't affect it.`advisorModel: \"off\"` turns the advisor off;`null` and`\"\"` do not.\n- **Held headless runs:** a held`claude -p` run returns the hold message as its result and**exits 0** . Batch scripts should check the result text.\n- **Compaction timing:** Claude Code compacts about 32k tokens below`autoCompactWindow` . If one turn jumps past the model's real window, the session ends with`Prompt is too long` and nothing recovers it.\n- **The usage estimate is approximate.** It only sees this machine's transcripts. Usage from claude.ai or other machines is invisible, so recalibrate if the`status` numbers drift from`/usage` .\n\n| File | What | \n|---|---|\n| `limit_pacer.py` | the pacer hook, plus the `install` /`uninstall` /`calibrate` /`status` commands | \n| `.claude-plugin/` ,`hooks/` ,`commands/` | the plugin: manifest, the two hooks, and the `/cc-limit-pacer:*` commands | \n| `audit.py` | the audit and the stats page | \n| `docs/sample_stats.py` | renders the stats page from sample data, for the screenshot | \n| `simulate.py` | replays a month of your history under each policy and lever | \n| `backtest.py` | lockout finder and per-window replay | \n| `test_pacer.py` | `python3 test_pacer.py` , uses a fake`~/.claude` in a temp directory |", "url": "https://wpnews.pro/news/pace-your-claude-code-to-avoid-hitting-limits", "canonical_source": "https://github.com/RahulBalakavi/cc-limit-pacer", "published_at": "2026-10-06 06:18:08+00:00", "updated_at": "2026-10-06 06:49:33.987128+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "large-language-models"], "entities": ["Claude Code", "cc-limit-pacer", "RahulBalakavi", "autocompact-gate", "GitHub", "Python"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/pace-your-claude-code-to-avoid-hitting-limits", "markdown": "https://wpnews.pro/news/pace-your-claude-code-to-avoid-hitting-limits.md", "text": "https://wpnews.pro/news/pace-your-claude-code-to-avoid-hitting-limits.txt", "jsonld": "https://wpnews.pro/news/pace-your-claude-code-to-avoid-hitting-limits.jsonld"}}