by domanski-ai
Track and rotate your Claude & Codex usage across accounts from one live dashboard — read live, never spending a token.
# Add to your Claude Code skills
git clone https://github.com/domanski-ai/headroomGuides for using cli tools skills like headroom.
Last scanned: 7/14/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-07-14T06:11:11.782Z",
"npmAuditRan": true,
"pipAuditRan": true,
"promptInjectionRan": true
}headroom is an open-source cli tools skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by domanski-ai. Track and rotate your Claude & Codex usage across accounts from one live dashboard — read live, never spending a token. It has 98 GitHub stars.
Yes. headroom passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.
Clone the repository with "git clone https://github.com/domanski-ai/headroom" and add it to your Claude Code skills directory (see the Installation section above).
headroom is primarily written in Python. It is open-source under domanski-ai on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other CLI Tools skills you can browse and compare side by side. Open the CLI Tools category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh headroom against similar tools.
No comments yet. Be the first to share your thoughts!
Top skills in this category by stars
A live dashboard for every Claude and Codex subscription you own — read straight from the providers without spending a single token — that rotates you to the next account with headroom the moment one hits a limit.
The heart of headroom is a live web dashboard you run locally. Run
headroom serve, open http://127.0.0.1:8377, and every account's 5-hour,
weekly, and model-scoped capacity is on one page, updating in real time. It's
an ordinary local web page, so it works in any browser on any OS — you're not
tied to one machine. A menu-bar app and pinnable desktop widgets are optional
extras layered on the same data, for a glance without opening a tab.
https://github.com/user-attachments/assets/71e8ec51-8f0f-4ec2-806f-221b9eb6571f
Five built-in themes (Midnight, Minimal, Chrome, Paper, Terminal), switchable live from the dashboard. The setup wizard asks how you want it to look.
| Midnight | Minimal |
|---|---|
![]() |
![]() |
| Chrome | Terminal |
|---|---|
![]() |
![]() |
If you run more than one Claude or ChatGPT subscription (work + personal + team), you know the drill: a session dies with "you've hit your limit", you have no idea how much is left on the other accounts, and you burn ten minutes logging in and out to find out.
headroom fixes all three problems:
headroom claude launches on the highest-ranked account with
proven headroom. Claude accounts are ranked by how much of the fable
model-scoped weekly window they have left, so a fresh session lands where
you can still switch model family. An explicitly non-Fable launch
(opus/sonnet/haiku) is ranked the opposite way — toward the account
whose Fable week needs the least protecting — because non-Fable usage
drains only the account-wide weekly window, and burning that window on the
wrong account leaves Fable capacity stranded behind a 7-day wall (see
headroom fable below). The order accounts appear in your config breaks
ties, and an account with no readable scoped reading ranks last among the
eligible ones; Codex accounts keep config order. Ranking never overrides
eligibility: an account without proven headroom is skipped whatever it is
ranked. When a limit hits, headroom rotate (or the /rotator skill
inside Claude Code) cools that login down until its window resets and hands
you the next one. Set a reserve (e.g. 10%) and it skips any account
already below that much headroom, so a session starts fresh instead of
hitting a wall mid-task.headroom fable is the scoped-pool calculator: per account
it reports how much of the Fable weekly pool is still reachable through
the account-wide 7-day window, how much is stranded or at risk, and how
much non-Fable slack each account has. The router enforces it: a
non-Fable launch that would strand Fable capacity is demoted whenever an
account with positive slack can take the work instead (never when the
whole fleet is negative — a degraded fleet still routes, least harm
first). Tune the pool-size assumption with routing.fable_pool_ratio
(default 1.0, deliberately pessimistic); headroom fable also shows a
history-calibrated estimate per account when your usage history supports
one.Automatic handoff is on by default — uninterrupted continuation is the
point of headroom. headroom claude stays resident around the Claude process
it launched. If that exact session reaches a subscription cap, headroom
requires three independent proofs before it acts: a current-session StopFailure hook matched as
rate_limit, a narrow session/weekly-cap message, and a new identity-bound
usage read showing at least 99% used in the corresponding account or model
window. The active model family comes from the final API-error transcript
event, not the model used when the session launched. Missing or ambiguous
evidence leaves Claude running.
After every non-mutating preflight succeeds, headroom sends Claude one
SIGTERM, requires its SessionEnd cleanup hook, verifies the final transcript
again, publishes the source bytes plus one content-free headroom boundary
record without overwriting anything in the target account, and resumes with a
forked session. The source transcript is never modified. If post-stop
validation fails, the source session is relaunched
with automation disabled. Three automatic handoffs in any rolling ten minutes
trips the loop guard; the fourth child stays alive. The guard counts
admissions that actually touched a session — one that reached its stop, or
one still in flight — so an admission released without ever stopping a child
(an aborted preemptive attempt, a lost target race) cannot spend the budget a
genuine cap needs.
When there is nowhere to go, headroom waits instead of giving up. A cap
that cannot be answered — every other account is capped too — used to disarm
automatic handoff for that child permanently, while it sat on the capped
account: the one state where it most needs to move. Nothing was disproven, and
the condition fixes itself, so headroom now HOLDS the proof (child alive,
automation armed, a cap_held event, one stderr line) and re-runs the full
preflight every five minutes — nothing is admitted on weaker evidence than a
first attempt would need. The moment an account frees up, the session moves.
Two refusals in that chain hold rather than disarm, because neither is
evidence against the cap: no account with headroom worth moving to, and a
usage collect that failed outright. (A third absence gets its own small bound
rather than the hold: if the transcript has not been flushed far enough to say
which model was running when the cap landed, the lookup is given
HEADROOM_CAP_MODEL_RETRIES further six-second windows — two by default —
before the child is disarmed.)
The destination bar is part of it: a capped session is never moved onto an
account that is itself about to refuse — 5h at or past the preemptive 5h
threshold, weekly or model-scoped weekly at or past 99%
(HEADROOM_CAP_TARGET_WEEKLY=100 restores the plain routing bar) — and when
that leaves nothing, the hold message names every account it skipped and why.
The wait is bounded: 60 attempts five minutes apart, so about five hours
(HEADROOM_CAP_HOLD_SECONDS, HEADROOM_CAP_HOLD_MAX; set the max to 0 for
the old give-up-immediately behaviour). When the budget runs out headroom
disarms exactly as it did before the hold existed: it prints the reason and
how long it waited, emits supervision_lost, and leaves the child alive and
untouched on the capped account. Nothing is killed and nothing is cooled — the
session is simply no longer being watched, and moving it is now a manual
/exit plus headroom handoff. Each new cap proof gets its own fresh budget.
If the capped window resets before then, the hold ends with the session still
armed (cap_cleared) — there is nothing left to rotate away from.
A cap that fresh usage contradicts is not a hold and never was: that still disarms on the first look. Neither is a trust failure — a login the provider rejected or revoked, a slot bound to a different account than expected, an organization that changed underneath the slot, a missing CLI or credential, an API-key seat with no subscription windows at all. Waiting does not fix any of those, so they disarm immediately instead of spending the budget. What a corroborated cap does wait out is the absence of a reading: the provider throttling the usage API, a Codex app-server that would not start, answer, or speak protocol, or one that answered with windows headroom could not map. (On the very first look there is nothing corroborated yet, so an unreadable account row disarms there too — a proof nobody can check must never move a session.)
A hold only ever moves the session on the cap it corroborated when the hold
began, even if a different window has hit the wall meanwhile — a
scoped-weekly cap can never turn into the account-wide handoff nobody proved.
On a retry where fresh usage still resolves to exactly that cap, the attempt
simply proceeds on it. Where it resolves to something else — no cap at all, or
a different window — headroom re-reads the recorded window in the fresh
snapshot and gets one of three answers. Readable and back below the wall: the
cap is over (cap_cleared). Readable and still at the wall: it is not over, so
the session rotates on the recorded cap as soon as an account frees up — set
HEADROOM_CAP_ROTATE_AT_WALL=0 and it keeps waiting instead. Missing,
malformed, or an expired observation: that proves nothing either way, so the
proof is kept and the wait continues. A window the snapshot simply stopped
reporting is never read as a window that reset.
The same asymmetry runs through the rest of the retry. Missing or ambiguous reset metadata on a cap that was already corroborated holds; on a first look it disarms, as it always did.
What comes back is the conversation, not the turn that was refused. The
resumed session starts idle: nothing re-sends the prompt Claude refused, and
background tasks, MCP connections and permission state do not survive a
handoff (see docs/KNOWN-LIMITS.md).
Turn it off in headroom setup, or explicitly in config:
{
"routi