The Opus cost of a PR is one field, and the menu-bar badge is showing you a different one
On a Pro or Max subscription, the question "what did this PR cost me on Opus" has a single-number answer: the delta on seven_day_opus.utilization between the first and last commit. Not dollars. Not the shared 5-hour bar. And yes, ClaudeMeter's own badge is tied to five_hour, not Opus. So an Opus-heavy PR can quietly push you toward the weekly Opus wall while the glance-layer reading you trust stays green. This page is about the one field that actually moves, and how to watch it per PR.
The one-paragraph version
Claude Code on a subscription has two rate-limit buckets that every Opus request increments: five_hour (shared across models, resets hourly-ish) and seven_day_opus (Opus only, rolling 7 days). The second one is the honest answer to "Opus cost per PR," because Sonnet requests do not move it. Subtract its reading at your first commit from its reading at your last commit; that is your PR's true Opus cost on this plan. The most common trap is looking at ClaudeMeter's menu-bar badge and assuming it reflects Opus risk. It does not. The badge is hardcoded to five_hour in extension/background.js. Opus is only visible once you open the popup, or hit the local bridge.
The anchor fact: badge code reads five_hour, not Opus
Here is the exact block of claude-meter/extension/background.js that runs every 60 seconds and updates the menu-bar widget. Both the text and the color come from the same variable, which is derived from five_hour:
The Opus-only float is read, it is just not promoted to the badge. The popup (a separate file) lists it, but only after you click:
Practical implication: if you are shipping an Opus-heavy PR, the menu-bar glance is the wrong source of truth. The popup, or the local bridge, is where seven_day_opus lives.
What the server sees while a PR runs
Three actors: your git working copy + the extension, the claude.ai usage endpoint, and Claude Code on Opus. The Opus-only float is the one that only moves on the Opus legs of the session.
PR lifetime, following seven_day_opus and five_hour
Measuring the Opus delta for one PR
Two curls, one subtraction. The extension and the Rust binary both post every snapshot to the same local bridge at http://127.0.0.1:63762/snapshots, so you can pull the Opus-only field directly:
That is the whole measurement. No dollar conversion, no local token count, no model-pricing lookup. The field seven_day_opus.utilization is already a fraction of the Opus ceiling the rate limiter enforces. Multiply the delta by 100 to get "percent of my weekly Opus this PR ate."
A worked example, in one reading
Real numbers from an Opus-heavy refactor branch: planning on Opus, implementation on Opus, one test pass at the end. All pulled from the 60-second local bridge log.
Over the same window, the five_hour delta was 17 points and the seven_day_sonnet delta was 0, because no Sonnet ran on this branch. The shared 5-hour bar moved a lot, but the Opus weekly only moved 4 points. That is the quantity "Opus cost per PR" names, and the one that predicts your next Opus 429.
Everything that flows into one Opus PR's delta
None of these are fields in the response; they all collapse into seven_day_opus. This is why subtracting the raw float is the only honest Opus-cost accounting.
inputs that move seven_day_opus across a PR
Four ways to read the Opus-only field
The Opus number is in every ClaudeMeter surface. The menu-bar badge is the one place it is not.
Menu-bar popup
Click the ClaudeMeter icon in the macOS menu bar. The '7d Opus' row is the current seven_day_opus.utilization. Write it down at first commit and last commit of the branch. Rendered by popup.js line 63.
Local bridge
Both the extension and the Rust binary POST every snapshot to http://127.0.0.1:63762/snapshots. curl + jq gives you '.[0].usage.seven_day_opus.utilization' in one shot. Same number, scriptable.
Direct endpoint
If you are already signed into claude.ai in Chrome, GET https://claude.ai/api/organizations/{org_uuid}/usage returns the same struct. Field name is seven_day_opus, declared in claude-meter/src/models.rs line 23.
Terminal binary
claude-meter run prints every utilization row including '7-day Opus' (see claude-meter/src/format.rs lines 19-21). Pipe through awk to grab the percent if you want a one-line read.
CI hook
Post-commit hook that curls the bridge, appends seven_day_opus to a .git/opus-usage.log, and diffs the first and last entry of a branch on merge. Per-PR Opus cost, no manual snapshots.
The measurement, step by step
Opus-only cost per PR on a subscription
Snapshot seven_day_opus at first commit
Open the popup or curl the local bridge. Record only the Opus-only weekly number. Ignore five_hour for this measurement; that is a different question answered by a different field.
Work the PR on Opus
Every Opus request pushes seven_day_opus up. Sonnet requests do not. If you mix models intentionally, you will see the Opus delta grow only on the Opus legs of the session.
Snapshot seven_day_opus at last commit
Same field, second read. The 60-second poll means if you forgot a manual snapshot, the bridge still has a sample within the minute.
Subtract: opus_cost_per_pr = after - before
A single number, in the range 0.0 to 1.0. Multiply by 100 for 'percent of the weekly Opus ceiling this PR burned.' Anything else that claims to be the Opus cost of your PR is a projection, not a measurement.
Budget forward with one division
remaining_opus_prs = (1.0 - current seven_day_opus) / average_opus_cost_per_pr. Three PRs of data is enough to start; the ratio stabilizes fast for a given repo and model-mix habit.
Preconditions for an honest Opus-per-PR number
verify before trusting the delta
- You sampled seven_day_opus.utilization at the first commit of the branch. The value matters; write it into the PR description so you can diff at merge.
- You sampled seven_day_opus.utilization at the last commit, before merge. If the extension is running, the 60-second poll has already captured both snapshots; you just have to pick the right two rows from the local bridge.
- The seven_day_opus.resets_at timestamp did not roll over between the two samples. The Opus weekly is a 7-day sliding window; if your branch lived more than a week, subtract across the reset and mark the delta as incomplete.
- Your PR stayed under extra_usage overflow. If seven_day_opus is at 1.0 for part of the PR, the true Opus cost is split across the bucket and the overage credits field (claude-meter/src/models.rs line 13 to 14, used_credits).
- You noted model mix. Sonnet steps inside the same PR do not move seven_day_opus at all. If 70 percent of the session ran on Sonnet, the Opus delta will look small even though Claude Code did a lot of work.
Dollar projection vs Opus-only delta
The dollar view is correct on the API. It is a phantom number on a subscription. The Opus-only delta is the only reading that matches what the Opus rate limiter will actually do to your next request.
| Feature | Local tokens x API rate | ClaudeMeter (Opus-only delta) |
|---|---|---|
| Unit reported | Dollars at $15/$75 per million tokens | Fraction of weekly Opus ceiling (0.00 to 1.00) |
| Matches the Opus rate limiter | No, converts via public API rate | Yes, same float the rate limiter checks |
| Isolates Opus from shared 5-hour | No, buckets all models together | Yes, seven_day_opus is Opus-only |
| Includes adaptive-thinking tokens | No, not all written to local JSONL | Yes, already applied server-side |
| Includes tokenizer expansion (1.0x to 1.35x on 4.7) | No, pre-tokenizer count | Yes, post-tokenizer applied |
| Useful for 'how many more Opus PRs this week' | No, dollar number does not map to plan ceiling | Yes, 1 minus utilization is headroom |
| Correct number to quote in a standup | Only if you are on the API | If you are on Pro, Max, Team, or Enterprise |
The most common misread
A team on Max 20x sees their menu-bar badge at 42 and assumes they have tons of headroom for another Opus PR. They start the PR, an hour in Claude Code returns a 429, the team argues Anthropic is throttling unfairly. What actually happened: the 42 on the badge was five_hour; the Opus weekly field (one line below in the popup, not visible in the menu bar) was already at 0.97 from two earlier Opus sessions that same week.
This is a design trade-off in the extension, not a bug. The badge is a single-character widget; it can only show one number. What the extension optimizes for is "am I about to 429 on the fastest-resetting bucket," and that is five_hour. If your Claude Code habit is Opus-heavy, the Opus weekly is the bucket that deserves the glance-layer attention, not five_hour. Reading seven_day_opus separately is how you close that gap.
The easy fix for teams that want an Opus-first badge: fork extension/background.js, change line 80 from worstPct(snaps, "five_hour") to worstPct(snaps, "seven_day_opus"), reload the unpacked extension. Everything else works the same; the popup already reads the field, the local bridge already exports it, the Rust binary already formats it.
Why "Opus cost per PR" is not the same question as "cost per PR"
A general cost-per-PR reading on a subscription returns four deltas at once: shared 5-hour, Opus weekly, Sonnet weekly, overage credits. That is the right answer when you want the complete picture of a PR's resource use. "Opus cost per PR" is narrower. It picks one of those four: the Opus-only weekly. The narrowing is meaningful because the Opus ceiling is the scarcest bucket for most subscribers in 2026, and because the most common optimization ("push small steps to Sonnet") only shows up when you track Opus-only cost separately from shared cost. A PR whose Opus delta is 1 percent while its five_hour delta is 18 percent is exactly the shape teams on Max 20x are optimizing toward. You cannot see that shape if you only watch a single combined number.
Forecast: Opus PRs remaining this week
Once you have two or three measured PR deltas for your repo, forecasting the rest of your Opus week is one division:
34 percent headroom divided by 4 percent per PR is roughly 8 more Opus PRs before the next resets_at on seven_day_opus. If the average climbs (bigger PRs, more thinking, more tool calls) the count falls accordingly. The number is directional, not a promise; the actual next PR can be 2 percent or 9 percent depending on session shape. But the method is strictly better than guessing in dollars.
The honest caveat
The /api/organizations/{org_uuid}/usage endpoint is internal to claude.ai and undocumented. The seven_day_opus field name has been stable for many months, and it is named identically in the Settings page's own JavaScript, but Anthropic can rename or split it at any release. ClaudeMeter deserializes into a strict Rust struct, so any shape change surfaces a parse error the maintainer patches quickly. If you are an API-only account, this page does not help you; ccusage times public API rates is the right tool for that case. The Opus-only delta view is specifically for Claude Code subscribers on Pro, Max, Team, or Enterprise, where the Opus rate limiter is the thing actually blocking your next request, and dollars are not.
Watch your Opus-only float live
ClaudeMeter reads seven_day_opus every 60 seconds from the same endpoint the Settings page calls. Free, open source, MIT licensed, no cookie-paste step.
Frequently asked questions
What is the actual 'Opus cost' of one PR on a Claude Code subscription?
It is the delta on seven_day_opus.utilization between your first and last commit on the branch, read from claude.ai/api/organizations/{org_uuid}/usage. Not a dollar figure, not a token count, not the shared 5-hour number. If that field was 0.62 when you started the PR and 0.66 when you merged, the PR cost you 4 percent of your weekly Opus ceiling. That is the only number the rate limiter checks before it decides whether to let your next Opus request through.
Why can the ClaudeMeter menu-bar badge stay green while my Opus weekly is about to hit 1.0?
The badge is intentionally tied to five_hour, not seven_day_opus. Look at claude-meter/extension/background.js lines 80-87: const five = worstPct(snaps, 'five_hour'); then chrome.action.setBadgeText and setBadgeBackgroundColor both branch on that five variable. There is no branch on Opus. A PR that is 90 percent Opus planning will push seven_day_opus hard while five_hour might be resetting every few hours. The glance-layer reading from the badge is the 5-hour number; if you care about Opus cost per PR, you have to open the popup (popup.js line 63) where seven_day_opus is listed, or hit the local bridge at 127.0.0.1:63762 and read the field yourself.
How is 'Opus cost per PR' different from 'cost per PR' in general?
A general cost-per-PR reading returns four deltas: five_hour (shared across all models), seven_day_opus (Opus only, weekly), seven_day_sonnet (Sonnet only, weekly), and extra_usage.used_credits (overage). Opus cost per PR collapses that to one number: the delta on seven_day_opus alone. A PR with heavy Sonnet cleanup can have a big five_hour delta and a tiny seven_day_opus delta, which is exactly the mix most cost-conscious teams aim for. Budgeting weekly Opus PRs is a different problem from budgeting shared 5-hour headroom, and it uses a different field.
Which requests actually move seven_day_opus?
Only Opus requests. Every Claude Code call on Opus 4.7 increments seven_day_opus AND five_hour on the server. Sonnet calls increment seven_day_sonnet AND five_hour, but leave seven_day_opus untouched. This is why teams that switch the small steps (formatting, unit-test generation, type fixes) to Sonnet see their Opus weekly drift up more slowly across a PR. The struct declaration is in claude-meter/src/models.rs lines 18-28 — seven_day_opus is a sibling of seven_day_sonnet, not the same field.
Does Opus 4.7's adaptive thinking count toward seven_day_opus even if I cannot see the thinking tokens?
Yes. Opus 4.7 runs adaptive thinking with display set to omitted by default. The thinking tokens are generated server-side and billed against seven_day_opus in the same way normal output tokens are. They are often not written in full to the local JSONL that ccusage reads. So for an Opus-heavy PR, the delta on seven_day_opus will be measurably larger than the delta a local-token tool projects. The utilization field already incorporates them; that is one of the reasons the server-truth read is the correct per-PR number on a subscription.
How many Opus PRs can I still fit in this week?
Divide the remaining Opus headroom by your measured Opus cost per PR. If the extension popup says 7d Opus is 64 percent, you have 36 percent left. If your last three merged PRs cost 3, 4, and 5 percent respectively (averaging 4 percent), you have roughly 9 more Opus PRs of similar scope this week before the float hits 1.0 and you flip to overage. This is a rolling 7-day window, not a calendar week; the resets_at timestamp on the same Window struct tells you exactly when the oldest usage rolls off.
I already run ccusage. Why do I still need to read seven_day_opus?
ccusage answers 'if I had paid Anthropic at the API list rate, what would this session have cost?' That is a useful number for API accounts; it is a phantom number on a subscription. seven_day_opus.utilization answers 'how close am I to the Opus wall the rate limiter actually enforces?' Subscribers need both answers to different questions. Most teams use ccusage to watch model-mix trends and seven_day_opus to watch 429 risk, specifically on the Opus bucket that Sonnet does not share.
Why not just expose seven_day_opus on the menu-bar badge too?
The design choice in background.js was single-number simplicity. The badge is a 2-to-3 character widget; it can only show one percent. five_hour was picked because it is the first thing to 429 you in a burst. That works for a Sonnet-heavy Claude Code user, it undersells risk for an Opus-heavy one. If you want an Opus-first badge, you can fork background.js to change line 80 to worstPct(snaps, 'seven_day_opus'), rebuild the extension, and load it unpacked. The popup already reads the field.
Can I script a 'Opus-cost-of-this-PR' number into my CI job?
Yes. The extension posts each snapshot to http://127.0.0.1:63762/snapshots (extension/background.js line 2). A post-commit hook that curls that URL and writes snapshots[0].usage.seven_day_opus.utilization to a file, plus a branch-close step that subtracts first and last, gives you Opus cost per PR in CI. The JSON shape is guaranteed by the Rust struct at claude-meter/src/models.rs line 23 (pub seven_day_opus: Option<Window>), so the parse is a one-liner in jq: .[0].usage.seven_day_opus.utilization.
What happens if my Opus weekly hits 1.0 mid-PR?
The next Opus Claude Code request returns a 429 specifically about the Opus limit. If extra_usage is enabled, subsequent Opus calls start spending overage credits instead of the Opus bucket, and seven_day_opus stops climbing because it is already at 1.0. extra_usage.used_credits on the overage_spend_limit endpoint starts climbing instead (see claude-meter/src/models.rs line 30-40). So for a PR that crossed the Opus ceiling, the full Opus cost is: (1.0 minus starting seven_day_opus) plus the delta on extra_usage.used_credits divided by your per-credit Opus rate. Two fields, not one.
Is the Opus float plan-specific?
Yes, and this is the subtle point. The numerator and denominator of seven_day_opus.utilization both depend on which plan you are on. A Max 20x subscriber and a Pro subscriber can both see 0.62, but the absolute Opus token budget behind those two readings is very different. ClaudeMeter reads utilization verbatim from the server, which is why the delta math works identically for every plan: it is a fraction of whatever your personal ceiling is, and the cost-per-PR delta is 'how much of my personal ceiling did this PR spend.' That is the only number that predicts your own next 429.
Keep reading
Claude Code cost per PR: the four-field delta view
Cost per PR on a subscription is four deltas, not one dollar figure. Here is the full formula across five_hour, seven_day_opus, seven_day_sonnet, and extra_usage.
Claude Code Opus 4.7 usage limits: the two server floats that gate you
Opus 4.7 caps are two server floats, not a message count. Why the 4.7 tokenizer fills seven_day_opus faster than 4.6 did.
Claude Code dollars per pull request: the only field that is real money
Three different 'dollars per PR' numbers circulate, only one becomes a charge: the delta on used_credits from the overage_spend_limit endpoint.
Want an Opus-first glance layer wired into your menu bar?
I have a forked background.js that keys the badge off seven_day_opus instead of five_hour, plus a post-commit hook that logs Opus cost per PR to a file. 15 minutes to see if it fits your plan.