Claude Code Limit Plugin - Marcel-Bich/marcel-bich-claude-marketplace GitHub Wiki
Live API usage in Claude Code statusline - colored progress bars, Git info, tokens, session metrics, device tracking, and more.
Use case: You want to see your actual API usage limits (the same data shown by /usage) directly in the statusline, updating with each Claude response.
Unlike tools that estimate usage from local logs, this plugin fetches the real utilization data from Anthropic's API.
-
Real API Data - Shows actual utilization from Anthropic's OAuth API (same as
/usage) - Colored Progress Bars - Visual indicators with signal colors based on utilization
-
Multiple Limits - 5-hour, 7-day, Sonnet, and Extra Credits, plus further entries of the API's
limits[]list (e.g. per-modelweekly_scopedlimits) -
Reset Times - Shows exact reset date and time for each limit; after a reset time has passed the bar shows
0.0% ... (reset) -
Stale Marker -
[stale 12m]marks API numbers older thanCLAUDE_MB_LIMIT_STALE_AFTER - Highscore Tracking - Track your highest token usage per plan (enabled by default)
- Est100% Estimate - Per-device estimate of the token count at 100 % API utilization, shown on the device line
-
Averages -
[AvgPeak:X%](average peak per completed window) and[Avg:Y%/h]/[Avg:Y%/d](average consumption incl. idle time) - Deduplicated Token Ledger - One ledger for main agent and subagents, every API message counted once, bounded reads that never block the statusline
- CWD Display - Current working directory
-
Git Info - Worktree, changes (+X,-Y) with colors (green/red), and branch, prefixed with
git: <parent>/<repo>showing the resolved target repo (follows the agent into whatever repo it last worked in, even from a non-git hub directory) - Context Metrics - Used tokens, tokens left, context max, context left %
-
Token Metrics - Session sums (main agent + its subagents) from the ledger: Input (incl. cache writes), Output, Cached (cache reads), Work Tokens; falls back to
LastReq(last request) when the ledger is unreadable - Session Info - Session duration, API duration, session cost
- Smart Display - Only shows limits that are available/relevant
- Cross-Platform - Works on Linux, macOS, and WSL2
-
Provider Support - Native Anthropic API plus z.ai / GLM Coding Plan (auto-detected via
ANTHROPIC_BASE_URL)
| Command | Description |
|---|---|
/limit:highscore |
Display highscores, Est100%, window tokens, per-model lifetime breakdown and averages |
cwd: /home/user/projects/my-app
git: projects/my-app
[wt] main (+15,-3)⎇ feature-branch
Tokens -> Input: 8 Output: 308 Cached: 105.8k Work Tokens: 316
Context -> UsedT: 966.2k TkLeft: 48.3% CtxMax: 60.4% ContextLeft: 80.0%
Session -> Sessn: 27h4m APIuse: 1h14m SnCost: $2.50
-
5h all [==--------] 14% reset: 2026-01-08 22:00
7d all [----------] 3% reset: 2026-01-09 20:00
7d Sonnet [=====-----] 52% reset: 2026-01-09 20:00
Opus 4.5 | High | default | LifetimeTotal: 15.2M $27.38 | Device: my-desktop
-
Session ID: 1d732ecd-141b-4e10-b222-820b8cc2c164 Profile: .claude
Caption: Implement session caption in statusline
Model names are colored: Haiku (silver), Sonnet (salmon/pink), Opus (gold).
The model line reads <Model> | <Effort> | <style> | LifetimeTotal: ... | Device: .... The effort
level (Low/Medium/High/XHigh/Max) is the live session value from the statusline stdin
effort.level, so it follows /effort changes immediately. The segment is omitted when the
model does not support reasoning effort. Ultracode is reported by Claude Code as xhigh and
therefore shows as XHigh.
With high utilization (colored in terminal):
cwd: /home/user/projects/my-app
git: projects/my-app
[wt] main (+0,-0)⎇ main
Tokens -> Input: 10 Output: 3 Cached: 99.7k Work Tokens: 13
Context -> UsedT: 99.7k TkLeft: 49.9% CtxMax: 62.3% ContextLeft: 80.0%
Session -> Sessn: 5m APIuse: 2m SnCost: $0.12
-
5h all [=========-] 85% reset: 2026-01-08 22:00
7d all [===-------] 35% reset: 2026-01-09 20:00
Sonnet 4 | Medium | default | LifetimeTotal: 200.5k $0.12 | Device: my-desktop
The git: line shows the resolved target repo as <parent>/<repo> (the last two path
segments), and all git info below it (worktree, changes, branch) is read from that repo,
not necessarily the cwd. The target is resolved in this order:
-
Work repo - the repo the MAIN agent last worked in, captured live from its
Edit/Write and Bash
cd/git -Ccalls by a PostToolUse hook. The line therefore follows the agent into whatever repo it touches, even from a non-git hub directory. Tracking is per-session (parallel sessions never collide) and subagents are excluded, so only the main agent's own work moves the line. A SessionEnd hook cleans up the per-session state file. - cwd discovery - the repo found by walking up from the current working directory.
- credo session-pin - the repo pinned for the credo project layer (a soft dependency; used as a fallback when the cwd is a hub with no git repo).
Sources 1 and 3 are soft dependencies - without them, only cwd-based discovery is used.
| Utilization | Color | Meaning |
|---|---|---|
| < 30% | Gray | Low usage |
| 30-49% | Green | Normal |
| 50-74% | Yellow | Moderate |
| 75-89% | Orange | High |
| >= 90% | Red | Critical |
| Label | Description | When Shown |
|---|---|---|
| 5h all | 5-hour rolling window (all models) | Always |
| 7d all | 7-day rolling window (all models) | Always (if available) |
| 7d Sonnet | 7-day Sonnet-specific limit | Only if utilization > 0 |
| Extra | Extra usage credits | Only if enabled AND used > $0 |
| 7d Opus | 7-day Opus-specific limit | Future-ready: appears once Anthropic includes Opus utilization in API response |
7d <Model>
|
Further limits from the API's limits[] list (e.g. weekly_scoped per model) |
If present in the API response (CLAUDE_MB_LIMIT_SCOPED) |
-
jq- JSON processor (install:sudo apt install jq) -
curl- HTTP client -
date- GNU date (Linux/WSL) or BSD date (macOS) - Valid Claude Code OAuth session (login via
claudeCLI)
The plugin auto-detects the provider via ANTHROPIC_BASE_URL:
-
Native Anthropic API (empty or
api.anthropic.com): full feature set, OAuth usage endpoint, lifetime token/cost accounting. -
z.ai / GLM Coding Plan (
https://api.z.ai/api/anthropic): shows the GLM quota (5h / weekly tokens + monthly MCP) in the same bar/color style, plus context, git, session info and agent context injection. Anthropic-only parts (OAuth usage, lifetime accounting) are skipped. - Other custom base URLs: rendered without provider limits (no quota endpoint known); everything else still works.
When a profile's projects/ directory is shared with a non-Anthropic profile (e.g. via symlink), only native claude-* models are counted in the token accounting - foreign models like GLM are never counted as Anthropic usage.
claude plugin marketplace add Marcel-Bich/marcel-bich-claude-marketplace
claude plugin install limit@marcel-bich-claude-marketplaceAfter installation, add the statusline configuration to ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "~/.claude/plugins/marketplaces/marcel-bich-claude-marketplace/plugins/limit/scripts/usage-statusline.sh",
"refreshInterval": 20
}
}refreshInterval (seconds) makes Claude Code re-render the statusline on a timer, not only
on assistant messages. It MUST be larger than how long the statusline takes to render:
Claude Code cancels an in-flight render when the next tick fires, so a value below the
render time makes the statusline never appear. The default is 20 because the
ccstatusline-combined setup shells out to npx and can take several seconds; a plain, fast
statusline can go lower. Without it the statusline freezes while the main session is idle -
for example during a long-running subagent - so the remaining budget you see can be minutes
stale. With it the usage stays live even while a subagent works. It does not increase API
calls: the statusline is token-free and reads a cache, and the token-owning refresh keeps
its own throttle (a floor plus a jittered 90-150s cadence, guarded by a lock).
If you configured the statusline before refreshInterval existed AND the limit plugin is
enabled, a SessionStart hook detects the missing field and adds it deterministically (with a
backup; a restart activates it). Opt out or set the value with
CLAUDE_MB_LIMIT_AUTO_REFRESH_INTERVAL (0 disables, a positive integer sets the seconds).
Plugin hooks do not run when the plugin is disabled, so a statusline-only setup (plugin
installed but disabled) is NOT auto-healed - add refreshInterval manually as shown above.
What updates live, and what counts subagents. On each render the script recomputes its
self-sourced values: the 5h / 7d / weekly bars (account-wide API usage, so subagent
consumption IS included), session timing, git, and the JSONL-based lifetime token/cost
totals (main + subagents). These stay current on every tick, even while a subagent runs.
The values Claude Code passes on stdin behave differently: the session cost
(total_cost_usd) is session-wide and so does include subagent API calls, whereas the
context-window tokens and percentage reflect only the main conversation's most recent API
response - subagents have their own separate context windows and are not summed into it.
Measured behavior: the session cost updates live on each render while a subagent runs - it
does not wait for the subagent to return (the main context stays frozen meanwhile, since it
reflects only the main conversation). So the session cost, the account-wide 5h / 7d bars, and
the lifetime totals all track subagent consumption live; only the context-window
tokens/percentage stay main-only.
Note: Restart Claude Code after changing settings.json.
If you want additional customization beyond what limit provides, you can combine it with ccstatusline.
Important: Since limit now includes CWD, Git, Context, Tokens, and Session info by default, you should disable duplicate features when using both:
{
"env": {
"CLAUDE_MB_LIMIT_CWD": "false",
"CLAUDE_MB_LIMIT_GIT": "false",
"CLAUDE_MB_LIMIT_CTX": "false",
"CLAUDE_MB_LIMIT_TOKENS": "false",
"CLAUDE_MB_LIMIT_SESSION": "false"
}
}You have two setup options:
Run the setup script that creates the wrapper and updates your settings:
Online (via curl):
curl -sL https://raw.githubusercontent.com/Marcel-Bich/marcel-bich-claude-marketplace/main/plugins/limit/scripts/setup-combined-statusline.sh | bashLocal (if plugin already installed):
~/.claude/plugins/marketplaces/marcel-bich-claude-marketplace/plugins/limit/scripts/setup-combined-statusline.shThen restart Claude Code.
1. Create ~/.claude/statusline-mb-combined.sh:
#!/bin/bash
# Combined statusline: ccstatusline + limit plugin
# Get ccstatusline output (all lines)
CCSTATUS=$(npx -y ccstatusline@latest 2>/dev/null)
# Get limit plugin output
LIMIT=$(~/.claude/plugins/marketplaces/marcel-bich-claude-marketplace/plugins/limit/scripts/usage-statusline.sh 2>/dev/null)
# Combine with newline
if [[ -n "$CCSTATUS" ]] && [[ -n "$LIMIT" ]]; then
echo -e "$CCSTATUS"
echo -e "$LIMIT"
elif [[ -n "$LIMIT" ]]; then
echo -e "$LIMIT"
elif [[ -n "$CCSTATUS" ]]; then
echo -e "$CCSTATUS"
fi2. Make it executable:
chmod +x ~/.claude/statusline-mb-combined.sh3. Update ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline-mb-combined.sh"
}
}Configure via environment variables in ~/.claude/settings.json:
{
"env": {
"CLAUDE_MB_LIMIT_SHOW_ERRORS": "false",
"CLAUDE_MB_LIMIT_DEBUG": "false"
},
"statusLine": {
"type": "command",
"command": "~/.claude/plugins/marketplaces/marcel-bich-claude-marketplace/plugins/limit/scripts/usage-statusline.sh"
}
}| Variable | Default | Description |
|---|---|---|
CLAUDE_MB_LIMIT_5H |
true |
Show 5-hour limit |
CLAUDE_MB_LIMIT_7D |
true |
Show 7-day limit |
CLAUDE_MB_LIMIT_SONNET |
true |
Show Sonnet limit (if available) |
CLAUDE_MB_LIMIT_EXTRA |
true |
Show extra credits (if used) |
CLAUDE_MB_LIMIT_MODEL |
true |
Show model name (colored), Style, LifetimeTotal, and Device |
CLAUDE_MB_LIMIT_CWD |
true |
Show current working directory |
CLAUDE_MB_LIMIT_GIT |
true |
Show git info (worktree, changes, branch) |
CLAUDE_MB_LIMIT_CTX |
true |
Show context metrics (UsedT, TkLeft, CtxMax, ContextLeft) |
CLAUDE_MB_LIMIT_TOKENS |
true |
Show token metrics (Input, Output, Cached, Work Tokens) |
CLAUDE_MB_LIMIT_SESSION |
true |
Show session timing (Sessn, APIuse, SnCost) |
CLAUDE_MB_LIMIT_SESSION_ID |
true |
Show session ID |
CLAUDE_MB_LIMIT_CAPTION |
true |
Show session caption (from /rename, summary, or first prompt) |
CLAUDE_MB_LIMIT_PROFILE |
true |
Show active profile name (e.g., .claude-work) |
CLAUDE_MB_LIMIT_SEPARATORS |
true |
Show separator lines (black dashes) |
CLAUDE_MB_LIMIT_COLORS |
true |
Enable colored output |
CLAUDE_MB_LIMIT_PROGRESS |
true |
Show progress bars |
CLAUDE_MB_LIMIT_RESET |
true |
Show reset times |
CLAUDE_MB_LIMIT_SHOW_ERRORS |
false |
Show "limit: error" on failures |
CLAUDE_MB_LIMIT_DEBUG |
false |
Log to /tmp/claude-mb-limit-debug_${PROFILE_NAME}.log (true, 1, yes or on; same flag for every script) |
CLAUDE_MB_LIMIT_AUTO_REFRESH_INTERVAL |
20 |
Statusline refreshInterval (seconds) the SessionStart hook adds when the field is missing; 0 disables the auto-heal, a positive integer sets the seconds |
CLAUDE_MB_LIMIT_REFRESH_CADENCE |
150 |
Base seconds between usage-API refreshes; plus 0-60s jitter -> 150-210s (avg ~180). This is the knob for usage-endpoint rate limits |
CLAUDE_MB_LIMIT_CACHE_AGE |
120 |
Seconds between global scans of the JSONL transcripts for the token ledger. No API calls - unrelated to rate limits; the scan runs detached and never blocks the render |
CLAUDE_MB_LIMIT_SESSION_SCAN |
10 |
Minimum seconds between scans of the current session transcript |
CLAUDE_MB_LIMIT_SESSION_SCAN_BYTES |
2097152 |
About this many bytes (2 MiB) of the current session transcript are read per render (a single longer line is read whole); a larger backlog is read over several renders and by the detached scan |
CLAUDE_MB_LIMIT_BG_SCAN_BUDGET |
25 |
Time budget (seconds) of one detached global scan; a first backfill continues on the next scans |
CLAUDE_MB_LIMIT_SCAN_BYTES |
0 |
Byte budget of one global scan (0 = only the time budget applies) |
CLAUDE_MB_LIMIT_STALE_AFTER |
600 |
Mark API numbers as [stale ...] when the usage cache is older than this many seconds |
CLAUDE_MB_LIMIT_SCOPED |
true |
Show further limits from the API's limits[] list (e.g. weekly_scoped) |
CLAUDE_MB_LIMIT_EST_MIN_PCT |
20 |
Minimum API utilization for an Est100% sample |
CLAUDE_MB_LIMIT_EST_MAX_AGE |
120 |
Est100% samples only use API numbers younger than this many seconds |
CLAUDE_MB_LIMIT_DEFAULT_COLOR |
\033[90m |
Default color (ANSI escape sequence) |
CLAUDE_MB_LIMIT_LOCAL |
true |
Enable highscore tracking (device-local usage) |
CLAUDE_MB_LIMIT_DEVICE_LABEL |
hostname | Custom device label for highscore display |
CLAUDE_CONFIG_DIR |
~/.claude |
Base directory for Claude config (multi-account support) |
CLAUDE_MB_LIMIT_OPUS |
true |
Show Opus limit (future-ready: appears once Anthropic includes Opus utilization in API response) |
CLAUDE_MB_LIMIT_AVERAGE |
true |
Show [AvgPeak:...] / [Avg:...] averages |
CLAUDE_MB_LIMIT_HISTORY_ENABLED |
true |
Enable history tracking for average display |
CLAUDE_MB_LIMIT_HISTORY_INTERVAL |
600 |
Minimum seconds between history writes (10 min) |
CLAUDE_MB_LIMIT_HISTORY_DAYS |
28 |
History retention in days |
CLAUDE_MB_LIMIT_PROGRESSBAR_MODE |
auto-compact |
Progress bar mode. auto-compact: 100% = the auto-compact trigger point (a tacho); full: 100% = the full context window |
CLAUDE_CODE_AUTO_COMPACT_WINDOW |
(unset) | Exact auto-compact trigger point in tokens. Highest precedence; capped at the window size. No tilde |
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE |
(unset) | Exact auto-compact trigger as a percentage (1-100) of the full window. No tilde |
CLAUDE_MB_LIMIT_AUTOCOMPACT_FALLBACK_PCT |
83 |
Conservative fallback percentage used only when the real trigger is unknown. Shown with a leading ~ (estimated) |
CLAUDE_MB_LIMIT_CTX_CACHE |
true |
Statusline writes a per-session cache /tmp/claude-mb-context-cache_${session_id}.json (window size, limits, cost) |
CLAUDE_MB_LIMIT_INJECT |
true |
Inject hook feeds a short status line into the agent's context (UserPromptSubmit + PostToolUse) |
CLAUDE_MB_LIMIT_COMPACT_SKILL |
(unset) | The skill the agent should run when a threshold is reached, e.g. /my-skill. Empty = status only, no skill named |
CLAUDE_MB_LIMIT_INJECT_INTERVAL |
120 |
Minimum seconds between routine status injects (throttle) |
CLAUDE_MB_LIMIT_INJECT_DELTA |
1 |
Minimum change (pct points) in ctx/5h/weekly to re-inject a routine status (delta-guard) |
CLAUDE_MB_LIMIT_INJECT_THRESHOLDS |
80,92 |
Comma-separated %% of the way to auto-compact at which the skill hint fires (any count, e.g. 33,66,92) |
CLAUDE_MB_LIMIT_INJECT_MAX_AGE |
300 |
Ignore the cache (inject nothing) if older than this many seconds - avoids reporting stale numbers |
If you use multiple Claude accounts (e.g., personal and work), you can run separate profiles by setting CLAUDE_CONFIG_DIR:
# Work account
export CLAUDE_CONFIG_DIR=~/.claude-work
claude
# Personal account (default)
claudeEach profile gets its own:
- Credentials (
$CLAUDE_CONFIG_DIR/.credentials.json) - Highscore state (
$CLAUDE_CONFIG_DIR/marcel-bich-claude-marketplace/limit/) - History data
This is useful when you want separate usage tracking per account.
To show only the 5-hour percentage without colors or progress bars:
{
"env": {
"CLAUDE_MB_LIMIT_7D": "false",
"CLAUDE_MB_LIMIT_COLORS": "false",
"CLAUDE_MB_LIMIT_PROGRESS": "false",
"CLAUDE_MB_LIMIT_RESET": "false"
}
}Output: 5h all 14%
The agent (Claude) cannot read the statusline - it runs as a separate process and never sees the rendered line. This feature gives the running agent its own resource usage so it can act on it (for example run a securing or compacting skill before an auto-compact loses progress), even during long autonomous runs where no user prompts arrive.
How it works:
- The statusline writes a small per-session cache
/tmp/claude-mb-context-cache_${session_id}.jsonwith the values Claude Code hands only to the statusline: the context fill percentage and window size (context_window_sizeis canonical - it reflects model switches AND the 1M beta mid-session automatically, no lookup table to maintain), plus the 5h / weekly limits and session cost. One file per session, so parallel sessions never overwrite each other. - The inject hook (
scripts/inject-status.sh, onUserPromptSubmit+PostToolUse) reads that cache and injects a short status line throughadditionalContext- visible to the agent, without flooding the user chat. It stays silent if the cache is missing or stale (CLAUDE_MB_LIMIT_INJECT_MAX_AGE), so it never reports outdated numbers. - It is throttled (
CLAUDE_MB_LIMIT_INJECT_INTERVAL) and delta-guarded (CLAUDE_MB_LIMIT_INJECT_DELTA): a routine status re-injects only when at least that many percentage points changed in ctx/5h/weekly, so quiet phases inject nothing. Each threshold inCLAUDE_MB_LIMIT_INJECT_THRESHOLDSfires once and adds an action hint to run the skill fromCLAUDE_MB_LIMIT_COMPACT_SKILL. Thresholds reset after a compact drops the fill.
You decide what runs at the thresholds. This plugin ships no skill of its own: set
CLAUDE_MB_LIMIT_COMPACT_SKILL to whatever skill should auto-run (any skill, e.g.
/my-skill). If it is unset, the agent only gets a "secure progress" hint without a
skill name. Set the trigger points with CLAUDE_MB_LIMIT_INJECT_THRESHOLDS
(comma-separated, any number of values, e.g. 80,92 or 33,66,92).
Since limit v2.32.0 the context percentage is a tacho: the fill relative to the
auto-compact trigger point, not the full window. So the threshold values are percent
of the way to auto-compact. A leading ~ on the percentage means the trigger point is
an estimate (the conservative fallback) rather than a value read from a setting or env
override. The trigger point is resolved in this precedence: CLAUDE_CODE_AUTO_COMPACT_WINDOW
(exact tokens) -> the autoCompactWindow setting -> CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
(exact percent of the full window) -> the CLAUDE_MB_LIMIT_AUTOCOMPACT_FALLBACK_PCT
fallback (default 83, shown with ~).
Example injected line (with CLAUDE_MB_LIMIT_COMPACT_SKILL=/my-skill):
[limit] Context ~85% (170k/200k) | 5h 64% | Weekly 31% | $4.20
ACTION: Context at >= 80% of the way to auto-compact - run /my-skill now to secure progress before it triggers.
Highscore tracking is enabled by default. Disable with CLAUDE_MB_LIMIT_LOCAL=false if you don't want device-local tracking.
Instead of complex calibration algorithms, we track the highest token usage ever measured on this device:
- Highscores can only increase, never decrease - Your record only gets broken by higher usage
- Converges to real limit over time - The more you work, the closer your highscore gets to the real API limit
- Separate highscores per plan - Switching between max20, max5, and pro uses the correct highscore
- 5h and 7d are independent records - Each time window has its own highscore
When you share a Claude account across multiple devices, the API shows your total usage across all devices. But you cannot know how much of that usage came from YOUR device.
Highscore tracking solves this elegantly:
- We measure tokens consumed on THIS device
- We compare against your personal best (highscore)
- Over time, your highscore converges toward the real limit
- No complex multi-device calibration needed
5h all [==--------] 14% reset: 2026-01-08 22:00 [AvgPeak: 41.3%] [Avg: 6.2%/h]
5h all [=====-----] ~50% reset: 2026-01-08 22:00 [Highest:7.5M/15.2M] [Est100%:9.8M] (my-desktop)
7d all [----------] 3% reset: 2026-01-09 20:00 [AvgPeak: 57.8%] [Avg: 7.9%/d]
7d all [=---------] ~8% reset: 2026-01-09 20:00 [Highest:4.2M/52.3M] [Est100%:~61.0M] (my-desktop)
- Line 1: API/User-wide usage (all devices)
-
Line 2: Local/Device usage showing
~prefix (estimated from highscore), your[Highest:current/record], the per-device[Est100%:X]and device name
All token numbers here are work tokens (input + output + cache writes) from the deduplicated ledger, see Token Ledger.
[Est100%:X] is a continuous estimate of where 100 % API utilization lies, in work tokens:
- It is the median of
window_tokens / (API% / 100)over samples taken at >= 20 % API utilization (CLAUDE_MB_LIMIT_EST_MIN_PCT) in the current window. - Without samples in the current window it falls back to the value of the previous window, shown with a leading
~. - It replaces the former LimitAt easter egg, which compared counts from different schemes and almost never refreshed.
Per-device value. Est100% is shown on the device line, not on the account-wide line. The tokens come from this device's transcripts only (other devices keep their own config directory and cannot be read from here), while the API percentage is account-wide. With parallel use of the same account on other devices the estimate is therefore a lower bound.
When no samples are taken:
- While the transcript backfill is incomplete - window tokens are still missing, so the ratio would be too low.
/limit:highscoresays so while the backfill runs. - While the API numbers are older than
CLAUDE_MB_LIMIT_EST_MAX_AGE(default 120 s) - an old percentage would make the ratio too high.
Highscore data is stored in ~/.claude/marcel-bich-claude-marketplace/limit/limit-highscore-state_${PROFILE_NAME}.json:
{
"schema_version": 2,
"plan": "max20",
"highscores": {
"max20": {"5h": 5200000, "7d": 52300000},
"max5": {"5h": 2100000, "7d": 18700000},
"pro": {"5h": 480000, "7d": 3200000},
"unknown": {"5h": 1000000, "7d": 10000000}
},
"windows": {"5h": {...}, "7d": {...}},
"est": {"5h": {"id": ..., "samples": [...], "prev": ...}, "7d": {...}}
}Fields explained:
-
schema_version- State schema (2 since v2.36.0) -
plan- Current detected plan (from credentials.json) -
highscores- Highest recorded work-token usage per plan, per window (only rises) -
windows- Last knownresets_atand API value per window, used to detect window resets and derive the window start -
est- Est100% samples of the current window (tokens / (API% / 100), the last 50 are kept) and the median of the previous window as fallback
Window tokens are no longer accumulated in this file; they are summed from the Token Ledger for the time since the window start. Upgrading to schema 2 discards the old highscores and LimitAt values once (they were measured in an inflated unit); a .bak copy of the old state is kept.
The plugin automatically detects your plan from ~/.claude/.credentials.json:
| Plan | Detection (from rateLimitTier) |
|---|---|
| max20 | Contains "20x" |
| max5 | Contains "5x" |
| pro | Contains "pro" |
| unknown | Fallback if nothing matches |
Example credential entry:
{
"claudeAiOauth": {
"subscriptionType": "max",
"rateLimitTier": "default_claude_max_20x"
}
}Conservative starting values (will be exceeded quickly with normal usage):
| Plan | 5h Default | 7d Default |
|---|---|---|
| max20 | 1.0M | 10.0M |
| max5 | 500K | 5.0M |
| pro | 200K | 2.0M |
| unknown | 1.0M | 10.0M |
| Variable | Default | Description |
|---|---|---|
CLAUDE_MB_LIMIT_LOCAL |
true |
Enable highscore tracking |
CLAUDE_MB_LIMIT_DEVICE_LABEL |
hostname | Custom label shown in statusline and in /limit:highscore
|
CLAUDE_MB_LIMIT_EST_MIN_PCT |
20 |
Minimum API utilization for an Est100% sample |
CLAUDE_MB_LIMIT_EST_MAX_AGE |
120 |
Est100% samples only use API numbers younger than this many seconds |
Run /limit:highscore to see your highscores, Est100%, window tokens, lifetime breakdown and averages (abridged):
## Highscore Status
**Plan:** max20 | **Device:** my-desktop
### Combined Total (Main + Subagents)
**15.2M Tokens** | $27.38 | Cache reads: 1.2G
### Current Window (Main + Subagents)
- **5h:** 2.3M Tokens (cache reads 180.4M)
- **7d:** 8.7M Tokens (cache reads 702.1M)
### Current Usage (from API)
- **5h:** 14% (resets in 2h 10m - 2026-01-08 22:00)
- **7d:** 3% (resets in 1d 20h - 2026-01-09 20:00)
### Local Highscores and Est100%
**Highscores (max20)**
- 5h: 5.2M
- 7d: 52.3M
**Est100% (my-desktop)** (median of this device's tokens / (account-wide API% / 100), samples at >= 20 %)
- 5h: 9.8M
- 7d: 61.0M
### Lifetime Breakdown (per model)
**Main Agent:**
- <model id>: 12.1M (cache reads 950.3M), $21.40
**Subagents:**
- <model id>: 3.1M (cache reads 249.7M), $5.98
### History & Averages
**Averages (account-wide API utilization):**
- 5h: average peak per window (7d) 41.3% | usage per hour (24h) 6.2%
- 7d: average peak per window (28d) 57.8% | usage per day (7d) 7.9%
While the transcript backfill is still running, the "Current Window" block notes that the window sums are incomplete and that no Est100% samples are taken yet. A model without a known price shows cost n/a (unknown price) instead of a guessed cost.
Q: What happens when the 5h/7d window resets?
A: Window tokens are summed from the new window start, so they start again near 0. Your highscore remains unchanged. A reset is detected when resets_at moves, when the utilization drops sharply (more than 20 points or below half) with an unchanged resets_at, or when the stored reset time has passed.
Q: What happens when I downgrade my plan (e.g., max20 to pro)? A: The plugin automatically detects the new plan and uses the corresponding highscore. Each plan has its own separate records.
Q: Can I reset my highscores?
A: Delete ~/.claude/marcel-bich-claude-marketplace/limit/limit-highscore-state_${PROFILE_NAME}.json to start fresh.
Q: Where did LimitAt go? A: LimitAt was removed in v2.36.0. It compared counts from different schemes and almost never refreshed. The continuous Est100% Estimate replaces it.
Q: Why does Est100% not appear?
A: It needs samples at >= 20 % API utilization in the current window (or a value from the previous window). No samples are taken while the transcript backfill is incomplete or while the API numbers are older than CLAUDE_MB_LIMIT_EST_MAX_AGE.
The plugin shows averages from the local history on the account-wide limit lines (enabled by default).
5h all [==--------] 14% reset: 2026-01-08 22:00 [AvgPeak: 41.3%] [Avg: 6.2%/h]
7d all [----------] 3% reset: 2026-01-09 20:00 [AvgPeak: 57.8%] [Avg: 7.9%/d]
-
[AvgPeak:X%]- Average peak utilization per completed window (over the last 7 days for 5h, over the last 28 days for 7d). The Opus and Sonnet lines showAvgPeakonly. -
[Avg:Y%/h](5h, over 24 hours) /[Avg:Y%/d](7d, over 7 days) - Average consumption per hour / day, idle time included.
Values are rounded half-up to one decimal. History entries record resets_at, so completed windows can be told apart. The former [Average:L%/A%] display was removed in v2.36.0 (both halves read the same field).
| Variable | Default | Description |
|---|---|---|
CLAUDE_MB_LIMIT_AVERAGE |
true |
Show [AvgPeak:...] / [Avg:...] averages |
History data is stored in ~/.claude/marcel-bich-claude-marketplace/limit/limit-history_${PROFILE_NAME}.jsonl.
The model line shows LifetimeTotal: X.XM $XX.XX - your accumulated work tokens (input + output + cache writes) and cost across all sessions on this device, main agent and subagents. It comes from the same Token Ledger as the session line, window tokens, highscores and Est100%.
- Cost is priced per concrete model id, cache writes by TTL. Models without a known price are not guessed, their cost is shown as
$X+n/a. - Cache reads are tracked and shown separately (
/limit:highscore), never added 1:1. - Lifetime totals are kept in the ledger and survive the deletion of transcripts.
All local token numbers come from one deduplicated ledger built from the Claude Code transcripts (projects/<project>/<session>.jsonl and .../<session>/subagents/agent-*.jsonl), for main agent and subagents alike:
-
One count per API message. Claude Code writes one transcript line per content block (thinking, text, tool use) and repeats the message's usage on each. Lines are deduplicated by
message.id+requestId(last line wins), so a message split across two incremental reads is still counted once. -
One spelling per transcript. Paths are canonicalized (duplicate slashes,
/./and symlinked directories), so a transcript is never counted twice under two spellings, e.g. with a trailing slash inCLAUDE_CONFIG_DIR. - Work tokens = input + output + cache writes. Cache reads (typically about 99 % of the raw volume) are tracked separately.
-
Windows from timestamps. Messages are summed into 5-minute buckets; window tokens are the sum since the window start (
resets_at- 5h / 7d), so there is no per-render delta and no baseline that a lost write could reset. -
Only native models. Only
claude-*model ids are counted. - Safe state. All state read-modify-writes run under a lock with atomic writes, so parallel sessions cannot corrupt them; an unreadable state skips the local values for one render instead of counting from 0.
Bounded reading. Reading is linear in the bytes read (one prefilter, one streaming JSON pass, one pass for dedup and sums) and always bounded:
-
Per render only the current session transcript is read, about
CLAUDE_MB_LIMIT_SESSION_SCAN_BYTES(default 2 MiB) per render. A single line longer than that is read whole. The render-time scan runs at most everyCLAUDE_MB_LIMIT_SESSION_SCANseconds and writes nothing while the transcript did not grow. A trailing partial line is left for the next read. -
The global scan over all transcripts runs detached every
CLAUDE_MB_LIMIT_CACHE_AGEseconds, so it never blocks the statusline. It stops at its time budget (CLAUDE_MB_LIMIT_BG_SCAN_BUDGET, default 25 s, checked with millisecond resolution) and at an optional byte budget (CLAUDE_MB_LIMIT_SCAN_BYTES, default0= time budget only). Small transcripts are read in batches. - Resume. Both scans resume from stored byte offsets; unfinished files are marked pending and continued by the next scan.
Backfill after an upgrade. The ledger is backfilled from all existing transcripts in the background over a few detached scans. Until the backfill is complete the window sums are too low, so no Est100% samples are taken (/limit:highscore says so while it runs).
Pruning. Entries of deleted transcripts are pruned; the lifetime totals keep their tokens. A transcript read or marked pending in the same run is never pruned.
Known limit. Deduplication works per transcript file. The rare API message that appears in two files (e.g. a subagent sidechain and its parent transcript) is counted in both - about 1 % extra in observed transcripts.
State is stored in ~/.claude/marcel-bich-claude-marketplace/limit/:
-
limit-ledger_${PROFILE_NAME}.json- Token ledger (per-file offsets, 5-minute buckets, lifetime totals per model for main agent and subagents) -
limit-highscore-state_${PROFILE_NAME}.json- Highscores, window tracking and Est100% samples
The former separate main/subagent scanner states and the stdin delta accounting state are no longer written.
Note: If the ledger file is deleted, lifetime totals reset. Only currently existing transcripts can be rescanned - tokens from deleted logs are lost.
- Reads your OAuth token from
~/.claude/.credentials.json - Checks if cached data exists and is fresh (default: 2 minutes)
- If cache expired, fetches fresh usage data from Anthropic's OAuth API
- Formats each limit with colored progress bar, percentage, and reset time
- Updates automatically with each Claude response (statusline refresh)
To avoid excessive API calls, the usage endpoint is only re-fetched on a jittered cadence (default 150-210s, avg ~180), with a 60s hard floor and error backoff. The cache is stored in /tmp/claude-mb-limit-cache_${PROFILE_NAME}.json. If you hit usage-endpoint rate limits, raise the cadence via CLAUDE_MB_LIMIT_REFRESH_CADENCE (base seconds, default 150). Note: CLAUDE_MB_LIMIT_CACHE_AGE is a different setting - it only bounds the local JSONL token-accounting scan and makes no API calls, so it has no effect on rate limits.
A 429 response stores one retry_at. The statusline shows exactly that countdown and refresh-usage.sh does not call the API before it. When the usage cache is older than CLAUDE_MB_LIMIT_STALE_AFTER (default 600 s) the limit lines are marked [stale Xm]; after a limit's resets_at has passed it shows 0.0% ... (reset) instead of the previous window's value.
Warning: Do not lower CLAUDE_MB_LIMIT_REFRESH_CADENCE below the default. Anthropic may rate-limit or block your account if you make too many usage-endpoint requests. The default is a safe value - raise it, do not lower it.
- Verify you're logged in:
claude /login - Check if credentials exist:
ls ~/.claude/.credentials.json - Test manually: Run the script directly in your terminal
- Enable error display:
CLAUDE_MB_LIMIT_SHOW_ERRORS=true ./path/to/script.sh
To see the raw API response:
CLAUDE_MB_LIMIT_DEBUG=true ~/.claude/plugins/marketplaces/marcel-bich-claude-marketplace/plugins/limit/scripts/usage-statusline.shTo visually test the color transitions without real API data, run the debug script:
~/.claude/plugins/marketplaces/marcel-bich-claude-marketplace/plugins/limit/scripts/debug-progress.shThis simulates progress from 0% to 100% (5% per second) so you can verify all color thresholds are displayed correctly in your terminal.
Some accounts may see this error. Workaround:
- Run
claude /loginto re-authenticate - If issue persists, see: https://github.com/anthropics/claude-code/issues/15243
- Ensure your terminal supports ANSI color codes
- Some terminals may need specific configuration for 256-color support (orange)
The script supports both GNU date (Linux) and BSD date (macOS). If you encounter issues on macOS, ensure you have a recent version of the system tools.
This plugin reads your OAuth token from the local credentials file to authenticate API requests. The token is:
- Only used locally to fetch your own usage data
- Never transmitted anywhere except to Anthropic's official API
- Never displayed in the statusline output
Important: Do not let Claude Code read or execute this script during a session, as the script output could end up in the conversation context. The statusline runs in a separate process that does not feed back into Claude's context.
-
Unofficial API - The
/api/oauth/usageendpoint is not officially documented and may change -
Token Expiry - If your OAuth token expires, you'll need to re-login with
claude /login - Rate Limits - The script is called on each statusline refresh; Anthropic may rate-limit excessive calls
- Per-file deduplication - The token ledger deduplicates API messages per transcript file. A message present in two transcripts (e.g. a subagent sidechain and its parent) is counted in both, about 1 % extra
- Est100% is per device - Only this device's transcripts are readable while the API percentage is account-wide; with parallel use on other devices Est100% is a lower bound
- Run
/pluginin Claude Code - Go to Marketplaces tab and select "Update marketplace"
- Go to Installed tab and update the limit plugin
- Restart Claude Code
This software is provided "as is", without warranty of any kind. Use at your own risk.
- The author is not responsible for any issues arising from use of this plugin
- The API endpoint used is not officially documented and may change without notice
- You are solely responsible for ensuring this plugin works with your setup
- No support or maintenance is guaranteed
MIT - See LICENSE for full terms.
See also: Signal | Dogma | All Plugins
Keywords / Tags
Claude Code, Claude Code Plugin, Claude Code Extension, Claude Code Usage, Claude Code Limit, Claude Code Rate Limit, Claude Code API Usage, Claude Code Statusline, Claude Code Status Bar, Claude Code Progress Bar, Claude Code Utilization, Claude Code Quota, Claude Code Credits, Claude Code Tokens, Claude Code Cost, Claude Code Billing, Claude Code Subscription, Claude Code Max, Claude Code Pro, Claude Code 5h Limit, Claude Code 7d Limit, Claude Code Opus Limit, Claude Code Sonnet Limit, Claude Code Reset Time, Anthropic CLI, Anthropic Plugin, Anthropic Extension, Anthropic Claude, Anthropic AI, Anthropic API, Anthropic OAuth, Anthropic Usage, Anthropic Billing, Anthropic Limits, Anthropic Rate Limit, AI Agent Usage, AI Agent Limits, AI Agent Quota, AI Agent Cost, AI Code Assistant, AI Coding, AI Programming, AI Development, API Usage Tracking, API Rate Limit, API Quota, API Credits, Usage Display, Usage Monitor, Usage Tracker, Live Usage, Real-time Usage, Statusline, Status Bar, Progress Bar, Terminal Statusline, CLI Statusline, Colored Progress Bar, ANSI Colors, WSL, WSL2, Windows Subsystem Linux, Windows 10, Windows 11, Linux, macOS, Ubuntu, Debian, Cross Platform, ccstatusline, OAuth Token, Credentials, API Key, Cache, Rate Limiting, jq, curl, bash, Shell Script, Marcel Bich, marcel-bich-claude-marketplace, limit plugin, usage plugin, rate limit plugin