Skip to content

feat: add API usage widgets (session, weekly, reset, context bar) - #168

Merged
sirmalloc merged 9 commits into
sirmalloc:mainfrom
pcvelz:feat/api-usage-widgets
Mar 2, 2026
Merged

sirmalloc merged 9 commits into
sirmalloc:mainfrom
pcvelz:feat/api-usage-widgets

Conversation

@pcvelz

@pcvelz pcvelz commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds four new widgets that display Claude Code API usage data, closing #94:

  • session-usage: 5-hour session utilization with progress bar
  • weekly-usage: 7-day utilization with progress bar
  • reset-timer: countdown to next session reset
  • context-bar: context window usage with progress bar (using context_window data from Claude Code stdin JSON)

Also enhances the existing ContextPercentage widget to use context_window data when transcript-based token metrics aren't available.

How it works

  • Fetches from GET /api/oauth/usage using existing OAuth credentials (macOS Keychain + Linux ~/.claude/.credentials.json fallback)
  • 180-second cache + 30-second rate limit lock to minimize API calls
  • Widgets register in the standard widget registry — users add them via the TUI like any other widget
  • No changes to default widget layout

Files changed

File Change
src/widgets/ApiUsage.tsx New — all 4 widget classes + credential reading + API fetch + caching
src/widgets/index.ts Export new widgets
src/utils/widgets.ts Register in widget registry
src/types/StatusJSON.ts Add context_window schema for Claude Code's context data
src/widgets/ContextPercentage.ts Enhanced to use context_window from stdin when available

Context

This was originally prototyped as a bash script and then implemented as native TypeScript widgets in a fork. This PR extracts just the widget code with no other changes.

Uses the same API approach as claude-pulse — same endpoint, same auth headers.

Test plan

  • bun run build succeeds
  • bun test passes
  • Widgets appear in TUI widget list and can be added to lines
  • Piped input renders session/weekly usage bars when credentials are available
  • Shows [No credentials] gracefully when OAuth token is unavailable
  • Cache file created at ~/.cache/ccstatusline-api.json after first API call
  • Verify on Linux with ~/.claude/.credentials.json

@sirmalloc

Copy link
Copy Markdown
Owner

@pcvelz Thanks, I'll review this soon, travelling at the moment. How does this handle Windows and WSL? If they are unsupported, I'd like to still merge it, but with a system to gate it properly and have it only appear on supported OS's.

@zhil

zhil commented Feb 24, 2026

Copy link
Copy Markdown

@sirmalloc can this be merged?

liafonx added a commit to liafonx/ccstatusline that referenced this pull request Feb 25, 2026
… reset, context bar)

Resolved conflicts: keep both fork widgets (session-name, free-memory) and PR widgets (session-usage, weekly-usage, reset-timer, context-bar).

Made-with: Cursor
@liafonx

liafonx commented Feb 26, 2026 •

Copy link
Copy Markdown

Hi, this is quite a handy feature for Subscription users. Since the PR is still pending merge, would you mind adding a small custom feature that allows users to choose whether to hide or unhide the progress bar? For example, I like to keep the status line compact and only show the used percentage.
PS: Also request to support rawValue mode

@pcvelz
pcvelz force-pushed the feat/api-usage-widgets branch from e643ee6 to b7dae7c Compare February 26, 2026 11:25
@pcvelz

pcvelz commented Feb 26, 2026

Copy link
Copy Markdown
Contributor Author

@sirmalloc I've updated this PR with Windows support, based on @zac15987's working Windows snippet on issue #94.

I don't have access to a Windows machine myself, so I can't verify this with absolute certainty. That said, I'm fairly confident it works — I analyzed the differences between zac15987's working Windows script and our widget code, and the only deviation was process.env.HOME, which is undefined on Windows. Replaced it with os.homedir() which works cross-platform.

The rest of the code was already platform-agnostic:

  • Credential reading uses fs.readFileSync (works on all platforms)
  • API calls use Node's built-in https module (no curl/shell dependency)
  • All paths use path.join() (handles Windows backslashes)
  • macOS Keychain access is gated behind process.platform === 'darwin'

On Windows, credentials are read from ~/.claude/.credentials.json — same as Linux.

The fix is also published as v2.1.8 in the fork.

Add four new widgets that display Claude Code API usage data:
- session-usage: 5-hour session utilization with progress bar
- weekly-usage: 7-day utilization with progress bar
- reset-timer: countdown to session reset
- context-bar: context window usage with progress bar

Fetches data from /api/oauth/usage using existing OAuth credentials
(macOS Keychain + Linux file fallback). Includes 180s cache with
30s rate limiting to minimize API calls.

Also enhances ContextPercentage widget to use context_window data
from Claude Code's stdin JSON when available.

Closes sirmalloc#94
@pcvelz
pcvelz force-pushed the feat/api-usage-widgets branch from b7dae7c to 07dd5d8 Compare February 26, 2026 11:38
@sirmalloc

Copy link
Copy Markdown
Owner

@pcvelz I've got a Windows machine I can test on. I'll dig into reviewing this today.

@mcg88

mcg88 commented Mar 2, 2026

Copy link
Copy Markdown

@sirmalloc Anything further needed on this? I'd like to see it merged into main so happy to help with any outstanding issues.

…statusline

- parse credentials/cache/API response via zod with nullable field support\n- move usage cache+lock to ~/.cache/ccstatusline/usage.{json,lock}\n- add missing getCategory() methods on API usage widgets\n- resolve context percentage brace-style lint issue
@sirmalloc

Copy link
Copy Markdown
Owner

@mcg88 @pcvelz I'm actively working on this. I'll be pushing several changes to the PR to fit this change into the existing style conventions of the codebase and address some issues. Hang tight.

Split API usage widgets into dedicated files and a shared usage utility, replacing the monolithic ApiUsage widget module.

Key changes:

- add src/utils/usage.ts for API fetch/caching, parsing, error mapping, progress-bar helpers, and shared 5-hour window math

- move widgets to standalone files: SessionUsage, WeeklyUsage, ResetTimer, ContextBar

- remove src/widgets/ApiUsage.tsx and update widget exports/registry wiring

- make BlockTimer usage-aware with usage API first and JSONL fallback via shared resolver

- make ResetTimer follow BlockTimer UX: time/progress/short-progress modes, raw value support, invert toggle, and JSONL fallback when usage timing is unavailable

- make SessionUsage and WeeklyUsage match timer interaction model: progress mode cycling, invert toggle, invert-clearing when returning to text mode, and raw-value support

- update ItemsEditor to hide/disable invert keybind when widget is in text mode

- remove eager block-metric parsing from ccstatusline render path so JSONL fallback is only invoked when usage timing is missing

- add comprehensive tests for usage window fallback behavior and widget mode/toggle/raw output behavior

Validation:

- bun test

- bun run lint
- add a shared context-window metrics utility to normalize context_window fields (window size, percentages, usage, and token snapshots)

- make context window size from status JSON authoritative for context calculations when present; derive usable limit as 80% of reported size

- keep model-id fallback behavior for missing context_window data, including case-insensitive [1m]/[1M] detection

- update Context %, Context % (usable), Context Length, and Context Bar to use status JSON first and fall back to JSONL token metrics when needed

- update Session Clock to use cost.total_duration_ms first with JSONL duration fallback

- keep Tokens Input/Output JSON-first, while reverting Tokens Cached/Total to cumulative session JSONL totals

- simplify render pipeline behavior to always parse current session JSONL token metrics when transcript_path exists

- add/expand tests for context-window parsing, denominator precedence, 1M-without-suffix scenarios, case-insensitive suffix fallback, token widget source behavior, context bar rendering, and session clock behavior
- switch Context Bar usage basis from total current_usage (input+output+cache) to context-length usage (input+cache), matching Context Length widget

- keep statusline JSON-first behavior with JSONL/model fallbacks unchanged

- keep short-by-default progress mode and long/short toggle behavior

- update ContextBar tests for new token basis and progress-mode expectations
@sirmalloc
sirmalloc merged commit a03b7c2 into sirmalloc:main Mar 2, 2026
@sirmalloc

Copy link
Copy Markdown
Owner

Merged, will publish soon

@sirmalloc

Copy link
Copy Markdown
Owner

@pcvelz This has been published as v2.1.0

@sanjeevpenupala

Copy link
Copy Markdown

@sirmalloc Getting API error when adding the usage status lines. How can I debug what exactly is the issue?

CleanShot 2026-03-03 at 09 49 24

@sirmalloc

Copy link
Copy Markdown
Owner

@sanjeevpenupala What OS are you on?

@sanjeevpenupala

sanjeevpenupala commented Mar 3, 2026 •

Copy link
Copy Markdown

@sirmalloc I'm on macOS Sequoia 15.6.1.

Also, I just did /login and the usage percentages showed up thereafter. Weird...

Does the code require to periodically refresh your credentials, to show your usage?

CleanShot 2026-03-03 at 09 53 53

@sirmalloc

Copy link
Copy Markdown
Owner

@sanjeevpenupala interesting. On macOS it uses your oauth token from the keychain, maybe /login refreshed it? I only tested on macOS 26, let me know if this occurs again or stops working.

@sirmalloc

Copy link
Copy Markdown
Owner

@sanjeevpenupala It's possible if you hadn't launched claude in a bit that the oauth token in your keychain was expired, and claude had not refreshed it during the first rendering of the statusline. there's also a 30s lock / error window on the usage fetch, so it's possible doing any message in claude that force a token refresh and then refreshed the statusline would have fixed it. I'll explore some better UX around this.

@sirmalloc

Copy link
Copy Markdown
Owner

@sanjeevpenupala Actually I think their usage api is acting up. Doing /usage in claude code directly is stalling out for me. Potentially related to all the outages recently.

@pcvelz
pcvelz deleted the feat/api-usage-widgets branch March 14, 2026 13:16
BenIsLegit pushed a commit to BenIsLegit/ccstatusline-usage that referenced this pull request Mar 28, 2026
…rmalloc#168)

* feat: add API usage widgets (session, weekly, reset timer, context bar)

Add four new widgets that display Claude Code API usage data:
- session-usage: 5-hour session utilization with progress bar
- weekly-usage: 7-day utilization with progress bar
- reset-timer: countdown to session reset
- context-bar: context window usage with progress bar

Fetches data from /api/oauth/usage using existing OAuth credentials
(macOS Keychain + Linux file fallback). Includes 180s cache with
30s rate limiting to minimize API calls.

Also enhances ContextPercentage widget to use context_window data
from Claude Code's stdin JSON when available.

Closes sirmalloc#94

* fix(api-usage): zod-validate usage data and move cache to ~/.cache/ccstatusline

- parse credentials/cache/API response via zod with nullable field support\n- move usage cache+lock to ~/.cache/ccstatusline/usage.{json,lock}\n- add missing getCategory() methods on API usage widgets\n- resolve context percentage brace-style lint issue

* Refactor usage widgets and unify timer/usage display modes

Split API usage widgets into dedicated files and a shared usage utility, replacing the monolithic ApiUsage widget module.

Key changes:

- add src/utils/usage.ts for API fetch/caching, parsing, error mapping, progress-bar helpers, and shared 5-hour window math

- move widgets to standalone files: SessionUsage, WeeklyUsage, ResetTimer, ContextBar

- remove src/widgets/ApiUsage.tsx and update widget exports/registry wiring

- make BlockTimer usage-aware with usage API first and JSONL fallback via shared resolver

- make ResetTimer follow BlockTimer UX: time/progress/short-progress modes, raw value support, invert toggle, and JSONL fallback when usage timing is unavailable

- make SessionUsage and WeeklyUsage match timer interaction model: progress mode cycling, invert toggle, invert-clearing when returning to text mode, and raw-value support

- update ItemsEditor to hide/disable invert keybind when widget is in text mode

- remove eager block-metric parsing from ccstatusline render path so JSONL fallback is only invoked when usage timing is missing

- add comprehensive tests for usage window fallback behavior and widget mode/toggle/raw output behavior

Validation:

- bun test

- bun run lint

* Prefer status JSON context-window metrics with robust fallbacks

- add a shared context-window metrics utility to normalize context_window fields (window size, percentages, usage, and token snapshots)

- make context window size from status JSON authoritative for context calculations when present; derive usable limit as 80% of reported size

- keep model-id fallback behavior for missing context_window data, including case-insensitive [1m]/[1M] detection

- update Context %, Context % (usable), Context Length, and Context Bar to use status JSON first and fall back to JSONL token metrics when needed

- update Session Clock to use cost.total_duration_ms first with JSONL duration fallback

- keep Tokens Input/Output JSON-first, while reverting Tokens Cached/Total to cumulative session JSONL totals

- simplify render pipeline behavior to always parse current session JSONL token metrics when transcript_path exists

- add/expand tests for context-window parsing, denominator precedence, 1M-without-suffix scenarios, case-insensitive suffix fallback, token widget source behavior, context bar rendering, and session clock behavior

* Align Context Bar with Context Length semantics

- switch Context Bar usage basis from total current_usage (input+output+cache) to context-length usage (input+cache), matching Context Length widget

- keep statusline JSON-first behavior with JSONL/model fallbacks unchanged

- keep short-by-default progress mode and long/short toggle behavior

- update ContextBar tests for new token basis and progress-mode expectations

* usage: honor CLAUDE_CONFIG_DIR and use runtime-safe HTTPS API fetch

* Fix context bar overflow and preserve usage error states

* Group usage widgets under new Usage picker category

* Rename context remaining toggle to used/remaining shortcut

---------

Co-authored-by: Peter van Velzen <[email protected]>
Co-authored-by: Matthew Breedlove <[email protected]>
tahodev pushed a commit to tahodev/ccstatusline that referenced this pull request Oct 20, 2026
…rmalloc#168)

* feat: add API usage widgets (session, weekly, reset timer, context bar)

Add four new widgets that display Claude Code API usage data:
- session-usage: 5-hour session utilization with progress bar
- weekly-usage: 7-day utilization with progress bar
- reset-timer: countdown to session reset
- context-bar: context window usage with progress bar

Fetches data from /api/oauth/usage using existing OAuth credentials
(macOS Keychain + Linux file fallback). Includes 180s cache with
30s rate limiting to minimize API calls.

Also enhances ContextPercentage widget to use context_window data
from Claude Code's stdin JSON when available.

Closes sirmalloc#94

* fix(api-usage): zod-validate usage data and move cache to ~/.cache/ccstatusline

- parse credentials/cache/API response via zod with nullable field support\n- move usage cache+lock to ~/.cache/ccstatusline/usage.{json,lock}\n- add missing getCategory() methods on API usage widgets\n- resolve context percentage brace-style lint issue

* Refactor usage widgets and unify timer/usage display modes

Split API usage widgets into dedicated files and a shared usage utility, replacing the monolithic ApiUsage widget module.

Key changes:

- add src/utils/usage.ts for API fetch/caching, parsing, error mapping, progress-bar helpers, and shared 5-hour window math

- move widgets to standalone files: SessionUsage, WeeklyUsage, ResetTimer, ContextBar

- remove src/widgets/ApiUsage.tsx and update widget exports/registry wiring

- make BlockTimer usage-aware with usage API first and JSONL fallback via shared resolver

- make ResetTimer follow BlockTimer UX: time/progress/short-progress modes, raw value support, invert toggle, and JSONL fallback when usage timing is unavailable

- make SessionUsage and WeeklyUsage match timer interaction model: progress mode cycling, invert toggle, invert-clearing when returning to text mode, and raw-value support

- update ItemsEditor to hide/disable invert keybind when widget is in text mode

- remove eager block-metric parsing from ccstatusline render path so JSONL fallback is only invoked when usage timing is missing

- add comprehensive tests for usage window fallback behavior and widget mode/toggle/raw output behavior

Validation:

- bun test

- bun run lint

* Prefer status JSON context-window metrics with robust fallbacks

- add a shared context-window metrics utility to normalize context_window fields (window size, percentages, usage, and token snapshots)

- make context window size from status JSON authoritative for context calculations when present; derive usable limit as 80% of reported size

- keep model-id fallback behavior for missing context_window data, including case-insensitive [1m]/[1M] detection

- update Context %, Context % (usable), Context Length, and Context Bar to use status JSON first and fall back to JSONL token metrics when needed

- update Session Clock to use cost.total_duration_ms first with JSONL duration fallback

- keep Tokens Input/Output JSON-first, while reverting Tokens Cached/Total to cumulative session JSONL totals

- simplify render pipeline behavior to always parse current session JSONL token metrics when transcript_path exists

- add/expand tests for context-window parsing, denominator precedence, 1M-without-suffix scenarios, case-insensitive suffix fallback, token widget source behavior, context bar rendering, and session clock behavior

* Align Context Bar with Context Length semantics

- switch Context Bar usage basis from total current_usage (input+output+cache) to context-length usage (input+cache), matching Context Length widget

- keep statusline JSON-first behavior with JSONL/model fallbacks unchanged

- keep short-by-default progress mode and long/short toggle behavior

- update ContextBar tests for new token basis and progress-mode expectations

* usage: honor CLAUDE_CONFIG_DIR and use runtime-safe HTTPS API fetch

* Fix context bar overflow and preserve usage error states

* Group usage widgets under new Usage picker category

* Rename context remaining toggle to used/remaining shortcut

---------

Co-authored-by: Peter van Velzen <[email protected]>
Co-authored-by: Matthew Breedlove <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants