Claude Usage Widget Options
Shows your Claude (Claude Code) subscription usage on the bar - the 5-hour and 7-day rolling limit utilization - with a popup menu that displays both windows as progress bars together with their reset times (a countdown plus the exact reset timestamp). Any per-model weekly cap your plan has (e.g. a separate Fable limit) shows up as an extra bar automatically; see Per-model weekly caps.
The data is read from the same OAuth credentials the Claude Code CLI uses
(~/.claude/.credentials.json) and fetched from Anthropic's usage endpoint. No API key or
extra configuration is required as long as you are signed in to Claude Code.
| Option | Type | Default | Description |
|---|---|---|---|
label |
string | 'Claude {five_hour}%' |
The format string for the label. Supports the placeholders below. |
label_alt |
string | 'Claude {seven_day}%' |
The alternative format string, toggled by the toggle_label callback. |
update_interval |
integer | 60 |
How often the label and reset countdown are refreshed, in seconds. Must be between 30 and 3600. |
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. |
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). |
seven_day_reset_format |
string | 'absolute' |
How the 7-day window's reset line is phrased in the popup: relative or absolute. |
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. |
token_history |
dict | {'enabled': false, ...} |
Optional local token-usage history. See Token history. |
status |
dict | {'enabled': false, ...} |
Optional Claude API status indicator. See API status. |
tooltip |
boolean | true |
Whether to show a summary tooltip on hover. |
callbacks |
dict | {'on_left': 'toggle_menu', 'on_middle': 'do_nothing', 'on_right': 'toggle_label'} |
Mouse-click callbacks. |
menu |
dict | {'blur': true, 'round_corners': true, 'round_corners_type': 'normal', 'border_color': 'System', 'alignment': 'right', 'direction': 'down', 'offset_top': 6, 'offset_left': 0, 'pin_icon': '', 'unpin_icon': ''} |
Popup menu settings. |
Placeholders
The label is plain text by default. You can prepend a Nerd Font glyph in a <span> if you
want an icon (e.g. <span>\U000f06a9</span> {five_hour}%), or embed your own image with an
<img> tag (e.g. <img src='C:/path/to/claude.svg' width='14' height='14'> {five_hour}%). The
following placeholders can be used in label / label_alt:
{five_hour}- 5-hour window utilization (percent,--when unavailable).{seven_day}- 7-day window utilization (percent,--when unavailable).-
{five_hour_reset}- time until the 5-hour window resets. Shown as a countdown when under a day away (e.g.4h 27m), otherwise as a local weekday + time (e.g.Sat 6:00 AM). -
{seven_day_reset}- time until the 7-day window resets (e.g.Sat 6:00 AM). -
{stale}- a warning glyph shown only while Claude Code's OAuth token has expired, empty otherwise. Place it in its own<span>(e.g.{five_hour}% <span class='stale'>{stale}</span>). -
{session_tokens}{today_tokens}{week_tokens}{month_tokens}{year_tokens}- compact token totals (e.g.1.2M) for each period. Requiretoken_history.enabled;--otherwise. -
{status}- a status dot, coloured by the current Claude API status level via.status.<none|minor|major|critical>classes. Place it in its own<span>. Requiresstatus.enabled; empty otherwise. -
{status_text}- the status description (e.g.All Systems Operational).
claude_usage:
type: "yasb.claude_usage.ClaudeUsageWidget"
options:
label: "Claude {five_hour}% · {five_hour_reset}"
label_alt: "Claude 7d {seven_day}% · {seven_day_reset}"
update_interval: 60
cache_ttl: 120
callbacks:
on_left: "toggle_menu" # open the usage menu
on_middle: "refresh" # force an immediate re-fetch, bypassing cache_ttl
on_right: "toggle_label" # switch the bar text between 5h and 7d
menu:
blur: true
round_corners: true
round_corners_type: "normal"
border_color: "System"
alignment: "right"
direction: "down"
offset_top: 6
offset_left: 0
Description of Options
- label: The format string for the label. Supports the placeholders listed above.
- label_alt: The alternative format string, toggled with the
toggle_labelcallback. - update_interval: How often the bar label and reset countdown are refreshed, in seconds (30-3600).
- 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.
- five_hour_reset_format / seven_day_reset_format: How each window's reset line is phrased in the popup.
relativeshows a countdown (Resets in 4h 11m);absoluteshows a local weekday and time (Resets on Sat @ 6:00 AM). The exact reset timestamp is always shown on the line below. - reset_show_date: In
absolutemode, 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 inrelativemode. - tooltip: Whether to show a summary tooltip on hover.
- callbacks: Mouse-click callbacks. Built-in actions:
toggle_menu(open/close the popup menu),toggle_label(swap betweenlabelandlabel_alt),refresh(force an immediate re-fetch, bypassingcache_ttl),do_nothing, andexec. - menu: A dictionary specifying the popup menu settings:
- blur: Enable blur effect for the menu.
- round_corners: Enable round corners (not supported on Windows 10).
- round_corners_type: Type of round corners (
normal,small). - border_color: Border color of the menu.
- alignment: Horizontal alignment of the menu (
left,right,center). - direction: Whether the menu opens
downorup. - offset_top / offset_left: Pixel offsets for fine positioning.
- 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.
Authentication
The widget reuses Claude Code's existing OAuth session. It reads the access token from
%USERPROFILE%\.claude\.credentials.json (or $CLAUDE_CONFIG_DIR\.credentials.json when
that environment variable is set) and never logs or stores it elsewhere. If you are not
signed in to Claude Code, the widget shows -- until you sign in.
Only Claude Code itself renews the OAuth token. If it has expired (e.g. you have not used
Claude Code in a while), the usage endpoint rejects the request and the widget keeps serving
the last cached values; the {stale} placeholder shows a warning glyph until the token is
refreshed by running any Claude Code command. The refresh action forces a re-fetch but
cannot renew an expired token.
Refresh
The popup header has a refresh button that forces an immediate re-fetch, bypassing cache_ttl.
The same action is available as the refresh callback for any mouse button. While the menu is
open, its sections redraw in place when fresh data arrives. A refresh is ignored while a fetch
is already in flight.
Per-model weekly caps
Some plans give one or more models their own weekly cap on top of the shared 5-hour/7-day
windows (e.g. a separate Fable limit). When the usage endpoint reports one, the popup gains an
extra bar for it - titled with the model's name (Fable Weekly) - right after the 7-Day
section, using the same progress bar, reset line and low/medium/high colouring as the
built-in windows. There is no config option for this: it is read directly from the API response
and appears or disappears with your plan, so a model added later needs no widget update.
Token history
When token_history.enabled is true, the popup gains a Tokens section with a
Session / Today / Week / Month / Year toggle, the selected period's total, and an optional
usage graph. The same totals are available on the bar via the {*_tokens} placeholders.
The data comes from Claude Code's own session transcripts (~/.claude/projects/**/*.jsonl):
no API key and no network. Only numeric token counts, timestamps, the model name and the
session id are read; message content is never touched. The scan is incremental (a file is
re-parsed only when its size or mtime changes) and runs off the UI thread.
token_history:
enabled: true
default_period: "today" # session | today | week | month | year
show_graph: true
show_graph_grid: false
week_starts_on: "monday" # monday | sunday
count_cache_read: true # false counts only new input/output/cache-creation
scan_interval: 120 # seconds between transcript scans (30–3600)
- enabled: Turn the Tokens section and
{*_tokens}placeholders on. - default_period: Which period is selected when the menu first opens.
- show_graph / show_graph_grid: Show a usage graph for the selected period, with an optional grid.
- show_models: Show a per-model token breakdown in the Tokens section, following the selected period. Top 5 models, computed from local transcripts.
- week_starts_on: First day of the week for the Week total.
- count_cache_read: Whether cache-read tokens count toward the totals. They dominate for heavy users; set
falsefor "new work only". - scan_interval: Seconds between transcript scans (30–3600).
Session is the most recently active session's whole lifetime, so it can span days and may exceed Today.
API status
When status.enabled is true, the widget can show a coloured dot reflecting the public
Claude API status (status.claude.com, no authentication). Use the {status} placeholder on
the bar, and/or an optional status line in the popup header (show_in_menu).
status:
enabled: true
show_in_menu: true
icon: "●" # any glyph; coloured by .status.<level>
poll_interval: 300 # seconds between status checks (60–3600)
- enabled: Turn the
{status}/{status_text}placeholders and the menu status line on. - show_in_menu: Show a dot + description line in the popup header.
- icon: The glyph used for the dot. Its colour comes from the
.status.<level>class. - poll_interval: Seconds between status checks (60–3600).
Widget Style
.claude-usage {}
.claude-usage .widget-container {}
.claude-usage .icon {}
.claude-usage .label {}
.claude-usage .stale {} /* warning glyph while the OAuth token is expired */
.claude-usage .status {} /* {status} dot on the bar */
.claude-usage .status.none {} /* green / minor / major / critical / unknown */
.claude-usage .status.minor {}
.claude-usage .status.major {}
.claude-usage .status.critical {}
/* Popup menu */
.claude-usage-menu {}
.claude-usage-menu .header {} /* header row (title + refresh button) */
.claude-usage-menu .header .text {} /* "Claude Usage" title */
.claude-usage-menu .header .refresh {} /* refresh button */
.claude-usage-menu .header .refresh:hover {}
.claude-usage-menu .status-row {} /* status line below the header (show_in_menu) */
.claude-usage-menu .status-row .dot {} /* coloured via .dot.<level> */
.claude-usage-menu .status-row .status-text {}
.claude-usage-menu .section {} /* 5-Hour / 7-Day / per-model weekly bars */
.claude-usage-menu .section .title {}
.claude-usage-menu .section .progress {} /* progress-bar track */
.claude-usage-menu .section .progress .fill {} /* filled portion */
.claude-usage-menu .section .progress.low .fill {} /* < 50% */
.claude-usage-menu .section .progress.medium .fill {} /* 50-79% */
.claude-usage-menu .section .progress.high .fill {} /* >= 80% */
.claude-usage-menu .section .footer .reset {}
.claude-usage-menu .section .footer .percent {}
.claude-usage-menu .section .footer .percent.low {}
.claude-usage-menu .section .footer .percent.medium {}
.claude-usage-menu .section .footer .percent.high {}
.claude-usage-menu .section .date {} /* absolute reset timestamp */
/* Token history section (token_history.enabled) */
.claude-usage-menu .section.tokens {}
.claude-usage-menu .section .period-toggle {}
.claude-usage-menu .section .period-btn {}
.claude-usage-menu .section .period-btn.active {}
.claude-usage-menu .section .token-total {}
.claude-usage-menu .section.tokens .model-usage {} /* per-model breakdown container */
.claude-usage-menu .section.tokens .model-usage .title {} /* "Models" header */
.claude-usage-menu .section.tokens .model-rows {} /* the per-model bar rows */
.claude-usage-menu .section.tokens .model-name {}
.claude-usage-menu .section.tokens .model-total {}
.claude-usage-menu .section.tokens .model-rows .progress.model-0 .fill {} /* bar accent 0..4 */
.claude-usage-menu .section.tokens .model-rows .progress.model-1 .fill {}
.claude-usage-menu .section.tokens .model-rows .progress.model-2 .fill {}
.claude-usage-menu .section.tokens .model-rows .progress.model-3 .fill {}
.claude-usage-menu .section.tokens .model-rows .progress.model-4 .fill {}
.claude-usage-menu .header .pin-btn {} /* pin button (use font-family "Segoe Fluent Icons" for the glyphs) */
.claude-usage-menu .header .pin-btn.pinned {} /* while pinned */
.claude-usage-menu .section .graph-container {}
Example Style
A full style covering every element, including the optional status, token-history and
per-model rows. Matches the Windows 11 look the rest of the widgets (e.g. control_center)
use: a translucent dark panel (pair with menu.blur: true), white/grey text hierarchy, a blue
accent, and thin 1px separators between sections instead of boxed cards. Copy/paste and adjust
colours to taste.
/* Bar */
.claude-usage .icon {
color: rgba(255, 255, 255, 0.9);
font-size: 16px;
margin: 1px 4px 0 0;
}
.claude-usage .label {
color: rgba(255, 255, 255, 0.9);
padding: 0 2px;
}
.claude-usage .stale {
color: #ff6b6b;
margin-left: 4px;
}
.claude-usage .status { margin-right: 4px; }
.claude-usage .status.none { color: #6ccb5f; }
.claude-usage .status.minor { color: #ffc83d; }
.claude-usage .status.major { color: #ff9d42; }
.claude-usage .status.critical { color: #ff6b6b; }
.claude-usage .status.unknown { color: rgba(255, 255, 255, 0.4); }
/* Popup menu */
.claude-usage-menu {
background: rgba(32, 32, 32, 0.6);
min-width: 300px;
}
.claude-usage-menu .header {
padding: 14px 16px 10px 16px;
}
.claude-usage-menu .header .text {
color: #ffffff;
font-size: 15px;
font-weight: 600;
}
.claude-usage-menu .header .refresh,
.claude-usage-menu .header .pin-btn {
color: rgba(255, 255, 255, 0.6);
font-size: 15px;
padding: 2px 4px;
margin-left: 4px;
border-radius: 4px;
transition: background-color 0.08s, color 0.08s;
}
.claude-usage-menu .header .pin-btn {
font-family: "Segoe Fluent Icons";
}
.claude-usage-menu .header .refresh:hover,
.claude-usage-menu .header .pin-btn:hover {
color: #ffffff;
background-color: rgba(255, 255, 255, 0.08);
}
.claude-usage-menu .header .pin-btn.pinned { color: #47AFF5; }
/* Optional status line (status.show_in_menu) */
.claude-usage-menu .status-row {
padding: 0 16px 12px 16px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.claude-usage-menu .status-row .dot { font-size: 10px; margin-right: 8px; }
.claude-usage-menu .status-row .dot.none { color: #6ccb5f; }
.claude-usage-menu .status-row .dot.minor { color: #ffc83d; }
.claude-usage-menu .status-row .dot.major { color: #ff9d42; }
.claude-usage-menu .status-row .dot.critical { color: #ff6b6b; }
.claude-usage-menu .status-row .dot.unknown { color: rgba(255, 255, 255, 0.4); }
.claude-usage-menu .status-row .status-text { color: rgba(255, 255, 255, 0.6); font-size: 12px; }
/* 5-hour / 7-day sections, and any per-model weekly cap bar (e.g. Fable) - all share these rules.
A thin bottom border separates sections instead of a boxed background, and the last section
(Tokens when enabled, otherwise the last usage bar) drops it so it doesn't sit flush against
the popup's rounded bottom edge. */
.claude-usage-menu .section {
padding: 14px 16px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.claude-usage-menu .section.tokens { border-bottom: none; }
.claude-usage-menu .section .title {
color: rgba(255, 255, 255, 0.6);
font-size: 12px;
font-weight: 600;
padding-bottom: 8px;
}
.claude-usage-menu .progress {
background-color: rgba(255, 255, 255, 0.08);
border-radius: 4px;
min-height: 8px;
max-height: 8px;
}
.claude-usage-menu .progress .fill {
background-color: #47AFF5;
border-radius: 4px;
}
.claude-usage-menu .progress.medium .fill { background-color: #ffc83d; }
.claude-usage-menu .progress.high .fill { background-color: #ff6b6b; }
.claude-usage-menu .reset {
color: rgba(255, 255, 255, 0.6);
font-size: 12px;
padding-top: 8px;
}
.claude-usage-menu .percent {
color: #ffffff;
font-size: 13px;
font-weight: 600;
padding-top: 8px;
}
.claude-usage-menu .percent.medium { color: #ffc83d; }
.claude-usage-menu .percent.high { color: #ff6b6b; }
.claude-usage-menu .date {
color: rgba(255, 255, 255, 0.4);
font-size: 11px;
padding-top: 2px;
}
/* Token history (token_history.enabled) */
.claude-usage-menu .section .period-toggle { padding-bottom: 10px; }
.claude-usage-menu .section .period-btn {
color: rgba(255, 255, 255, 0.6);
background-color: rgba(255, 255, 255, 0.06);
border: none;
border-radius: 4px;
/* No left padding so the first button lines up with the 16px edge; spacing is on the right. */
padding: 4px 12px 4px 0;
font-size: 12px;
}
.claude-usage-menu .section .period-btn.active {
color: #000000;
background-color: #47AFF5;
font-weight: 600;
}
.claude-usage-menu .section .token-total {
color: #ffffff;
font-size: 20px;
font-weight: 600;
padding: 2px 0 8px 0;
}
.claude-usage-menu .section .graph-container { min-height: 60px; }
/* Per-model breakdown (token_history.show_models). The name and total columns are
given a min-width so the bar column stretches to fill the remaining space. */
.claude-usage-menu .section.tokens .model-usage { padding-bottom: 12px; }
.claude-usage-menu .section.tokens .model-usage .title { color: rgba(255, 255, 255, 0.6); }
.claude-usage-menu .section.tokens .model-name {
color: rgba(255, 255, 255, 0.85);
font-size: 12px;
min-width: 90px;
}
.claude-usage-menu .section.tokens .model-total {
color: rgba(255, 255, 255, 0.6);
font-size: 12px;
min-width: 48px;
}
.claude-usage-menu .section.tokens .model-rows .progress {
min-height: 6px;
max-height: 6px;
}
.claude-usage-menu .section.tokens .model-rows .progress.model-0 .fill { background-color: #47AFF5; }
.claude-usage-menu .section.tokens .model-rows .progress.model-1 .fill { background-color: #b48ce0; }
.claude-usage-menu .section.tokens .model-rows .progress.model-2 .fill { background-color: #6ccb5f; }
.claude-usage-menu .section.tokens .model-rows .progress.model-3 .fill { background-color: #ffc83d; }
.claude-usage-menu .section.tokens .model-rows .progress.model-4 .fill { background-color: #ff9d42; }