Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ ccstatusline --version
- **Context Length** / **Context Window** / **Context %** / **Context % (usable)** / **Context Bar** - Show current context length, total context window size, used/remaining percentage, usable-window percentage, or a progress bar. The window size is taken from Claude Code's reported `context_window.context_window_size` when present, then from a model-name hint (e.g. a `[1m]` suffix), and finally from a fixed fallback. Set `CCSTATUSLINE_CONTEXT_SIZE_FALLBACK` to a positive integer to override that last-resort fallback (defaults to `200000`) — useful when an older Claude Code does not report the window size for a 1M-context model, so the bar would otherwise read against 200k. Immediately after `/compact`, transcript fallback uses the latest `compact_boundary.postTokens` value until a new main-chain turn reports the current size, so the widgets do not retain the pre-compaction context.
- **Compaction Counter** - Show how many context compactions have been detected in the current session by scanning transcript compaction markers. It can render as icon plus number, text plus number, or number-only, and can hide while the count is zero. Two optional, independent per-item add-ons toggle extra detail: a trigger split (`↻ 3 (2 auto, 1 manual)`; a compaction whose trigger is missing or unrecognized is bucketed as `unknown`) and tokens reclaimed (`↻ 3 ↓887.0k`, each compaction's `preTokens - postTokens` floored at 0 and summed, shown only when greater than 0 — so very old transcripts predating the `postTokens` field display nothing). Its value selector can instead render the total count, one trigger count (`auto`, `manual`, or `unknown`), or reclaimed tokens as a standalone value; hide-when-zero applies to the selected value.
- **Spend Limit Usage** / **Spend Limit Amount** - For developers behind a Claude apps gateway with spend limits (Claude Code 2.1.251 or later). Spend Limit Usage shows the share of the limit used, as a percentage or bar, and can show the remaining share instead. Spend Limit Amount shows `$314.12 / $500.00` and renders nothing until the gateway reports the dollar figures (Claude Code and gateway 2.1.284 or later). Both read `rate_limits.spend_limit` from the status line payload only and never call the usage API; without a spend limit they render nothing.
- **Session Usage** / **Weekly Usage** / **Weekly Sonnet Usage** / **Weekly Opus Usage** / **Weekly Fable Usage** / **Extra Usage Utilization** / **Extra Usage Remaining** / **Extra Usage Used** / **Extra Usage Daily Budget** / **Block Timer** / **Block Reset Timer** / **Weekly Reset Timer** - Show usage percentages, monthly pay-as-you-go overage usage, and current block/reset timing. Session and all-model weekly usage read the legacy flat API buckets when available and fall back per field to `session` and `weekly_all` entries in the newer `limits[]` response. The per-model widgets prefer `weekly_scoped` entries for Sonnet, Opus, and Fable, with legacy Sonnet/Opus buckets as fallbacks; Weekly Fable Usage renders nothing when the API reports no Fable quota. Session Usage, the weekly percentage widgets, and Extra Usage Utilization can show either used or remaining percentage in every display mode. Session and weekly usage bars can also show a time cursor. Extra usage widgets accept known extra-usage state as complete when an account has no monthly limit configured, avoid repeated refetches and stale `[Timeout]` output, and format amounts with the API-reported billing currency when available. On accounts with no plan limits (usage-based Enterprise plans), extra usage is all of the account's spend rather than overage beyond a plan; the label editor can change the Extra Usage widgets' `Overage` labels to read `Spend`. Before the first charge of the month the API reports no utilization, so Extra Usage Utilization works it out from the amount spent and the monthly limit. Extra Usage Daily Budget divides what's left of the monthly limit by the days left in the month, today included, optionally skipping future weekend days (today always counts). It requires a monthly limit and amount spent, and displays zero once the limit is exhausted. Days are UTC days, since monthly limits reset at 00:00 UTC on the 1st. Reset timers can show remaining time, progress, or exact reset date/time with timezone and locale controls; while reset data is still arriving at startup, they show a labeled loading placeholder instead of a transient API error.
- **Block Usage** / **Weekly Usage** / **Weekly Sonnet Usage** / **Weekly Opus Usage** / **Weekly Fable Usage** / **Extra Usage Utilization** / **Extra Usage Remaining** / **Extra Usage Used** / **Extra Usage Daily Budget** / **Block Timer** / **Block Reset Timer** / **Weekly Reset Timer** - Show usage percentages, monthly pay-as-you-go overage usage, and current block/reset timing. Block Usage and the all-model Weekly Usage read the legacy flat API buckets when available and fall back per field to `session` and `weekly_all` entries in the newer `limits[]` response. The per-model widgets prefer `weekly_scoped` entries for Sonnet, Opus, and Fable, with legacy Sonnet/Opus buckets as fallbacks; Weekly Fable Usage renders nothing when the API reports no Fable quota. Block Usage, the weekly percentage widgets, and Extra Usage Utilization can show either used or remaining percentage in every display mode. Block and weekly usage bars can also show a time cursor. Extra usage widgets accept known extra-usage state as complete when an account has no monthly limit configured, avoid repeated refetches and stale `[Timeout]` output, and format amounts with the API-reported billing currency when available. On accounts with no plan limits (usage-based Enterprise plans), extra usage is all of the account's spend rather than overage beyond a plan; the label editor can change the Extra Usage widgets' `Overage` labels to read `Spend`. Before the first charge of the month the API reports no utilization, so Extra Usage Utilization works it out from the amount spent and the monthly limit. Extra Usage Daily Budget divides what's left of the monthly limit by the days left in the month, today included, optionally skipping future weekend days (today always counts). It requires a monthly limit and amount spent, and displays zero once the limit is exhausted. Days are UTC days, since monthly limits reset at 00:00 UTC on the 1st. Reset timers can show remaining time, progress, or exact reset date/time with timezone and locale controls; while reset data is still arriving at startup, they show a labeled loading placeholder instead of a transient API error.

An explicit per-model quota at 0% is shown even when its reset timestamp is still missing; the time cursor appears only once a usable window is available. Weekly Fable Usage uses the label `Weekly Fable:` and stays empty when the API reports no Fable quota.

Expand Down Expand Up @@ -297,7 +297,7 @@ Widget-specific shortcuts:
- **Git Conflicts**: `z` toggles how a visible conflict-free tree renders (`⚠0` or the clean glyph); `g` edits the conflict and clean glyphs
- **Context % widgets**: `u` toggle used vs remaining display, `p` cycle percentage/short bar/short bar only
- **Session Cost Rate**: `t` switch between active time (how long Claude spent working, the default) and clock time (the whole session)
- **Session Usage / Weekly Usage / Weekly Sonnet Usage / Weekly Opus Usage / Weekly Fable Usage / Spend Limit Usage / Extra Usage Utilization**: `p` cycle percentage/full bar/medium bar/short bar/short bar only and `u` switch between used and remaining percentage in every display mode. The editor row labels the current direction as `used` or `remaining`, while the `u` helper names the direction it will switch to. Session and weekly usage widgets use `t` to toggle the time cursor in bar modes.
- **Block Usage / Weekly Usage / Weekly Sonnet Usage / Weekly Opus Usage / Weekly Fable Usage / Spend Limit Usage / Extra Usage Utilization**: `p` cycle percentage/full bar/medium bar/short bar/short bar only and `u` switch between used and remaining percentage in every display mode. The editor row labels the current direction as `used` or `remaining`, while the `u` helper names the direction it will switch to. Block and weekly usage widgets use `t` to toggle the time cursor in bar modes.
- **Extra Usage Daily Budget**: `w` toggle counting weekdays only (Saturday and Sunday, UTC, are skipped; today always counts)
- **Block Timer**: `p` cycle time/full bar/short bar, `s` toggle compact time, `v` invert fill in progress mode
- **Block Reset Timer**: `p` cycle time/full bar/short bar, `s` toggle compact time/date, `t` toggle exact reset date/time, `f` toggle 12/24-hour display in date mode, `z` edit timezone in date mode, `l` edit locale in date mode, `v` invert fill in progress mode
Expand Down
28 changes: 20 additions & 8 deletions src/widgets/__tests__/SessionUsage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,20 @@ describe('SessionUsageWidget', () => {
id: 'session',
type: 'session-usage',
metadata: { cursor: 'true', display: 'slider' }
}, context)).toBe('Session: ▓▓░░░│░░░░ 20.0%');
}, context)).toBe('5h: ▓▓░░░│░░░░ 20.0%');
expect(render(widget, {
id: 'session',
type: 'session-usage',
metadata: { cursor: 'true', display: 'slider-only' }
}, context)).toBe('Session: ▓▓░░░│░░░░');
}, context)).toBe('5h: ▓▓░░░│░░░░');
});

it('applies the label override to every display mode', () => {
const widget = new SessionUsageWidget();
const context: RenderContext = { usageData: { sessionUsage: 20 } };
const metadata = { label: '5h ' };

expect(widget.getLabelPrefix()).toBe('Session: ');
expect(widget.getLabelPrefix()).toBe('5h: ');
expect(render(widget, { id: 'session', type: 'session-usage', metadata }, context)).toBe('5h 20.0%');
expect(render(widget, {
id: 'session',
Expand All @@ -77,19 +77,31 @@ describe('SessionUsageWidget', () => {
}, context)).toBe('5h ▓▓░░░░░░░░');
});

// The widget was Session Usage, labeled "Session: ", which Session Clock and
// Session Name use for the conversation; "Block: " is Block Timer's. The old
// label is an override away.
it('is Block Usage, labeled "5h: ", and takes "Session: " back as an override', () => {
const widget = new SessionUsageWidget();
const context: RenderContext = { usageData: { sessionUsage: 20 } };

expect(widget.getDisplayName()).toBe('Block Usage');
expect(render(widget, { id: 'session', type: 'session-usage' }, context)).toBe('5h: 20.0%');
expect(render(widget, { id: 'session', type: 'session-usage', metadata: { label: 'Session: ' } }, context)).toBe('Session: 20.0%');
});

runUsagePercentWidgetSuite({
baseItem: { id: 'session', type: 'session-usage' },
createWidget: () => new SessionUsageWidget(),
errorMessageMock: usageErrorMessageMock,
expectedInvertedTime: 'Session: 76.5%',
expectedInvertedTime: '5h: 76.5%',
expectedModifierText: '(medium bar, remaining)',
expectedPreviewInvertedTime: 'Session: 80.0%',
expectedProgress: 'Session: [████████████░░░░] 76.5%',
expectedPreviewInvertedTime: '5h: 80.0%',
expectedProgress: '5h: [████████████░░░░] 76.5%',
expectedRawInvertedTime: '76.5%',
expectedRawProgress: '[████████░░░░░░░░░░░░░░░░░░░░░░░░] 23.4%',
expectedRawTime: '23.4%',
expectedTime: 'Session: 23.4%',
expectedWholePercentTime: 'Session: 23%',
expectedTime: '5h: 23.4%',
expectedWholePercentTime: '5h: 23%',
modifierItem: {
id: 'session',
type: 'session-usage',
Expand Down
6 changes: 3 additions & 3 deletions src/widgets/shared/usage-percent-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ interface UsagePercentWidgetKindConfig {

const USAGE_PERCENT_WIDGET_CONFIG: Record<UsagePercentWidgetKind, UsagePercentWidgetKindConfig> = {
'session': {
label: 'Session: ',
displayName: 'Session Usage',
description: 'Shows daily/session API usage percentage',
label: '5h: ',
displayName: 'Block Usage',
description: 'Shows the current 5-hour block\'s usage percentage',
previewPercent: 20,
usageField: 'sessionUsage'
},
Expand Down
Loading