From d8688dc143f1f19da02a69a23cd0324364fb7048 Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Fri, 28 Aug 2026 13:59:40 +0200 Subject: [PATCH] fix(web): drop the provider label from the plan-usage chip when there is only one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chip prefixes every row with the provider name, so a machine that only has Claude limits renders "CLAUDE 5H 60% 7D 23%" — a 46px label naming the only thing it could possibly be. The name exists to tell two rows apart, so it should only appear when there are two. updatePlanUsageChip() now checks whether both Claude and Codex actually have windows before building the rows, and emits the .pu-provider span only in that case. The tooltip keeps naming the provider in both cases: it has the room, and the chip no longer does. Verified in a browser on an isolated beta instance: Claude-only renders bare windows with no .pu-provider in the DOM, Codex-only the same, and the two-provider chip is byte-identical to before. Co-Authored-By: Claude Opus 5 (1M context) --- src/web/public/app.js | 7 ++++++- test/plan-usage-chip.test.ts | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/web/public/app.js b/src/web/public/app.js index 72898890..fc750d49 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -2638,10 +2638,15 @@ class CodemanApp { if (!Number.isFinite(n)) return ''; return `${label}${n}%`; }; + // The provider label only earns its space when there is more than one + // provider to tell apart: a machine with Claude alone shows bare windows. + const hasWindows = (usage) => pct(usage?.fiveHour) !== null || pct(usage?.sevenDay) !== null; + const labelled = hasWindows(data) && hasWindows(data.codex); const row = (provider, usage) => { const windows = [seg('5h', pct(usage?.fiveHour)), seg('7d', pct(usage?.sevenDay))].filter(Boolean); if (!windows.length) return ''; - return `${provider}${windows.join('·')}`; + const label = labelled ? `${provider}` : ''; + return `${label}${windows.join('·')}`; }; const rows = [row('Claude', data), row('Codex', data.codex)].filter(Boolean); chip.innerHTML = rows.length ? rows.join('') : '—'; diff --git a/test/plan-usage-chip.test.ts b/test/plan-usage-chip.test.ts index 09b379b5..4a801eed 100644 --- a/test/plan-usage-chip.test.ts +++ b/test/plan-usage-chip.test.ts @@ -79,4 +79,36 @@ describe('header plan usage chip', () => { expect(codexRow).not.toContain('5h'); expect(codexRow).toContain('7d'); }); + + it('drops the provider label when Claude is the only provider with limits', () => { + const { CodemanApp, chip } = loadCodemanAppClass(); + const app = Object.create((CodemanApp as { prototype: object }).prototype) as UsageApp; + + app.updatePlanUsageChip({ + fiveHour: { usedPercentage: 60, resetAt: 1000 }, + sevenDay: { usedPercentage: 23, resetAt: 2000 }, + }); + + expect(chip.innerHTML).toContain('class="pu-row"'); + expect(chip.innerHTML).not.toContain('pu-provider'); + expect(chip.innerHTML).not.toContain('Claude'); + expect(chip.innerHTML).toContain('60%'); + expect(chip.innerHTML).toContain('23%'); + // The tooltip still names the provider — it has room, and the chip no longer does. + expect(chip.title).toContain('Claude plan usage'); + }); + + it('drops the provider label when Codex is the only provider with limits', () => { + const { CodemanApp, chip } = loadCodemanAppClass(); + const app = Object.create((CodemanApp as { prototype: object }).prototype) as UsageApp; + + app.updatePlanUsageChip({ + codex: { fiveHour: { usedPercentage: 12, resetAt: 3000 } }, + }); + + expect(chip.innerHTML).toContain('class="pu-row"'); + expect(chip.innerHTML).not.toContain('pu-provider'); + expect(chip.innerHTML).toContain('12%'); + expect(chip.title).toContain('Codex plan usage'); + }); });