Allow the HUD to show usage from an opt-in local snapshot when Claude Code omits rate limits, while rejecting stale or malformed data and documenting the fallback.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(provider): add Vertex AI detection and disable cost estimation
Add `isVertexModelId()` to detect Vertex AI model IDs (which use `@`
as a version separator, e.g. `claude-3-5-sonnet@20241022`), and check
`CLAUDE_CODE_USE_VERTEX=1` in `getProviderLabel()` to show "Vertex"
label alongside the existing Bedrock/Enterprise labels.
Disable cost estimation for Vertex AI users in both `estimateSessionCost`
and `getNativeCostUsd`, matching the existing Bedrock exclusion, since
Vertex pricing differs from Anthropic direct pricing.
* docs: add Vertex AI to provider label examples and cost notes
---------
Co-authored-by: mikzz xia <mikzzz@mikzzdeMacBook-Pro.local>
Claude Code occasionally reports context window usage as 0 despite
accumulated tokens, causing the statusline to display incorrect data.
Cache the last known-good context snapshot per session and restore it
when a suspicious zero frame is detected, with TTL-throttled writes
and periodic stale-entry cleanup.
Adds `display.usageCompact` (boolean, default false) that renders
usage stats in a shorter format:
Default: Usage 5h 25% (resets in 3h 45m) | Weekly 8% (resets in 2d)
Compact: 5h: 25% (3h 45m) | 7d: 8% (2d)
When enabled: drops the "Usage" label, uses "5h:"/"7d:" prefixes
with a colon, and shortens "(resets in X)" to "(X)".
Also fixes the Usage Style Mapping table in configure.md — the
"Text style" description previously showed `5h: 25% (1h 30m)` which
did not match the actual output. The table now accurately documents
all three styles (bar, text, compact).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When all terminal width detection methods fail (stdout.columns,
stderr.columns, COLUMNS env), the renderer falls back to the
hardcoded UNKNOWN_TERMINAL_WIDTH (40). This new `maxWidth` config
option lets users replace that fallback with a value suited to
their device — useful on mobile clients, piped subprocesses, or
terminals where auto-detection is unreliable.
When the terminal reports a real width, maxWidth is ignored.
Closes#385, closes#404
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Displays the current reasoning effort level inside the model bracket
(e.g., [Opus 4.6 ●max]) when `display.showEffortLevel` is enabled.
Data source priority:
1. stdin.effort field (future-proof — ready for when Claude Code
exposes effort in statusline JSON, per issues #39399, #50060)
2. Parent process CLI args (detects --effort flag at session start)
Supports all known levels with progressive fill symbols:
○ low | ◔ medium | ◑ high | ◕ xhigh | ● max
Unknown future levels display as plain text (no symbol), ensuring
forward compatibility as Claude Code adds/removes effort levels.
Also fixes: version selector in setup.md bash templates now filters
non-semver directories (e.g., .bak, -old) via grep before sort,
matching the existing PowerShell behavior.
Closes#201, relates to anthropics/claude-code#39399
Enterprise Claude Code accounts use model IDs like opusplan,
sonnetplan, and haikuplan instead of standard model names.
Previously getProviderLabel() returned 'Enterprise' for these,
causing usage and cost displays to be hidden via the same code
path used for Bedrock (which legitimately cannot show usage).
- Narrow the usage/cost hide condition to isBedrockModelId() only
- Add enterprise alias pricing to ANTHROPIC_MODEL_PRICING
- Add isEnterpriseModelId() helper and readable label mapping
(opusplan → Claude Opus, sonnetplan → Claude Sonnet, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The upstream compact-layout bar format shows "(2h 30m / 5h)" for relative
time — the slash reads naturally as "duration / window". But for absolute
or both modes, this produces "(at 14:30 / 5h)" or "(2h 30m, at 14:30 / 5h)"
where the slash is incoherent.
Preserve upstream relative-mode behavior. Switch to the preposition form
(e.g. "resets at 14:30" / "resets in 2h 30m, at 14:30") when timeFormat
is absolute or both.
Two bugs caught in review:
1. Limit-reached path hardcoded t("format.resets") = "resets" for ALL
timeFormat modes, so relative mode (the default) produced "Limit reached
(resets 2h 30m)" instead of the correct "resets in 2h 30m". Applied the
same resetsKey selection logic used in formatUsageWindowPart to both
usage.ts and session-line.ts.
2. formatAbsolute hardcoded the English word "at", breaking zh locale:
t("format.resets") = "重置于" (resets at) + "at 14:30" = "重置于 at 14:30"
(doubled preposition). Added "format.at" i18n key (en: "at", zh: "" — zh
omits the prefix since its "format.resets" already encodes the preposition).
Also updates the render.test.js assertion that was written against the old
incorrect behavior.
Adds a `display.timeFormat` configuration option (`'relative'` | `'absolute'` | `'both'`,
default `'relative'`) that controls how usage-window reset timestamps are shown in the HUD.
- `relative` (default) – unchanged behavior: "resets in 2h 30m"
- `absolute` – wall-clock time: "resets at 14:30" (or "at Jan 5 14:30" for next-day resets)
- `both` – combined: "resets in 2h 30m, at 14:30"
Implementation:
- New shared `src/render/format-reset-time.ts` utility (locale-aware, eliminates
duplicate private implementations in usage.ts and session-line.ts)
- `src/config.ts`: `TimeFormatMode` type + `timeFormat` field with validation
- `src/render/lines/usage.ts` + `src/render/session-line.ts`: thread `timeFormat`
through `formatUsageWindowPart`; select correct i18n preposition
(`format.resets` vs `format.resetsIn`) when mode is `absolute`
- 18 new tests in `tests/format-reset-time.test.js`
Closes#432
On a fresh session Claude Code emits used_percentage=0 before any user
input, while current_usage already holds the real initial-context tokens
(system prompt, tools, memory files — ~9% on a 200k model). The HUD
was treating 0 as a valid native value and skipping the token-based
fallback, so the context bar stayed at 0% even though /context showed 9%.
Treat used_percentage=0 the same as null: fall through to the manual
calculation from current_usage. When tokens are present the bar now
reflects the true initial usage; when both are zero it still shows 0%.
Fixes#417
Adjust two test expectations to account for the trailing spaces
that paddedLabel() adds when aligning shorter labels (Usage, Weekly)
to the width of the longest label (Context = 7 chars).
When Context, Usage, and Weekly lines wrap to separate rows on narrow
terminals, their progress bars now align vertically. A shared
paddedLabel() helper pads each label with spaces to the maximum visual
width across the three labels, accounting for CJK double-width chars.
- Add src/render/lines/label-align.ts with paddedLabel() utility
- Update identity.ts and usage.ts to use paddedLabel()
- Add tests for English and Chinese label alignment
The output speed (`out: N tok/s`) only renders while stdin is actively
streaming and disappears once output ends. Placing it between git and
duration causes the surrounding elements (duration, cost) to reflow
horizontally every time speed appears or disappears — jarring visual
churn on every turn.
Moving speed to the end of the line (after cost, before customLine)
means the transient field only appends/disappears at the tail, leaving
all stable elements in place.
Applied to both renderProjectLine (expanded layout) and
renderSessionLine (compact layout) for consistency.
The macOS/Linux awk-based version sorting command uses '"'"' to nest
single quotes inside bash -c '...'. After JSON encoding/decoding in
settings.json, this quoting breaks on Windows Git Bash, causing a
silent syntax error that prevents the HUD statusline from starting.
Replace awk with sort -V (GNU version sort, included with Git for
Windows) in the Windows + Git Bash section, which avoids nested
single quotes entirely.
Fixes#326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>