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.
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).
getProviderLabel was string-matching `anthropic.claude-` in model IDs,
which false-positived on cross-region IDs like `us.anthropic.claude-sonnet-4-6`.
Now checks `CLAUDE_CODE_USE_BEDROCK=1` env var instead.
Fixes#466
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the hardcoded Anthropic pricing table and estimateSessionCost()
logic with a direct read of stdin.cost.total_cost_usd — the native field
Claude Code provides after each API response.
- Add cost.* fields to StdinData type
- Extract costUsd in index.ts and pass through RenderContext
- Simplify renderCostEstimate to read ctx.costUsd directly
- Rename i18n key label.estimatedCost → label.cost
- Update label to "Cost ($USD)" / "耗油量(美元)" (zh)
- Remove dead estimateSessionCost, pricing table, and related helpers
- Update tests to use costUsd; add index.test.js coverage for the field
- Update README to reflect native field behavior
Closes#380
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cover both rendering paths (expanded + compact) to verify that:
- modelFormat compact/short correctly strips context suffix and prefix
- modelOverride completely replaces the model name in the badge
- modelOverride takes precedence over modelFormat
- loadConfig structural test validates new display fields
- Fix detectLanguage() to follow POSIX priority: LC_ALL > LC_MESSAGES > LANG
- Fix Chinese format.resetsIn from broken wrap-around grammar to prefix form
- Fix loadConfig() to call mergeConfig({}) when no config file exists,
ensuring detectLanguage() runs for auto-detection
- Add setLanguage('en') guard to render.test.js for locale-independent tests
- Add dedicated i18n test suite (tests/i18n.test.js) covering t(),
detectLanguage(), and mergeConfig language handling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When both 5h and 7d usage windows are displayed, the 7d gauge had no
label prefix. This adds a dim-styled "Weekly" label (matching the
Context/Usage label style) and removes colons from usage window labels
for consistency with other HUD labels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: support 256-color and hex color values in config
Extends the colors config to accept 256-color indices (0-255) and hex
strings (#rrggbb) in addition to the existing named color presets.
This allows full theme customization without patching source files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: allow number type in color config validation test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a static `display.customLine` config field that renders a user-defined
phrase (max 80 chars) in Claude orange on the project line, joined with
the standard │ separator.
- config.ts: add customLine to HudConfig.display with validation
- colors.ts: add claudeOrange() using 256-color (38;5;208)
- project.ts: append customLine to expanded mode project line
- session-line.ts: append customLine to compact mode parts
- setup.md: add "Custom line" option to Step 4
- configure.md: add Q5 Custom Line to both Flow A and Flow B
* fix: render showSpeed and showDuration in expanded layout
These config options were only implemented in the compact layout
(renderSessionLine in session-line.ts). When using lineLayout: "expanded",
enabling display.showSpeed or display.showDuration had no effect.
This adds both options to renderProjectLine (the expanded layout's
project line), matching the compact layout behavior:
- showSpeed: output token speed (tok/s)
- showDuration: session duration timer
Fixes#221
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add renderProjectLine tests for showSpeed and showDuration
Address Copilot review feedback by adding test coverage for the
new expanded layout rendering of speed and duration:
- duration shown when showDuration is true
- duration omitted when showDuration is false
- speed code path doesn't crash when showSpeed is true
- speed omitted when showSpeed is false
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: cover expanded layout speed rendering
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* fix: clarify usage time format — show 'resets in' instead of ambiguous elapsed/total
Fixes#240
The format `(2h 43m / 5h)` was confusing because it mimics the common
`(elapsed / total)` pattern, but actually showed time remaining until
reset. Changed to `(resets in 2h 43m)` which is unambiguous.
Before: `Usage █░░░░░░░░░ 7% (2h 43m / 5h)`
After: `Usage █░░░░░░░░░ 7% (resets in 2h 43m)`
* test: cover usage reset wording
---------
Co-authored-by: d 🔹 <258577966+voidborne-d@users.noreply.github.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
The --extra-cmd feature only rendered extraLabel in compact mode via
renderSessionLine. In the default expanded layout, extraLabel was
collected but never passed to any render function.
Append extraLabel to the project line in expanded mode, consistent
with its placement on the session line in compact mode.
Fixes#242
* feat: show reset time for 7-day usage in text-only mode
- When usageBarEnabled is false, 7d usage now displays reset time,
- consistent with the existing 5h usage text-only behavior.
* test: cover text-mode 7-day reset countdown
---------
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* fix: resilient usage display under API rate limiting
The Anthropic usage API rate-limits to ~1 call per 5 minutes. With the
previous 60s cache TTL, 4 out of 5 API calls returned 429, causing the
HUD to permanently display "(429)" instead of actual usage data.
Three-layer fix:
- Increase cache TTL from 60s to 5 minutes to match rate limit window
- Preserve lastGoodData in cache across rate-limited periods so the HUD
always shows the best available data instead of errors
- Exponential backoff (60s→120s→240s→5min cap) with Retry-After header
support for consecutive 429 responses
Also show "syncing..." instead of raw HTTP status on first-run rate limit.
* Update usage-api.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: harden 429 cache fallback behavior
* test: stabilize usage cache suite after rebase
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* fix(context): scale autocompact buffer by raw usage to avoid inflated percentages at low context
Previously the buffered context percentage applied a flat 22.5% buffer
regardless of actual usage. This caused the HUD to show ~28% context
used immediately after /clear or at session start, when real usage was
only ~5%. The fix scales the buffer linearly: zero buffer at ≤5% raw
usage, ramping to full buffer at ≥50%, matching when autocompact
actually kicks in.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: harden autocompact buffer startup coverage
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* feat(config): add showSessionName toggle (default off)
Session name display from #155 is now opt-in via display.showSessionName
config. This addresses user feedback requesting the ability to hide the
session name. Added to setup onboarding and configure command flows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(docs): cover session-name default behavior
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* feat: add showProject config to hide project name from statusline
Adds `display.showProject` (default: true) to control whether the
project path is displayed. When set to false, the project name and
its associated git info are hidden from both compact and expanded
layouts.
* fix: keep git status visible when project name is hidden
---------
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>