Skip to content

v2.0.2: Fable 5 pricing, attribution & quota fixes, cost-composition charts - #29

Merged
Carl723000 merged 13 commits into
ClaudeCodeUsage:mainfrom
Carl723000:fix/adaptive-refresh-and-stale-quota
Jun 11, 2026
Merged

Carl723000 merged 13 commits into
ClaudeCodeUsage:mainfrom
Carl723000:fix/adaptive-refresh-and-stale-quota

Conversation

@Carl723000

Copy link
Copy Markdown
Collaborator

Patch release. All changes are backwards-compatible; new settings default to existing behaviour.

Added

  • Claude Fable 5 / Mythos 5 pricing; [1m] long-context model ids resolve to base pricing (also fixes proxy configs like deepseek-v4-pro[1m]).
  • Stacked cost-composition charts on Today (hourly), This-Month (daily) and All-Time (monthly) — each cost bar splits into input / output / cache-write / cache-read, with a Y-axis and reference lines.
  • Sessions tab "Session" column showing the conversation title (sortable), so same-project sessions are distinguishable.

Fixed

  • Quota stuck/stale or "only back after restart": expired windows roll to 0% and refetch; an expired in-memory token now re-reads ~/.claude/.credentials.json (which Claude Code keeps refreshing) before our own refresh; 429 cool-down cut from 5 min to 60 s; gentler /usage cadence (60 s active / 120 s idle). Quota-after-reset adapted from Fix: quota indicator (5h/wk %) gets stuck showing a stale value #24 (@nickearnshaw).
  • Usage not showing on first VS Code open (Usage percentage doesn't show on first open #26): status bar shows a loading state immediately; quota fetch is non-blocking.
  • "This project" undercounted / vanishing: attribution keys off the session's home project dir (not the per-record cwd, which wanders mid-session); shown even at $0.
  • Message count counts messages you actually typed (excludes API calls, /command echoes, interruption markers); token figures unchanged.
  • Per-metric chart Y-axis updates on metric switch; sub-agent/workflow logs attribute to their parent session/project; activity-aware ~8 s refresh during active runs; drill-down double-scrollbar and negative-UTC date-label fixes; F5 preLaunchTask (fix: correct preLaunchTask reference in launch.json (F5 fails) #22, @nickearnshaw).

Docs / project

Full detail: CHANGELOG [2.0.2].

Known issue #27 (v2.0.1 dashboard won't open) — webview was substantially reworked here; asking the reporter to verify on v2.0.2. macOS Keychain support (#28) scheduled for v2.0.3.

Co-Authored-By: Claude noreply@anthropic.com

Carl723000 added 13 commits June 9, 2026 12:36
Three related status-bar refresh fixes (problem reported: quota stuck at
a stale 100% after the 5h window reset; status bar not updating promptly
during ultracode runs).

1. Stale quota after reset (adapted from PR ClaudeCodeUsage#24 by @nickearnshaw):
   add liveWindows() in statusBar.ts. A window's utilization is only valid
   until its resets_at; once that passes the cached value is stale. We now
   drop expired windows before display and hide the indicator if nothing
   current remains, rather than rendering a value we can no longer trust.
   Bounds staleness to each window's period (<=5h / <=1 week) instead of
   forever.

2. Activity-aware cadence: track the last .jsonl write (lastActivityAt,
   updated by the recursive fs.watch). While active (a write in the last
   60s) the polling timer ticks every ~15s and the quota cache shrinks to
   20s, so high-consumption ultracode/workflow runs update promptly. When
   idle, both fall back to the user's interval (min 30s) / 120s. The auto
   refresh timer became self-rescheduling to support this.

3. Coalesce overlapping refreshes: instead of dropping a trigger that
   arrives mid-load (which starved updates while many sub-agent files were
   being written rapidly), set a pendingRefresh flag and run exactly one
   more refresh after the current finishes.
…onthly

The daily (This Month tab) and monthly (All Time tab) charts previously
showed a flat single-colour cost bar with no scale. They now:

- Render inside the gridded hc-wrap layout: a Y-axis (max / max-2 / 0) and
  two dashed reference lines, matching the hourly chart. This gives the
  "three reference levels" the user asked for.
- Render the cost metric as a stacked composition — input / output /
  cache-write / cache-read, same colours as the summary's Cost Composition
  (blue / orange / purple / green). Each segment's height is its share of
  that day's/month's cost, so a glance shows both total spend and where it
  went.

The metric switcher still works: switching to a token/message metric
re-renders single-colour bars (updateMainChart now rebuilds bar content
per metric from data attributes rather than only resizing). Cost segments
are pointer-events:none so clicking a bar still drills down to the
hourly / daily detail.

Implementation notes:
- Shared renderMainCostChart() backs both renderDailyChart and
  renderAllTimeChart.
- Bars carry the cost breakdown as data-cost-* attributes so the client
  can rebuild the stack on metric switch without a round-trip.
- The fixed-height .chart-container wrapper was removed for these two
  charts (hc-wrap is self-contained with its own scroll), avoiding a
  double scrollbar.
- README.md: the changelog links pointed to `changelog.md` (lowercase)
  but the file is `CHANGELOG.md` — broken on case-sensitive GitHub.
  Fixed both occurrences. Dropped the stale "v2 translations in 2.0.1"
  note.

- The five language READMEs were still v1-era content: old feature lists,
  old upstream jack21 screenshot links, inline v1 changelogs. Rewritten
  to v2:
  - en / zh-TW / ja / ko: concise editions — slogan, v2 screenshots
    (images/v2-*-en.png), feature list, install, key settings,
    troubleshooting (incl. cleanupPeriodDays + sub-agent note), and a
    pointer to the main README for full detail.
  - zh-CN: full translation of README.md (Chinese is the highest-traffic
    locale for this repo's README).

All language editions now carry the "coach in your status bar"
positioning and the "issues/PRs welcome" note.
…ue templates

- CLAUDE.md rewritten to the v2 architecture (advisor / claudeApiClient /
  adviceDemoSample modules, adaptive refresh, curl-based OAuth, automated
  release workflow) and the project's positioning + conventions.
- CLAUDE.local.md added for per-maintainer personal notes (gitignored and
  .vscodeignored — not committed, not packaged). Documents the local
  environment, working preferences, collaborators and roadmap.
- CONTRIBUTING.md added: scope, dev setup, PR checklist, the planned
  node:test direction (issue ClaudeCodeUsage#25), and the automated release flow.
- GitHub issue templates (bug report / feature request) added, both noting
  the project scope so requests land in-scope.
- CHANGELOG [2.0.2] entry covering the quota / refresh / chart fixes and
  the docs refresh.
…l, per-workspace session

Follow-ups from v2.0.2 RC testing:

- Today's hourly cost chart is now a stacked composition (input / output /
  cache-write / cache-read), matching the daily and monthly charts.

- The drill-down charts (daily under a month, hourly under a day) were
  still flat single-colour bars with no scale and day-number-only labels.
  They now use the same gridded layout (Y-axis + two reference lines) and
  stacked cost composition via a shared `griddedChart` client helper. The
  daily drill-down x-axis shows month/day instead of a bare day number.

- Expanding a detail now scrolls it into view. Clicking a bar at the top
  of a tab previously expanded a detail row far down the table that users
  never noticed.

- "Current session" in the status bar is now the single most-recent
  conversation scoped to this window's workspace, instead of a global
  5-hour aggregate across all projects. Different workspaces now show
  their own current-session cost; returns nothing if idle >5h so a stale
  session doesn't show as current.
…'this project today'

Final v2.0.2 RC fixes from testing:

- Chart Y-axis now updates per metric. The metric switcher left the
  reference-line labels stuck on the cost metric's units because the
  container holds two hc-yaxis elements (main chart + token-composition
  chart) — the 6-value query failed its `=== 3` guard. Now scoped to the
  main chart's own wrap.

- Quota no longer vanishes when a window resets. An expired window is
  rolled forward to 0% with its reset time advanced by whole periods
  (5h / 1 week), instead of being hidden. A forced refetch (bypassing the
  cache when an expired window is detected) replaces the 0% estimate with
  the real new-window value shortly after.

- Status bar secondary number changed from "current session" to
  "this project today" — today's cost for the current workspace. Both
  numbers are now midnight-stable (the old session figure vanished after
  5h idle and was identical across all windows because it aggregated the
  last 5h globally). New i18n key `workspaceToday` (6 languages); icon is
  $(folder). The per-workspace current-session figure is still computed
  for the webview. Adds ClaudeDataLoader.filterByWorkspace().
…de review)

Two correctness fixes from a self code-review of the v2.0.2 branch:

- startAutoRefresh's self-rescheduling timer could spawn duplicate chains:
  if it ran again (e.g. on a config change) while a tick's
  refreshData().finally(tick) was mid-flight, the orphaned chain would
  keep its own setTimeout alive alongside the new one, multiplying the
  refresh cadence over time. A generation token now stops any superseded
  chain.

- liveWindows roll-to-0% (so a reset window doesn't vanish) is now bounded:
  a window that expired more than ~2 periods ago is dropped instead of
  shown at a fabricated 0%. This avoids implying "full quota available"
  when the OAuth fetch has actually been failing for a long time (expired
  creds, offline). A genuine recent reset still shows 0% and is corrected
  by the forced refetch within a TTL.
…ent session attribution

Batch of fixes from v2.0.2 RC round 3 + new-model support:

Pricing
- Claude Fable 5 / Mythos 5 added ($10/$50, cache write $12.50, cache
  read $1 per MTok — verified 2026-06-09 against the official pricing
  page). Family fallback maps unknown fable/mythos snapshots to this tier.
- getModelPricing now strips a trailing "[1m]" long-context marker before
  lookup (1M-context variants bill at standard rates). This also fixes
  pricing for users whose proxy config pins e.g. "deepseek-v4-pro[1m]".

Status bar
- "This project" no longer disappears at $0: the figure shows whenever a
  workspace is open, including $0.00. Hiding at zero read as a bug.
- filterByWorkspace now also matches records that only carry the
  dash-encoded project directory name (records without a cwd field):
  the workspace path is encoded the same way Claude Code does
  (D:\Jiaming\My_Proj → d--Jiaming-My-Proj) and compared directly.
  Previously such records counted in the global total but never in the
  per-project figure — part of the "project sums don't add up" report.

Session attribution (pre-v2.1 hardening)
- parseSessionInfo now resolves files nested under a session directory
  (subagents/workflows/*/agent-*.jsonl) to their parent session id and
  real project directory. They previously got a 'wf_xxx' pseudo-project
  and 'agent-xxx' session ids, fragmenting Sessions/Projects aggregation
  — the other part of the mismatch report, and groundwork for the v2.1
  workflow attribution.

Sessions tab
- New sortable "Session" column showing the conversation title (the name
  `claude --resume` shows, harvested from each session's summary log
  line), falling back to the session id. Same-project sessions are now
  distinguishable. i18n key sessionTitle added for all six languages.

Drill-down charts
- Removed the fixed-height chart-container wrapper around the gridded
  drill-down charts (double scrollbar).
- Date labels/tooltips parse 'YYYY-MM-DD' textually instead of
  new Date(...) UTC parsing, which shifted labels a day back in
  negative-UTC timezones.

Cleanup
- getCurrentSessionData reuses filterByWorkspace (drops duplicate norm).
Full implementation spec for v2.1.0 at docs/V2.1-WORKFLOW-SPEC.md,
written to be handed to a fresh Claude Code session for end-to-end
implementation. Covers: verified on-disk data formats for workflow /
sub-agent logs, the five phases (advice reliability fix, loader data
model, Workflows tab, thinking share + quota guard, per-skill stats,
advice upgrade), acceptance criteria per phase, conventions, and real
verification data locations. docs/ excluded from the .vsix.
…e count, startup visibility

Root-caused with on-disk diagnostics this round:

Workspace attribution ("This project" undercount)
- A single conversation's per-record cwd wanders as work moves between
  folders (observed: one session split 10/71 across two cwds), so
  cwd-based matching fragmented the per-project figure ($9.51 of $36.78).
  Records now carry _projectDirEncoded — the encoded project directory
  the session file lives in (= where the session was started) — and
  filterByWorkspace matches that first, attributing whole conversations
  to their workspace. cwd matching remains as a secondary net.
  Verified: workspace-today now equals global-today when all of today's
  work happened in one workspace.

Session titles
- Titles were showing raw uuids: current Claude Code stores titles as
  `ai-title` / `custom-title` jsonl lines, not the legacy `summary` type.
  Harvest both (custom beats AI; summary kept for old logs). Verified
  against real data — custom titles like 【CC usage插件】… now display.

Messages = what the user typed
- messageCount previously counted API calls (one conversation showed 33
  "messages" for 5 actual prompts). The loader now synthesizes zero-usage
  marker records for genuine user prompts (excluding meta/command lines,
  sidechain dispatches, and anything in sub-agent logs) and messageCount
  counts only those. Token figures are unchanged. Sessions with spend but
  no typed prompt in scope remain listed.

Startup visibility (also reported on GitHub: "usage not showing the
first time I open VS Code")
- The cost item rendered empty text until the first full refresh, which
  was blocked behind an awaited OAuth quota fetch (curl; seconds or a
  failure on a cold network). The status bar now shows a loading state
  from t=0, the quota fetch is fire-and-forget so local figures land
  immediately, and a failed first quota fetch retries up to 3× with
  backoff instead of waiting for the next tick.

Cadence
- Active refresh tick 15s → 8s, active quota TTL 20s → 15s (Fable 5
  consumption moves fast enough that 15s read as laggy).

Community standards
- PULL_REQUEST_TEMPLATE.md (structured for fast review and future
  automated triage), question.yml issue template.

Docs
- docs/V2.2-AUTOMATION-SPEC.md: human-gated AI issue/PR handling spec
  (mention-driven claude-code-action + label/draft-queue triage where
  merging a triage PR is the explicit authorization to post).
…command echoes from message count

Two issues from RC testing:

Quota "only comes back after I restart VS Code"
- Root cause: when the in-memory OAuth token expired and our own refresh
  failed, getValidCredentials never re-read ~/.claude/.credentials.json —
  which Claude Code itself keeps refreshing. So a stale cached token stuck
  until the extension host restarted. Now an expired in-memory token
  triggers a disk re-read first (Claude Code has very likely already
  rotated it), falling back to our refresh only if the disk copy is also
  expired.
- The 429 cool-down was a flat 5 minutes, so a single rate-limit looked
  like a multi-minute outage. Cut to 60 s.
- The previous round's aggressive cadence likely caused those 429s:
  quota TTL is now 60 s active / 120 s idle (was 15 s) and the cold-start
  retry is a single attempt, not a storm. Local cost still refreshes
  every ~8 s via the fs watcher — only the slow-moving quota % is
  throttled, which is what keeps /usage under its rate limit.

Message count inflated by system markers
- "Messages" counted Claude Code's own user-line markers: interruption
  notices ([Request interrupted by user]) and slash-command echoes
  (<command-name>/model…, <local-command-stdout>…). Excluded via
  isSyntheticUserText. Example session: 106 → 86 (matches the genuine
  typed-prompt count).
@Carl723000
Carl723000 merged commit fae6d4b into ClaudeCodeUsage:main Jun 11, 2026
1 check passed
@Carl723000
Carl723000 deleted the fix/adaptive-refresh-and-stale-quota branch August 24, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant