Skip to content

Add optional status-bar quota format template - #108

Merged
Carl723000 merged 8 commits into
ClaudeCodeUsage:mainfrom
Alfiefe10:feat/status-bar-quota-format
Sep 22, 2026
Merged

Carl723000 merged 8 commits into
ClaudeCodeUsage:mainfrom
Alfiefe10:feat/status-bar-quota-format

Conversation

@Alfiefe10

@Alfiefe10 Alfiefe10 commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds an opt-in statusBarQuotaFormat setting (⚙ Settings > Quota: status bar format) for people who want a different set of quota windows, order or separators in the status bar than the built-in 5h 6% · wk 1%.

A template names the windows itself:

  • {5h.FIELD} – the 5-hour session window
  • {wk.FIELD} / {7d.FIELD} – the all-models week
  • {model:NAME.FIELD} – a per-model weekly cap, matched case-insensitively on the API's scope label
  • FIELD is pct, reset (follows resetCountdownFormat) or label; {{ and }} are literal braces

For example {5h.pct} | {7d.pct} · {model:Fable.pct} renders 6% | 1% · 12%, and {5h.pct} hasta {5h.reset} with the clock countdown renders 33% hasta 15:25. A reset token can also name its own style — {5h.reset:units}, :decimal, :clock or :at (the tooltip's wall clock, Thu 16:59) — so one bar can mix them: {5h.pct} {5h.reset:units} | {wk.pct} {wk.reset:at} renders 33% 2h 17m | 30% Thu 16:59 whatever resetCountdownFormat says.

Separators and literal spacing come out exactly as typed. A segment whose windows the account doesn't report is dropped together with its separator, so the same template works on a plan with no per-model cap. An unknown token is left verbatim so a typo is visible instead of silently shortening the line. The warning colour follows the windows the template actually shows, same reasoning as the built-in layout.

Empty (the default) keeps today's behaviour untouched. A non-empty template supersedes quotaFiveHourOnly and showScopedWeekly, since it already says which windows to show.

The logic is a pure helper in quotaFormat.ts; it is wired through statusBar.ts / extension.ts the same way resetCountdownFormat was in #75.

Linked issues

None.

Type of change

  • New feature (non-breaking) → feature (minor)

How was this tested?

Extension Development Host (F5), on a real account with the 5h window at 33%:

Template Status bar
{5h.pct} | {7d.pct} · {model:Fable.pct} renders all three, updates without a reload
A B {5h.pct} A B 33% — internal spacing kept
{5h.pct} · opus {model:Opus.pct} 33% — no orphaned "opus" on a plan without that cap
{5h.pcnt} {5h.pcnt} — typo stays visible
(empty) back to the built-in layout

Unit tests. node --test out/test/quotaFormat.test.js: 64/64, 23 of them new — grammar, aliases, dotted model names like Fable 5.1, all three reset formats, per-token reset styles, separators, literal spacing, dropped segments, brace escaping, typos, toggles being ignored, warning colour. statusBarThresholds.test.ts gains a wiring case that drives setVisibility/updateQuota against the vscode stub, so the path from the setting to the bar text and its warning colour is pinned, not just the pure formatter. Each new assertion was checked by mutating the compiled output until it failed.

Full suite. npm test on Windows 10: 1058 tests, 1049 pass. The 8 failures are in files this PR doesn't touch and fail identically on a clean main here — mostly EPERM: operation not permitted, symlink, since Windows needs Developer Mode for symlinks. One of them is not Windows-specific and is what turns Node Tests red here: claudeIncrementalIndex.test.ts:283 stamps its fixture 2026-08-21 and asks for windowDays: 30, so it began failing on its own around 2026-09-20, on main too (its last CI run was 2026-09-16).

Not run: the Playwright layer (npm run test:ui) — the visual baseline is chromium-linux only.

Checklist

  • npm run compile is clean
  • User-facing strings go through I18n with all eight UI locales filled
  • Behaviour/documentation changes update all seven README editions together
  • CHANGELOG.md updated (user-visible changes)
  • README.md updated if behaviour/settings changed
  • New settings default to existing behaviour (opt-in)
  • No new runtime dependencies

On the README box: the setting is documented in README.md and README-zh-CN.md, the two editions that carry settings detail. The other five (-en, -zh-TW, -ja, -ko, -id) document no settings at all — not showResetInStatusBar, not resetCountdownFormat, not statusBarMetric — so statusBarQuotaFormat would be the only setting name in those files. Happy to add it to all seven if you'd rather have it.

Adds statusBarQuotaFormat (default empty, which keeps the built-in
layout). A template names the quota windows itself:
{5h|wk|7d|model:NAME}.{pct|reset|label}, e.g.
"{5h.pct} | {7d.pct} · {model:Fable.pct}".

Separators come out as typed. A segment whose windows the account does
not report is dropped together with its separator, so one template
works across plans. The warning colour follows the windows the
template shows.
Copilot AI lite review requested due to automatic review settings September 21, 2026 07:52
@github-actions github-actions Bot added the feature Minor bump — new feature label Sep 21, 2026
@github-actions

Copy link
Copy Markdown

🤖 Automated first-pass review

The configured analysis model did not return a usable analysis for this pull request. The item has still been received and remains available for maintainer review.

To help with review, please ensure the change summary, tests, and any user-facing documentation or localization updates are included.


🤖 Posted automatically by CCU Bot — not a maintainer decision.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Preserve unknown tokens and literal whitespace, and document the setting in all seven README editions.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Adds an opt-in statusBarQuotaFormat setting for customizable quota windows, fields, separators, and localized status-bar rendering.

Changes:

  • Adds configuration, parsing, rendering, and status-bar integration.
  • Adds localization, tests, and changelog documentation.
  • Supports aliases, escaping, missing windows, and warning-color selection.
File Description
src/​types.ts Adds configuration typing.
src/​test/​quotaFormat.test.ts Tests template behavior and edge cases.
src/​statusBar.ts Applies custom quota formatting.
src/​settings.ts Registers the new setting.
src/​quotaFormat.ts Implements parsing and rendering.
src/​i18n.ts Adds localized setting text.
src/​extension.ts Wires configuration changes.
CHANGELOG.md Documents the feature.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/quotaFormat.ts Outdated
let named = 0; // window tokens in this segment...
let reported = 0; // ...and how many of them the account reports
const endSegment = (nextSep: string): void => {
const text = segment.replace(/\s+/g, ' ').trim();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, fixed in efa9b2c. I only wanted to tidy up the hole a missing window leaves, but I was collapsing the whole segment, so it also ate spaces I typed on purpose. Now only that gap closes and the rest comes out as typed (A B {5h.pct} gives A B 6%). Added tests for both cases.

Comment thread src/quotaFormat.ts
Comment on lines +330 to +333
const endSegment = (nextSep: string): void => {
const text = segment.replace(/\s+/g, ' ').trim();
if (text && (named === 0 || reported > 0)) {
out = out ? out + sep + text : text;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't reproduce that exact example: {model:Opus.pct} {5h.pct} without an Opus window gives me 6%, because {5h.pct} keeps the segment alive. But you're right about the underlying issue, it shows up when nothing else in the segment is reported: {nope.pct} {model:Opus.pct} came out empty and hid the typo. Fixed in efa9b2c, a segment with an unknown token is never dropped now. Test added.

Comment thread src/settings.ts Outdated
Comment on lines +575 to +576
label: 'Quota: status bar format',
help: 'Empty keeps the built-in layout (5h 6% · wk 1%). Otherwise: {5h.pct}, {wk.pct} (or {7d.pct}) and {model:Fable.pct}, each also taking .reset and .label — e.g. "{5h.pct} | {7d.pct} · {model:Fable.pct}". A window your plan does not report renders empty.',

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it to README.md and README-zh-CN.md. I left the other five on purpose: they don't document any setting at all (no showResetInStatusBar, no resetCountdownFormat...), so this would be the only one in there and it would look odd. If the maintainer wants it in all seven I'll add it, no problem.

Drives setVisibility/updateQuota against the vscode stub so the path from
the setting to the bar text and its warning colour is pinned, not only
the pure formatter.
Literal text kept its own whitespace collapsed, and a segment naming only
windows the account lacks took any typo in it down as well, which
contradicted the rule that an unrecognised token stays visible. A missing
window now leaves a marker that closes just its own gap.

Also documents the setting in the two README editions that carry
settings detail.
resetCountdownFormat is one setting for the whole bar, so a template could not
put a countdown for the 5h window beside a wall clock for the week. A reset
token now takes an optional style - {5h.reset:units}, :decimal, :clock or :at -
and falls back to the global format without one. A reset the API left blank
closes its gap the way a missing window does.
@Alfiefe10

Copy link
Copy Markdown
Contributor Author

About the red Node Tests: it's not from this PR. The failing test is content analysis is materialized from per-file contributions without a second body scan (claudeIncrementalIndex.test.ts:283) and it fails for me on a clean checkout of main too. The fixture has 2026-08-21 timestamps hardcoded and the test uses windowDays: 30, so it started failing by itself around Sept 20. main last ran CI on Sept 16, that's why it shows up here first. The next test in that file pins Date.now, so I guess the same fix applies. I can send it as a separate PR if you want.

I also pushed 26c8971: a reset token can now pick its own style ({5h.reset:units}, :decimal, :clock, :at), so you can mix a countdown and a wall clock in the same bar. Description updated.

@Carl723000
Carl723000 merged commit dd096f5 into ClaudeCodeUsage:main Sep 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Minor bump — new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants