Claude Pro's 5-hour window visibility, reduced to one worst-case badge on your toolbar

If you belong to more than one Anthropic org, the org you have open is rarely the one about to throttle. ClaudeMeter pins the toolbar badge to whichever membership is closest to the five-hour ceiling, polls the same JSON the Settings page itself fetches, and refreshes on a 60-second clock you do not have to think about.

M
Matthew Diakonov
9 min read
4.9from Source-verifiable in the public ClaudeMeter repo
worstPct in extension/background.js:65-73
60-second poll cadence in both extension and macOS app
Mismatched warning thresholds documented exactly

The problem with one-org visibility

Most playbooks for surfacing your 5-hour window assume you have a single Anthropic org. You do not. Almost everyone on a Pro plan also ends up in at least one Team workspace they were invited to, and Anthropic enforces the rolling window per-org, not per-account. So the relevant question is not “what is my five-hour utilization,” it is “what is the highest five-hour utilization on any membership my next prompt could land in.”

A badge that shows the active org is wrong about half the time. A badge that cycles between orgs is wrong at any given glance. The only reliable visibility surface for a multi-org account is one that reduces every membership to a single worst-case number and pins it there. That is the entire premise of the toolbar badge below.

0sPoll interval
0Number on the badge
0%Browser orange threshold
0%Red, on every surface

The anchor fact: 0 lines that decide what you see

The whole multi-org reduction lives in nine lines of JavaScript in the public extension repo. Read the file, run it yourself, or copy the logic into your own visibility tool. The numbers below are verbatim from extension/background.js on the main branch.

extension/background.js

Two functions, one reduce, one badge call. Every snap in snaps is one organization the user belongs to. pctFromWindow normalizes the inconsistent 0-to-1 vs 0-to-100 scale (the same payload can have one bucket at 0.94 and another at 94.0). Then worstPct picks the maximum and that single number is what the toolbar pixel renders.

How the badge gets there, end to end

Every 60 seconds, the service worker wakes up, asks claude.ai which orgs you belong to, fetches the usage JSON for each one, reduces to the worst case, and writes the result to the toolbar. Nothing is cached more than 60 seconds, nothing is estimated locally.

Multi-org → one toolbar badge

Pro org
Team org
Other orgs
worstPct()
Toolbar badge
Tooltip
Bridge port

The poll loop, with the actual function names

The sequence below is what happens during one tick of the chrome.alarms timer, with the exact endpoint paths and the exact field that lands on the badge. Replace any of these with your own tool and the visibility surface still works as long as you preserve the 60-second cadence and the worst-case reduction.

One refresh tick, browser side

ChromeService workerclaude.aiToolbar badgealarms.create('refresh', 1 min)GET /api/accountmemberships[]GET /api/organizations/{org}/usage (per org){ five_hour, seven_day, ... }worstPct(snaps, 'five_hour')setBadgeText('94'), setBadgeBackgroundColor(#b26a00)94 — orange — at-a-glance signal

The browser badge and the Mac title use different orange thresholds

This is the part nobody documents because it is genuinely small, but if you run both surfaces side by side you will notice it. The browser badge turns orange at 80 percent. The Mac menu bar pill turns orange at 90 percent. They both turn red at 100. Same release, two thresholds. The browser nudges earlier because the toolbar pixel is small and peripheral, so getting an early warning out of it matters more.

Verbatim from the macOS source:

src/bin/menubar.rs

Threshold mismatch, in one table

FeatureMac menu barBrowser badge
Color at <80% utilizationno fill, default text colorgreen (#2c6e2f) background
Color at 80-89%no fill, default text colororange (#b26a00) background
Color at 90-99%orange (219,118,32) backgroundorange (#b26a00) background
Color at >=100%red (215,58,73) backgroundred (#b00020) background
SurfaceMac menu bar title pillBrowser toolbar badge text

Yes, the columns swapped. The 'competitor' column above is the Mac menu bar shipping in the same release as the badge in the 'ours' column. Both surfaces of ClaudeMeter, one repo, two thresholds, on purpose.

What the badge tells you at a glance

The badge is one number plus a color, nothing else. That is the whole point. Anything more granular goes in the popup, where you have time to read. At a glance you should be able to answer five questions in under a second, and they all live in two pixels of color and two digits of text.

Five questions, one badge

  • Am I close to a 5-hour throttle on any of my orgs? Color says it.
  • If I am, how close? The two-digit number says it.
  • Is the badge fresh? It refreshed less than 60 seconds ago.
  • Does this match the bar at claude.ai/settings/usage? Yes, same JSON.
  • Did I have to paste a cookie? No, it rides your existing session.

How this differs from the other visibility playbooks

Most articles about seeing the five-hour window land on one of three patterns: open the Settings page when you remember to, run a CLI that parses local JSONL files, or paste a session token into a third-party dashboard. Each one breaks for a different reason. The toolbar badge is a direct answer to all three.

Visibility surfaces, side by side

FeatureLocal-log tools and dashboardsClaudeMeter toolbar badge
SourceLocal JSONL token counts under ~/.claude/projectsServer JSON from /api/organizations/{org_uuid}/usage
Multi-org awarenessOne org at a time, or whichever tab is activeWorst case across every membership in a single badge
Refresh cadenceOn-prompt or on-script-run only60 seconds, even when claude.ai is not open
Reset clockInferred from first message timestampresets_at ISO timestamp returned by the server
SetupPaste cookie or session token, refresh on expiryLogged into claude.ai = it works, no paste
CostFree or one-time purchase, closed sourceFree, MIT-licensed, on GitHub

Setting it up so the badge starts moving

Three steps. The middle one is the entire reason the badge can show your real five-hour percent without a paste step.

1

Install the extension

Load the unpacked extension from the public ClaudeMeter repo's extension/ directory in chrome://extensions, developer mode on. There is no separate sign-in.

2

Stay logged in to claude.ai

The fetch uses credentials: 'include', so the request rides the same session cookies your browser already has for claude.ai. No paste, no token, no API key. If you log out, the badge falls back to '!' until you log in again.

3

Pin the toolbar icon

Pin the extension to the visible part of the toolbar. The badge text and color update every 60 seconds via chrome.alarms. Hover the icon for the longer 5h and 7d tooltip.

4

Optional: install the macOS menu bar app

If you want the same number in the system bar with the slightly tighter orange threshold (>=90 instead of >=80), grab the macOS app from the same repo. It polls the same endpoint with the same cadence and writes the worst-case to the menu bar title.

One thing to remember about the rolling reset

The five-hour window does not reset to zero on a fixed clock. It is a sliding boundary. Every prompt you send pushes the boundary's next age-out forward, so the percent on the badge can fall on its own (when you stop sending) or rise (when you keep sending), without ever crossing a hard reset. The popup row shows the live resets_at ISO timestamp from the server, formatted as 3h, 22m, or now depending on how soon the next message in the window will age out. That is the only reset clock that ever matches what Anthropic enforces.

Surfaces ClaudeMeter exposes, on a loop

Browser toolbar badgeToolbar tooltip 5h / 7dPopup, one row per orgmacOS menu bar title pillmacOS menu dropdownLocal bridge :63762snapshots.json on diskCLI: claude-meter --json

Want help wiring multi-org five-hour visibility into your team's setup?

Fifteen minutes on a call, we walk through the badge, the popup, the bridge, and the snapshot file with your real account.

Frequently asked questions

Where does the 5-hour percentage on the toolbar badge come from?

It comes from GET /api/organizations/{org_uuid}/usage on claude.ai, the same JSON the Settings page renders. The extension calls that endpoint with your existing logged-in cookies, parses the five_hour.utilization float, normalizes the 0-to-1 vs 0-to-100 scale, and writes it to chrome.action.setBadgeText. There is no second source of truth and no local estimation involved. If the number on the badge disagrees with the bar at claude.ai/settings/usage, you are looking at a stale poll, not a different metric.

What does worst-case across orgs mean and why is that the right number?

If your account belongs to two organizations, say a personal Pro and a Team workspace, the rate limiter on Anthropic's side trips per org. You can be at 14 percent on org A and 96 percent on org B; the next prompt to org B will 429. Cycling between two badges or showing the active tab does not help, because the org you happen to have open is not always the one closest to throttling. ClaudeMeter computes worstPct(snaps, 'five_hour') across all your memberships in a single reduce, so the badge always tells you which way you are about to fall over.

Why are the browser badge thresholds different from the Mac menu bar?

They are. In extension/background.js the badge turns orange at >=80 percent and red at >=100 percent. In src/bin/menubar.rs the title pill turns orange at >=90 percent and red at >=100 percent. Same release, two different warning thresholds. The browser nudges you a notch earlier because the toolbar is a smaller, more peripheral pixel surface and we wanted the orange to fire while you still had room to wind down a session. The Mac title sits on a larger, more attention-grabbing surface and gets the tighter band.

How often does the badge refresh?

Once per minute, fixed. POLL_MINUTES = 1 in extension/background.js sets a chrome.alarms tick that calls refresh() every 60 seconds, and the macOS app uses POLL_INTERVAL = Duration::from_secs(60) in src/bin/menubar.rs. There is no exponential backoff and no on-focus poll. If the page disagrees with the badge by more than a percent or two, wait up to 60 seconds and the badge will catch up.

Does the badge tell me which org is over?

Not on the pixel itself. The badge is one number, the worst case, with no org tag. Click the toolbar icon and the popup renders one row per account with the email next to each five-hour bar, so you can see which membership tripped the worst-case. The Mac menu bar dropdown does the same with one row per snapshot. Keeping the badge to a single number is intentional: at a glance you want one signal, not a cycle.

What if my org returns 0.94 and another returns 94.0 in the same payload?

That happens. The endpoint is internal and the scale is inconsistent across buckets and across releases. The clamp is at extension/popup.js:6-11, u <= 1 ? u * 100 : u, applied before any worst-case reduction. The same clamp lives in the Rust side as part of the formatter. If you write your own visibility tool against this endpoint and skip the clamp, an org at 0.94 will look like 0.94 percent and the other org at 94.0 will dwarf it in your badge. Always normalize first, reduce second.

Can the badge show me the rolling reset time?

Not on the badge text itself. The badge is a percent. The popup row shows resets_at as a relative label like '5-hour · 3h' or '5-hour · 22m', computed from the live ISO timestamp the server returns. Hover the toolbar icon and the title attribute shows the same number expanded. The reset is sliding, not anchored to your first prompt, so the label moves on every poll if you are still active.

How is this different from extensions that cycle through metrics?

A cycling badge alternates between five-hour, seven-day, and other windows on a four-second loop, which means at any single glance you might be reading the wrong axis. ClaudeMeter pins the badge to one bucket, five-hour, because that is the one most likely to throttle a synchronous chat. The seven-day and weekly buckets matter, but they live in the popup, not the badge. Different design choice, same source of truth.

Will the badge keep working if I clear cookies on claude.ai?

No. The fetch uses credentials: 'include' which means the request rides your existing claude.ai session cookies. If you log out, the next /api/organizations/{org_uuid}/usage call returns a 401 or 403, refresh() catches it, and the badge text becomes '!' on a gray background. Open claude.ai, log back in, click the toolbar icon's refresh button, and the badge recovers in under a second. There is no separate auth flow and no API key to re-paste.

Why not poll from a server somewhere instead of the browser?

Because the cookies live in your browser. The endpoint authorizes per-session, not per-API-key, and Anthropic does not publish a programmatic credential for this data. A server poller would either need you to paste cookies into a remote service, which is the manual step ClaudeMeter exists to remove, or it would simply not work. Running the poll inside the same browser that already holds the session is the cheapest path to server-truth visibility, which is why the extension is the default surface and the macOS app is the long-running one.