You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(claude_usage): token history, API status, model breakdown and pinnable popup
Builds on the existing claude_usage widget; everything is off by default and
closes#967, #970 and #971.
- refresh action plus a header button that force an immediate fetch and skip
cache_ttl, with in-flight dedup; a {stale} indicator that shows once the OAuth
token has expired; and per-window reset wording (relative or absolute, with an
optional date) that fixes the broken "Resets in Sat 6:00 AM" line
- local token-usage history: a Session/Today/Week/Month/Year section read from
Claude Code's own transcripts under ~/.claude/projects, scanned off-thread and
incrementally, with the cache bounded (hourly past 15 days and daily past ~13
months are pruned on scan). No API key, no network call, content never read
- Claude API status dot driven by the public status.claude.com page (no auth),
keeping the last known status on a failed poll
- per-model token breakdown in the Tokens section, following the same period
toggle. Model names are derived from the id so new models need no upkeep, and
fast-mode usage (usage.speed) is split into its own row
- pinnable, draggable popup matching the cpu/memory/gpu widgets, via a shared
create_pin_button helper in stat_popup
- the popup resizes to fit the selected period instead of cramming or stretching
- docs and example CSS under docs/
Co-Authored-By: ManaphatDev <106569727+Gaer12TH@users.noreply.github.com>
Copy file name to clipboardExpand all lines: README.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -90,6 +90,7 @@ choco install yasb
90
90
|[Bluetooth](https://github.com/amnweb/yasb/wiki/(Widget)-Bluetooth)| Shows the current Bluetooth status and connected devices. |
91
91
|[Brightness](https://github.com/amnweb/yasb/wiki/(Widget)-Brightness)| Displays and change the current brightness level. |
92
92
|[Cava](https://github.com/amnweb/yasb/wiki/(Widget)-Cava)| Displays audio visualizer using Cava. |
93
+
|[Claude Usage](https://github.com/amnweb/yasb/wiki/(Widget)-Claude-Usage)| Shows your Claude (Claude Code) subscription usage with a popup of the 5-hour and 7-day limits. |
93
94
|[Copilot](https://github.com/amnweb/yasb/wiki/(Widget)-Copilot)| GitHub Copilot usage with a detailed menu showing statistics |
94
95
|[CPU](https://github.com/amnweb/yasb/wiki/(Widget)-CPU)| Shows the current CPU usage and information. |
95
96
|[Clock](https://github.com/amnweb/yasb/wiki/(Widget)-Clock)| Displays the current time and date, with customizable formats. |
Copy file name to clipboardExpand all lines: docs/widgets/(Widget)-Claude-Usage.md
+130-7Lines changed: 130 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,21 +14,35 @@ extra configuration is required as long as you are signed in to Claude Code.
14
14
|`label_alt`| string |`'Claude {seven_day}%'`| The alternative format string, toggled by the `toggle_label` callback. |
15
15
|`update_interval`| integer |`60`| How often the label and reset countdown are refreshed, in seconds. Must be between 30 and 3600. |
16
16
|`cache_ttl`| integer |`120`| How long (seconds) a fetched result is cached on disk before the endpoint is queried again. The endpoint is rate-limited, so keep this at a sane value. |
17
+
|`five_hour_reset_format`| string |`'relative'`| How the 5-hour window's reset line is phrased in the popup: `relative` (`Resets in 4h 11m`) or `absolute` (`Resets on Sat @ 6:00 AM`). |
18
+
|`seven_day_reset_format`| string |`'absolute'`| How the 7-day window's reset line is phrased in the popup: `relative` or `absolute`. |
19
+
|`reset_show_date`| boolean |`true`| In `absolute` mode, include the month/day (`Resets on Sat, Jun 13 @ 6:00 AM`) so two windows resetting on the same weekday stay distinguishable. |
20
+
|`token_history`| dict |`{'enabled': false, ...}`| Optional local token-usage history. See [Token history](#token-history). |
21
+
|`status`| dict |`{'enabled': false, ...}`| Optional Claude API status indicator. See [API status](#api-status). |
17
22
|`tooltip`| boolean |`true`| Whether to show a summary tooltip on hover. |
token totals (e.g. `1.2M`) for each period. Require `token_history.enabled`; `--` otherwise.
42
+
-`{status}` — a status dot, coloured by the current Claude API status level via
43
+
`.status.<none|minor|major|critical>` classes. Place it in its own `<span>`. Requires
44
+
`status.enabled`; empty otherwise.
45
+
-`{status_text}` — the status description (e.g. `All Systems Operational`).
32
46
33
47
```yaml
34
48
claude_usage:
@@ -40,7 +54,7 @@ claude_usage:
40
54
cache_ttl: 120
41
55
callbacks:
42
56
on_left: "toggle_menu"# open the usage menu
43
-
on_middle: "do_nothing"
57
+
on_middle: "refresh"# force an immediate re-fetch, bypassing cache_ttl
44
58
on_right: "toggle_label"# switch the bar text between 5h and 7d
45
59
menu:
46
60
blur: true
@@ -59,8 +73,10 @@ claude_usage:
59
73
- **label_alt:** The alternative format string, toggled with the `toggle_label` callback.
60
74
- **update_interval:** How often the bar label and reset countdown are refreshed, in seconds (30–3600).
61
75
- **cache_ttl:** How long a fetched result is cached on disk before the usage endpoint is queried again. Because the endpoint is rate-limited (HTTP 429), the widget serves the last cached value on any error instead of going blank.
76
+
- **five_hour_reset_format / seven_day_reset_format:** How each window's reset line is phrased in the popup. `relative` shows a countdown (`Resets in 4h 11m`); `absolute` shows a local weekday and time (`Resets on Sat @ 6:00 AM`). The exact reset timestamp is always shown on the line below.
77
+
- **reset_show_date:** In `absolute` mode, include the month/day in the reset line so the 5-hour and 7-day windows can be told apart when they fall on the same weekday. No effect in `relative` mode.
62
78
- **tooltip:** Whether to show a summary tooltip on hover.
63
-
- **callbacks:** Mouse-click callbacks. Built-in actions: `toggle_menu` (open/close the popup menu), `toggle_label` (swap between `label` and `label_alt`), `do_nothing`, and `exec`.
79
+
- **callbacks:** Mouse-click callbacks. Built-in actions: `toggle_menu` (open/close the popup menu), `toggle_label` (swap between `label` and `label_alt`), `refresh` (force an immediate re-fetch, bypassing `cache_ttl`), `do_nothing`, and `exec`.
64
80
- **menu:** A dictionary specifying the popup menu settings:
65
81
- **blur:** Enable blur effect for the menu.
66
82
- **round_corners:** Enable round corners (not supported on Windows 10).
@@ -69,6 +85,7 @@ claude_usage:
69
85
- **alignment:** Horizontal alignment of the menu (`left`, `right`, `center`).
70
86
- **direction:** Whether the menu opens `down` or `up`.
71
87
- **offset_top / offset_left:** Pixel offsets for fine positioning.
88
+
- **pin_icon / unpin_icon:** Nerd Font glyphs for the pin button in the popup header. The button keeps the popup open and lets it be dragged when pinned.
72
89
73
90
## Authentication
74
91
@@ -77,15 +94,91 @@ The widget reuses Claude Code's existing OAuth session. It reads the access toke
77
94
that environment variable is set) and never logs or stores it elsewhere. If you are not
78
95
signed in to Claude Code, the widget shows `--` until you sign in.
79
96
97
+
Only Claude Code itself renews the OAuth token. If it has expired (e.g. you have not used
98
+
Claude Code in a while), the usage endpoint rejects the request and the widget keeps serving
99
+
the last cached values; the `{stale}` placeholder shows a warning glyph until the token is
100
+
refreshed by running any Claude Code command. The `refresh` action forces a re-fetch but
101
+
cannot renew an expired token.
102
+
103
+
## Refresh
104
+
105
+
The popup header has a refresh button that forces an immediate re-fetch, bypassing `cache_ttl`.
106
+
The same action is available as the `refresh` callback for any mouse button. While the menu is
107
+
open, its sections redraw in place when fresh data arrives. A refresh is ignored while a fetch
108
+
is already in flight.
109
+
110
+
## Token history
111
+
112
+
When `token_history.enabled` is `true`, the popup gains a **Tokens** section with a
113
+
Session / Today / Week / Month / Year toggle, the selected period's total, and an optional
114
+
usage graph. The same totals are available on the bar via the `{*_tokens}` placeholders.
115
+
116
+
The data comes from Claude Code's own session transcripts (`~/.claude/projects/**/*.jsonl`):
117
+
no API key and no network. Only numeric token counts, timestamps, the model name and the
118
+
session id are read; message content is never touched. The scan is incremental (a file is
119
+
re-parsed only when its size or mtime changes) and runs off the UI thread.
count_cache_read: true # false counts only new input/output/cache-creation
129
+
scan_interval: 120 # seconds between transcript scans (30–3600)
130
+
```
131
+
132
+
- **enabled:** Turn the Tokens section and `{*_tokens}` placeholders on.
133
+
- **default_period:** Which period is selected when the menu first opens.
134
+
- **show_graph / show_graph_grid:** Show a usage graph for the selected period, with an optional grid.
135
+
- **show_models:** Show a per-model token breakdown in the Tokens section, following the selected period. Top 5 models, computed from local transcripts.
136
+
- **week_starts_on:** First day of the week for the Week total.
137
+
- **count_cache_read:** Whether cache-read tokens count toward the totals. They dominate for heavy users; set `false` for "new work only".
138
+
- **scan_interval:** Seconds between transcript scans (30–3600).
139
+
140
+
> Session is the most recently active session's whole lifetime, so it can span days and may exceed Today.
141
+
142
+
## API status
143
+
144
+
When `status.enabled` is `true`, the widget can show a coloured dot reflecting the public
145
+
Claude API status (`status.claude.com`, no authentication). Use the `{status}` placeholder on
146
+
the bar, and/or an optional status line in the popup header (`show_in_menu`).
147
+
148
+
```yaml
149
+
status:
150
+
enabled: true
151
+
show_in_menu: true
152
+
icon: "●" # any glyph; coloured by .status.<level>
153
+
poll_interval: 300 # seconds between status checks (60–3600)
154
+
```
155
+
156
+
- **enabled:** Turn the `{status}`/`{status_text}` placeholders and the menu status line on.
157
+
- **show_in_menu:** Show a dot + description line in the popup header.
158
+
- **icon:** The glyph used for the dot. Its colour comes from the `.status.<level>` class.
159
+
- **poll_interval:** Seconds between status checks (60–3600).
160
+
80
161
## Widget Style
81
162
```css
82
163
.claude-usage {}
83
164
.claude-usage .widget-container {}
84
165
.claude-usage .icon {}
85
166
.claude-usage .label {}
167
+
.claude-usage .stale {} /* warning glyph while the OAuth token is expired */
168
+
.claude-usage .status {} /* {status} dot on the bar */
169
+
.claude-usage .status.none {} /* green / minor / major / critical / unknown */
170
+
.claude-usage .status.minor {}
171
+
.claude-usage .status.major {}
172
+
.claude-usage .status.critical {}
86
173
/* Popup menu */
87
174
.claude-usage-menu {}
88
-
.claude-usage-menu .header {} /* "Claude Usage" title */
0 commit comments