* feat(display): show auth method and logged-in account on the first line
Adds an opt-in segment at the end of the first HUD line showing the
subscription plan of the current login (e.g. "Claude Max 20x") and the
logged-in account, derived from the oauthAccount block that Claude Code
persists in {CLAUDE_CONFIG_DIR}.json.
New display options (all default off):
- display.showAuth: plan label, e.g. "Claude Max 20x" / "API Key"
- display.showAuthUser: email local part (fallback: displayName)
- display.authUserLength: truncation length, 0 = full (default 8)
* fix(auth): strip whole ANSI sequences via shared sanitizeDisplayText helper
Replaces the local codepoint-class regex with the existing
sanitizeDisplayText() util so CSI/OSC sequences are removed entirely
instead of leaving parameter bytes behind (evil\x1b[31m@… -> evil@…),
matching how other externally-sourced display text is sanitized.
* fix(auth): prefer active API key over stale OAuth profile
---------
Co-authored-by: BBleae <yukinoshita.reimu@gmail.com>
Co-authored-by: Jarrod Watts <35651410+jarrodwatts@users.noreply.github.com>
* fix: correct effort suffix placement and guard check inconsistencies
the effort level tag (like "max") was showing up after the provider name
instead of after the model — so you'd see "Opus | Bedrock max" when it
should be "Opus max | Bedrock". small thing but it looked wrong.
also fixed a few spots where opt-in features (showDuration, showConfigCounts)
were using !== false checks instead of === true, which could show them
unexpectedly if the config object was partially constructed.
cleaned up duplicate debug namespaces too — two modules were both using
'context' and two were using 'config', which made debug output confusing.
* test: cover effort and opt-in render guards
---------
Co-authored-by: Jarrod Watts <jarrodwatts@users.noreply.github.com>
Add opt-in provider label placement for custom proxy workflows while preserving the existing default model badge order. Compact and expanded layouts now share the same badge formatter.
Closes#620
Update Opus 4.5+ local cost estimates to the official standard Anthropic rate of $5/M input and $25/M output while keeping older Opus 4.0/4.1 estimates on $15/M input and $75/M output. Adds focused coverage for Opus 4.5/4.6, Bedrock-style model IDs, and the older fallback. Verified locally with npm ci, npm run build, and node --test tests/core.test.js tests/render.test.js. GitHub CI passed on Node 18 and 20. Fixes#622. Supersedes #624.
令牌 is the established Chinese rendering of "token" in the
authentication/security sense only (access token → 访问令牌). For the
NLP/LLM sense — the unit of text shown by the HUD's token counters —
the standard term is 词元, officially designated as the Chinese name
for the AI-domain term "token" by the China National Committee for
Terms in Sciences and Technologies on 2026-03-25.
dist/ is intentionally untouched; it is auto-compiled by the
build-dist workflow.
Previously, external-snapshot balance_label was shown only when stdin
rate_limits were absent (mutually exclusive). Rate-limit windows (5h/7d)
and a prepaid/metered dollar balance are complementary data, so both
should be visible when available.
Changes:
- index.ts: when stdin provides rate_limits, also read the external
snapshot for a balance_label (only when externalUsagePath is set)
and merge it onto usageData
- session-line.ts: render balance_label as an additive segment after
the windows block rather than as an exclusive leading branch;
standalone balance (no window data) preserves existing behaviour
- tests/render.test.js: add test for combined windows + balance display
Backward-compatible: users without externalUsagePath configured see
no behaviour change (no extra file read, no extra segment).
Addresses review feedback from #573:
- Sanitize both `ctx.transcript.advisorModel` and `display.advisorOverride`
through the existing `sanitizeDisplayText` helper before rendering so
ANSI ESC, OSC, C0/C1 control, and bidi sequences cannot reach the
terminal. Defence-in-depth: re-sanitize the prettified result too.
- Cap advisor display at 64 chars at the render layer
(MAX_ADVISOR_DISPLAY_LEN), regardless of source.
- In the transcript parser, capture `advisorModel` only from records
whose `type === 'assistant'` (matching the documented schema) and
hard-cap the captured value at 64 chars (ADVISOR_MODEL_MAX_LEN) so a
malformed log cannot persist an oversized value through the JSON
cache. Bumps TRANSCRIPT_CACHE_VERSION 6 → 7. The cache deserializer
also re-applies the cap as belt-and-braces against legacy entries.
- Add 9 new tests covering: CSI/OSC stripping (ANSI ESC + BEL + DEL
bytes), bidi mark stripping (RLO/PDF), oversize transcript truncation,
oversize override truncation (display-layer), sanitize-collapses-to-
empty fallback, non-assistant record rejection (user / custom-title /
system), inline placement in expanded layout (renderProjectLine), and
inline placement in compact layout (renderSessionLine).
- Document `display.showAdvisor` and `display.advisorOverride` in
README.md and README.zh.md configuration tables.
`npm test`: 637 / 639 pass + 1 skip + 1 pre-existing unrelated failure
(`countConfigs cache: miss on nested rules additions`, fails identically
on `main`).
Surfaces the model configured via Claude Code's `/advisor` command so it
sits inline on the project line:
[Opus 4.7 (1M context)] │ AthenaKB git:(main*) │ Advisor: Opus 4.7
Context ██░░░░░░░░ 19%
## How it works
Claude Code stamps an `advisorModel` field onto every assistant record
in the session transcript when `/advisor` is configured. The transcript
parser already walks every line for tool / agent / todo state, so this
just captures the latest non-empty `advisorModel` into the existing
`TranscriptData` shape with no extra IO.
`renderProjectLine` then appends the prettified label (e.g.
`claude-opus-4-7` → `Opus 4.7`) as another part on the same row,
respecting the existing ` │ ` separator and ANSI handling. A
`display.showAdvisor` boolean (default false) gates the whole block;
`display.advisorOverride` lets users force a custom label if needed.
## What's included
- `TranscriptData.advisorModel` field + parser capture
- TRANSCRIPT_CACHE_VERSION bumped 5 → 6 to invalidate caches that
predate the new field
- `display.showAdvisor` / `display.advisorOverride` config + validation
- `renderProjectLine` integration + `prettifyAdvisorId` helper that
handles both canonical IDs and short aliases
- i18n labels for en (`Advisor`) and zh-Hans (`顾问`)
- `configure.md` Element Mapping + Turn Off/On flow entries
- 15 new tests covering ID prettification, render gating, transcript
capture (latest-wins, empty-string-ignored, missing-field fallback),
and config validation
## Notes
- `dist/` is intentionally untouched per CONTRIBUTING.md
- One pre-existing failure remains in `countConfigs cache: miss on
nested rules additions` — it fails identically on main without any
of my changes
Allow users to customize the characters used in progress bars via
colors.barFilled and colors.barEmpty. Defaults to the existing
block characters (█/░) so behavior is unchanged without configuration.
The settings live under colors.* rather than display.* because the
bar rendering functions already receive the colors object — this
avoids changing any call signatures.
Co-authored-by: Claude <noreply@anthropic.com>
The speed cache was stored in a single global .speed-cache.json file shared
by every concurrent Claude Code session. Because output_tokens in stdin is
session-local, comparing the current frame against a previous value written
by another session produced bogus tok/s readings on idle terminals whenever
another terminal was actively streaming, and poisoned the source terminal's
cache on reset.
Scope the cache by sha256 of the resolved transcript_path, matching the
approach in context-cache.ts. Skip speed tracking when transcript_path is
absent so we never fall back to a cross-session cache. Remove the legacy
global file opportunistically.
Fixes#495
Fix render width fallback handling, keep usage visible for Enterprise model aliases while still hiding Bedrock usage, and only generate branch hyperlinks for GitHub remotes.\n\nMaintainer review covered security, generated artifacts, subprocess/path/link handling, width-sensitive rendering regressions, and maintainability.\n\nTests: npm test (486 passed, 1 skipped)
* feat(context): make colour thresholds configurable
The context bar's warning and critical colours switch at hard-coded
70% and 85%. Those are reasonable defaults for a "compact is imminent"
signal, but workflows with an externally-triggered wrap-up step
(e.g. a pre-compaction hook that itself consumes tokens before
summarisation) need to start de-escalating earlier to leave headroom
for the wrap-up to complete.
Adds two config keys mirroring the existing pushWarningThreshold /
pushCriticalThreshold pattern in gitStatus:
display.contextWarningThreshold (default: 70)
display.contextCriticalThreshold (default: 85)
Defaults are unchanged, so existing installs see no behaviour
difference. Users who want earlier warnings can now set e.g.
{ contextWarningThreshold: 30, contextCriticalThreshold: 50 }.
Values are clamped to 0-100; non-numeric or non-finite values fall
back to the defaults. No ordering invariant is enforced (warning
above critical is allowed — the warning branch simply never fires).
Threaded through getContextColor and coloredBar via a new optional
ContextThresholds parameter; prompt-cache.ts uses getContextColor(0)
to force the "healthy" colour and is unaffected.
* fix(context): extend contextCriticalThreshold to token-breakdown trigger
The previous commit made the context bar's warning and critical
colour thresholds configurable. The token-breakdown detail line
(e.g. `(in: 45k, cache: 12k)`) also had a hard-coded `percent >= 85`
check in both session-line.ts and identity.ts, unchanged by that
commit — which meant a user setting contextCriticalThreshold to e.g.
50 would see the bar turn red at 50% but the detail only appear at
85%. Two different meanings for "critical" in the same UI.
Binds both triggers to `display?.contextCriticalThreshold ?? 85`,
so the single threshold controls both the colour and the detail.
Tests: breakdown shown at 55% when threshold=50; suppressed at 90%
when threshold=95. Mirrored for both renderSessionLine and
renderIdentityLine.
Docs: new keys added to commands/configure.md's "advanced settings
preserved when saving but not edited by this guided flow" list,
alongside usageThreshold and environmentThreshold.
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>