Turn your Claude subscription's opaque "percent used" into dollars left, a pace verdict, and a keep-going-or-stop call, so an overnight loop doesn't burn your whole week by Tuesday.
Your usage tools show a percentage and a reset time. That's not enough to answer the question that
actually bites: am I going to hit the weekly cap before I'm done? ccpool reads the account-global
rate_limits % that ccusage structurally can't see, fuses
it with a ccusage-calibrated $/1% into what that % is worth, warns the agent mid-turn when you're
over pace, and downshifts subagent model/effort so an unattended run conserves the pool. It reads
only local data and delegates every dollar to ccusage: complementary to ccusage and native
/status, not a replacement.
- One static binary, ~7.5 MB. A single Go binary (darwin/arm64, stripped), no runtime deps. Only
the
$readout shells out toccusage(Node/npx); without it, ccpool degrades gracefully to%-only. - Reads the number ccusage can't. ccusage reports what you spent; it's blind to the
account-global
rate_limits% that decides when you get throttled. ccpool is the missing half. - Dollars, not just a percent.
~$1,008 left of ~$2,799beats64% usedfor deciding "burn it or bank it." Self-calibrated from your usage (API-equivalent, not billed money). - Enforces, doesn't just advise.
ccpool run -- <cmd>downshifts subagents (opus/hightohaiku/low) when you're ahead of pace, so a fan-out or/loopconserves the pool automatically. - Decides.
ccpool checkgives aKEEP GOING/PACE DOWN/WIND DOWN/ ... verdict plus a working-hours runway, so a long or autonomous loop stops itself before the cap does. - Local and fails open. No network except the ccusage shell-out, no telemetry, and it never blocks Claude Code even on missing or stale data.
$ ccpool status
Weekly pool · 45% used · ~$1,400 left of ~$2,560 (API-equiv) · resets Wed 21:00 (2d 3h)
Pace · 6 pts under pace (51% of the week elapsed) -- banked headroom
Burn · ~0.9%/h -> hits cap in ~2.5d; resets first (in 2.1d) -- you're clear
Runway · budget outlasts the week -> reset (2d 3h) comes first with headroom, burn freelyccpool-demo.mp4
- Install
- Why ccpool exists (and why not just...)
- What each command does
- Keep your statusline: compose, don't replace
- Pace profiles (env)
- Config file
- Config (env)
- Limitations
- Acknowledgements
- Tests
Grab it any of these ways, then run ccpool init once to wire it into Claude Code.
No toolchain needed (you get the prebuilt static binary):
# Homebrew (stable channel; bleeding-edge is SeanLF/tap/ccpool-beta)
brew install SeanLF/tap/ccpool
# or grab a prebuilt binary from the GitHub Releases page (macOS + Linux, amd64 + arm64)macOS builds need 13 Ventura or newer (the Go 1.27 floor). Homebrew checks before it installs
anything; the Releases tarballs carry no OS check of their own, so confirm your version first if
you take one of those. macOS 12 is no longer supported, and go install won't rescue it: go.mod
requires Go 1.27, and Go 1.27 itself needs macOS 13. The last release that runs on Monterey is
v0.2.1. To keep building on 12, clone, lower the go directive in go.mod to 1.26, and build
with Go 1.26; the code still compiles there today, but nothing enforces that it keeps doing so.
From source (needs a Go toolchain, currently Go 1.27+ per go.mod):
go install github.com/SeanLF/ccpool@latest # or pin a version: @v0.2.0
# or from a clone
make build && export PATH="$PWD:$PATH"ccpool init --apply # wires it into Claude Code; zero config, backup taken firstccpool init is the whole setup: it adds the statusLine command plus the mid-turn warn hooks to
~/.claude/settings.json. It is dry-run by default (run it without --apply to see the exact
diff), idempotent, never-clobber (it merges alongside your other hooks, never replaces them),
and symlink-aware (it follows a dotfiles-symlinked settings.json to the real target). Then use
Claude Code as normal; the statusline self-populates ccpool's local store on every render.
init also installs a small bundled skill, checking-usage, into ~/.claude/skills/: it
teaches an agent to check your remaining pool budget via ccpool check and read the
keep-going/stop verdict (handy in long or autonomous loops). It's shown in the dry-run diff,
never-clobbered (edit the wording freely; re-running init won't touch it), and removable with
rm -rf ~/.claude/skills/checking-usage.
To unwire later, remove the
statusLineandhooksentriesinitadded, or set"enabled": false(see Config file) to mute it without touchingsettings.json.
The binary reads Claude Code's local data and the rate_limits number Anthropic already reports.
No network except the ccusage shell-out, no telemetry, and it fails open so it can never break Claude
Code.
- ccusage? It's the authoritative
$engine, and ccpool delegates every dollar to it. But it reports what you spent, and is structurally blind to the account-globalrate_limits% that decides when you get throttled. ccpool is the missing half, not a rival. - Native
/status? It improved a lot (weekly %, 5h %, per-model $, even diagnostic tips), and for a human at the keyboard it's often enough. But it's a manual pull an autonomous loop can't open, it only advises, and it won't project (runway, throttle-before-reset) or decide (keep-going/stop). ccpool projects, enforces, and decides while the loop runs. - 20 lines of jq? That gets you the raw %. It doesn't get you a calibrated dollar value, a pace verdict against how far through the week you should be, or an enforcement lever that actually downshifts a fan-out. That judgment layer is the tool.
- Claude-Code-Usage-Monitor? The closest tool to what ccpool does, and reading its source
informed ccpool's ingest guard (thanked below). It reads the same
rate_limits%, tracks cost, and forecasts burn. But it's a dashboard you watch that only advises ("leaves decisions to you"): ccpool wires into the loop instead (statusline + mid-turnwarnhook), turns the % into a calibrated pool-dollar value rather than per-token pricing, and decides and enforces (keep-going/stop verdict,rundownshift) so an unattended loop self-governs. - Are the dollars real? No, and ccpool says so up front: the
$is API-equivalent, not billed money (you pay a flat subscription). It's the right unit for "burn it or bank it," not for accounting. Self-calibrated from your usage.
ccpool status fuses the account-global rate_limits % with a ccusage-calibrated $/1% into a
dollar value for your weekly pool plus a pace verdict (the four-line readout at the top of this
page). Bare ccpool runs this.
ccpool check is time plus budget plus a keep-going/stop verdict for long or autonomous
loops, distinguishing a temporary 5h throttle from a real "stop for the week." It includes a
working-hours runway: time-to-exhaustion measured per active hour, so sleep doesn't dilute it.
$ ccpool check
time 2026-01-15 21:21 EST (Wed)
data fresh (5s ago)
SESSION 12% used · resets in 1h 38m (5h window)
WEEKLY 45% used · resets in 2d 3h (7d window)
51% of week elapsed -> 6pts UNDER even-burn pace -- expected unless you run 24/7
burn: ~0.9%/h -> even non-stop, resets before you'd reach the cap, fine
runway: budget outlasts the week -> reset (2d 3h) comes first with headroom, burn freely
VERDICT KEEP GOING -- 55% weekly headroom, session has room. Spend the budget you were asked to spend.ccpool run -- <cmd> runs <cmd>, downshifting subagent model/effort when you're burning
ahead of pace, so an unattended /loop or fan-out conserves the pool. It sets
CLAUDE_CODE_SUBAGENT_MODEL and CLAUDE_CODE_EFFORT_LEVEL, which take effect on spawned subagents.
ccpool review [days] is a retrospective: did you use the right model for the work? It flags
expensive-model turns that did trivial work (candidates to downshift).
ccpool warn is a Claude Code hook (UserPromptSubmit / PostToolUse) that warns the agent
mid-turn when it's over pace, near the 5h cap, or near context auto-compaction.
ccpool rhythm (read-only) reads your last 30d of transcripts in the current machine's local
time and measures rhythm strength R. High R (a sharp day/night rhythm) suggests a concrete
CCPOOL_WAKE_HOURS / CCPOOL_WORK_DAYS; low R (continuous loops fill the clock) says stick with
even. A suggester, never an auto-applier.
Run ccpool <command> --help for details on any command.
ccpool is a specialized pool gauge, not a general statusline (it deliberately shows no
model/git/dir, that's your host statusline's job). So if you already run one, add ccpool inside it.
ccstatusline forwards Claude's full payload (incl.
rate_limits) to its Custom Command widgets, so ccpool renders natively as a widget:
# in ccstatusline's config, add a Custom Command widget with command:
ccpool statusline --embed
--embed prints just ccpool's differentiator, pool 45% $1.4k +2↑ (weekly % · $-of-pool left ·
pace), and leaves ctx/5h/model/git to the host. ccpool init auto-detects a ccstatusline statusLine
and prints this recipe instead of offering to replace it. The $ self-populates even if ccpool is
only ever a widget: each render kicks off a throttled background calibration warm-up (never
blocking the line). (claude-powerline and CCometixLine don't forward the payload or don't take
external commands, so there ccpool has to be the statusLine: ccpool init --replace-statusline.)
Want provider-outage warnings too? That's a different question from what your pool is worth,
and AIWatch already answers it: it pairs with a ccstatusline Custom Command
widget to surface Anthropic (plus 30+ other providers') outages right in your line. Add it as a
sibling widget next to ccpool. ccpool itself stays deliberately local and network-free (see
docs/DECISIONS.md for why).
Doing it by hand instead of via init:
Run ccpool statusline bare in a terminal to preview the line (it renders from the freshest
stored snapshot instead of hanging on stdin).
Pace is used% vs how far through the week you should be. By default that's the plain elapsed
fraction of the rolling 7-day window: uniform 24/7, which fits a continuous autonomous-loop operator.
But the window's start is arbitrary (Anthropic-controlled) and few humans burn evenly, so a Mon-Fri
worker would look "ahead of pace" every Friday for no real reason. Describe your rhythm with two
orthogonal knobs (off either one falls to the CCPOOL_PACE_FLOOR residual, not zero, so one late
night isn't read as infinitely ahead of pace):
| knob | default | meaning |
|---|---|---|
CCPOOL_WORK_DAYS |
0-6 (all) |
which days you're active (wday 0=Sun … 6=Sat) |
CCPOOL_WAKE_HOURS |
0-24 (no sleep) |
your waking window on those days |
CCPOOL_PACE_FLOOR |
0.15 |
weight for off-days / sleeping hours |
Examples: 24/7 loop operator, defaults. 9-5 human, WORK_DAYS=1-5 WAKE_HOURS=9-17.
7-day indie who sleeps, WAKE_HOURS=8-24. 4-day week, WORK_DAYS=1-4 WAKE_HOURS=8-24.
CCPOOL_PACE_PROFILE is optional shorthand that just presets those knobs: even (default, all/24h),
weekdays (1-5/24h), workhours (1-5/9-17), or custom for graded CCPOOL_PACE_WEIGHTS (7,
Sun-Sat) × CCPOOL_PACE_HOUR_WEIGHTS (24). An explicit knob overrides the preset. One setting steers
status, check, warn, run's downshift, and the statusline bar together, so they can't disagree.
ccpool reads a config file at ~/.ccpool/ccpool.json (override CCPOOL_CONFIG). Zero-config still
works; every setting has a default, and the file just persists your choices so they survive without
keeping env vars exported. Resolution order is env > file > default: env stays the override, the
file is where a chosen or detected value lives. A realistic file:
{
"enabled": true,
"pace": { "profile": "workhours", "work_days": "1-5", "wake_hours": "9-17" },
"downshift": { "mode": "auto", "model": "haiku", "effort": "low" },
"clock": "24",
"colour": "truecolor",
"tier": "max_20x",
"history": { "keep_days": 30, "min_interval": 60 }
}enabled: false is a kill-switch: the statusline and warn hook go quiet (no-op) without unwiring
anything from settings.json, handy for a holiday or a focus block.
Commands. ccpool config show prints the effective value of every setting plus which layer
supplied it (env/file/default): the "why is my pace X?" answer. ccpool config init seeds the
file (dry-run by default; --apply writes it fill-missing-only, --apply --force re-detects and
overwrites). ccpool init --apply also seeds the config as part of first-time setup, so a single
command wires the hooks and the file. The threshold escape hatches
(CCPOOL_CHECK_*/WARN_*/RUNWAY_*, below) are deliberately not in the file, since they're
power-user overrides on internal judgment calls, not user-shape settings.
| var | default | meaning |
|---|---|---|
CCPOOL_PACE_MARGIN |
3 |
pts over pace before run downshifts / warn nags |
CCPOOL_DOWNSHIFT |
auto |
auto (enforce) · advise (print, don't apply) · off |
CCPOOL_DOWNSHIFT_MODEL / _EFFORT |
haiku / low |
what to downshift subagents to |
CCPOOL_CALIB_TTL |
21600 |
seconds to cache the $/1% calibration |
CCPOOL_CCUSAGE_CMD |
npx -y ccusage@20 |
how to invoke ccusage (pinned major; see internal/calib) |
CCPOOL_HISTORY_KEEP_DAYS |
30 |
prune --history cutoff; 0 = keep forever |
CCPOOL_HISTORY_MIN_INTERVAL |
60 |
min seconds between 5h-only history writes |
CCPOOL_CLOCK |
24 |
wall-clock format: 24 · 12 · auto (best-effort OS detect, macOS-only) |
NO_COLOR / TERM=dumb |
unset | standard no-color.org contract: strips all ANSI |
CCPOOL_HOME, CCPOOL_DB |
~/.ccpool, $HOME/ccpool.db |
ccpool state dir + SQLite store path |
- Downshift is launch-time (per
ccpool runinvocation), not continuous mid-run. Claude Code hooks can't set model/effort, so the wrapper is the enforcement point. The right grain for an unattended fan-out; it won't slow a single expensive main-loop turn. $values are API-equivalent, not billed money (you pay a flat subscription). The right signal for "burn it or bank it," not for accounting. Self-calibrated from your usage; drifts with model mix or promos (recomputed everyCCPOOL_CALIB_TTL).- Single data source. It reads the statusline snapshot; no OAuth fallback. It stamps data age when stale and is robust to the known leak bug (#52326), but it's one source, not ccusage's three-tier hierarchy (yet).
seven_dayis only the ALL-MODELS weekly window. Anthropic tracks separate per-model weekly caps (a Sonnet-only one, #27915, and a distinct Fable bucket) that/statusshows but that are not in therate_limitspayload ccpool reads. So you could hit a per-model cap with ccpool showing the main pool healthy. Treat a healthy weekly % as necessary-but-not-sufficient for model-heavy work and check/status.reviewproxies effort from output-token volume plus tool-call count (effort isn't logged per-turn);ultrathink/thinking inflate output invisibly. Treat it as a hint, not a verdict.
ccpool stands on other people's work:
- ccusage (@ryoppippi) is the authoritative
$engine. ccpool delegates every dollar to it and never hand-rolls pricing. - ccstatusline (@sirmalloc) is the composable
statusline ccpool embeds into as a
--embedwidget. - vhs (Charm) records the
status/init/checkdemo GIFs. - HyperFrames (HeyGen) renders the launch demo video from an HTML composition.
- Claude-Code-Usage-Monitor
(@Maciek-roboblog) independently logs the same
rate_limitshistory; reading its source informed ccpool's ingest guard against Claude's epoch-leak bug and theuser_versionschema migration. - agent-skills (Evil Martians) provided the
good-readmeskill that shaped this README's structure.
Independent and unofficial, not affiliated with Anthropic. ccpool reads Claude Code's local data
and the rate_limits number Anthropic already reports; it never circumvents any limit.
make check # gofumpt + vet + staticcheck + govulncheck + go test ./...Conformance suites diff every command's output against committed golden files (hermetic CCPOOL_*
env, no ~/.claude access). ccusage is mocked in tests via CCPOOL_CCUSAGE_CMD.


