Skip to content

feat: V2.2 — usage share card, conversation viewer, insights suite, heatmap & more - #68

Merged
Carl723000 merged 84 commits into
ClaudeCodeUsage:mainfrom
Carl723000:feat/v2.2-share-and-polish
Jul 6, 2026
Merged

Carl723000 merged 84 commits into
ClaudeCodeUsage:mainfrom
Carl723000:feat/v2.2-share-and-polish

Conversation

@Carl723000

Copy link
Copy Markdown
Collaborator

The V2.2 feature release. Highlights (full detail in CHANGELOG.md):

New surfaces

  • Usage share card — themed, configurable one-page SVG (range × scope × metrics), zh 万/亿 units.
  • Read-only conversation viewer (Sessions tab, default on) — re-read a past session without spending model context; Markdown-rendered answers, thinking/tools behind toggles, round-based cap.
  • Token heatmap (opt-in) — GitHub-style yearly heatmap on the All tab + an "Export/Publish to GitHub profile" SVG.
  • Experimental insights (opt-in, Content tab) — cache-churn bill, cache warmth by model, big one-shot turns, active hours, skill ROI.

Sessions / data

  • "Active" column — idle-capped hands-on time (distinct from the first→last span).
  • Live-refresh delay control (Off / 1 / 2 / 5 / 10 / 20 / 30s) replacing the on/off toggle — local file watching only, quota fetch throttled separately.
  • Timezone-aware bucketing (day/month/hour all key off the configured zone) + full UTC-offset dropdown.
  • Cache-write cost by TTL (1h = 2× vs 5m = 1.25×) — @zeyutang, fix: timezone bucketing and cache-write cost accuracy #62.

Housekeeping

  • Merged session resume+delete into one opt-in (enableSessionActions, default off); read-only viewer defaults on.
  • 7-language i18n for the new surfaces; settings-label localisation synced.
  • 114 tests pass (new pure modules: conversationLog, miniMarkdown, + insight builders).

Also folds in the community fixes merged since 2.1.1 (#50 Sonnet-5 window, #62 cache-TTL, #63 dep cleanup).

Carl723000 and others added 30 commits June 29, 2026 11:33
- CHANGELOG: add [2.2.0] — Unreleased; date [2.1.0] — 2026-06-26; add the
  missing [2.0.3] maintenance section (macOS Keychain, node:test, issue
  templates, CI hardening, release workflow).
- package.json: repository / bugs / homepage now point at the org
  (ClaudeCodeUsage/ClaudeCodeUsage), not jack21.

Co-Authored-By: Claude <noreply@anthropic.com>
New setting (default 1, 0–2) controlling only compact token rendering (1.2M /
345.6K), separate from cost decimalPlaces; full integer counts are unaffected.
Wired through I18n.formatTokensCompact and the formatNumber compact path, the
settings catalog + SETTINGS_I18N (5 locales), ExtensionConfig and config apply.
7 new node:test cases (0/1/2 places, K/M/B, integer pass-through, clamp).

Co-Authored-By: Claude <noreply@anthropic.com>
Status bar stays clean — default '5h 6% · wk 1%' (space, middot), not the dense
'5h:6%:4.8h | wk:1%:1.6d'. Two opt-in settings (both default off):
- showResetInStatusBar → '5h 6% ↻4.8h | wk 1% ↻1.6d' (compact countdown, bar sep)
- quotaFiveHourOnly → show only the 5h window
Full reset times always remain in the tooltip. Extracted a pure, dependency-free
src/quotaFormat.ts (formatQuotaStatusText / compactReset / worstShownUtilisation)
so it's unit-tested without vscode; statusBar.updateQuota now uses it. Catalog +
SETTINGS_I18N (5 locales) + config wiring. 8 new node:test cases.

Co-Authored-By: Claude <noreply@anthropic.com>
…ardRefresh

Double-negative 'Pause dashboard auto-refresh' becomes the positive
'Dashboard auto-refresh' (key dashboardAutoRefresh, default true). One-shot
SettingsStore.migrateDashboardAutoRefresh inverts any old pauseDashboardRefresh
value (globalState or settings.json) — true→false, false/undefined→true — behind
its own migration flag so it runs even post-v1-migration. All consumers
(extension refresh gating, webview body auto-off class + toggle handler) and
SETTINGS_I18N (5 locales) updated. Compile clean; 26/26 node:test green.

Co-Authored-By: Claude <noreply@anthropic.com>
Tested, dependency-free foundations for the two big V2.2 features; the webview
rendering + PNG export + heatmap cells will build on these in follow-up PRs.

- src/shareCard.ts (Usage Share Card / 用量卡片): totalTokens, cacheSharePct,
  modelFamily (no version exposed), selectShareBadge (deterministic, local rules:
  Context Marathoner / Cache Saver / Token Sprinter / Workflow Pilot / Steady
  Builder), buildShareCardData (privacy redaction — project name OFF by default,
  no room in the data shape for paths/ids/prompts), DEFAULT_SECTIONS,
  shareCardFilename.
- src/heatmap.ts: daysInMonth, intensityBucket (0..4), buildMonthHeatmap (zero-
  fills every day, tokens/cost/sessions metric switch).
- 11 new node:test cases (Phase 5.8 + 6.4). 37/37 green.

Co-Authored-By: Claude <noreply@anthropic.com>
- docs/V2.2.md: what shipped in 2.2 (status-legended), the Usage Share Card
  design + enforced privacy model, the token heatmap design, the settings
  changes, session/quota status, the contributor/PR credit policy, and the
  planning items (advice 'new session/clear' nudge, Optimizer opt-in file
  reading, conversation export, subscription sharing, Codex adapter, GitHub
  profile heatmap).
- docs/V2.3-achievements.md: SPEC ONLY (no V2.2 code) — positioning, privacy,
  the full achievement catalogue (token/session/prompt/workflow/model/plugin/
  hidden), levels, anti-gaming, community roadmap, the icon-prompt template,
  milestones, and the GitHub-profile sharing plan.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Fold the public roadmap (docs/V2.2.md) and the two local working specs
(V2.2-FEATURES-SPEC.md, V2.2-AUTOMATION-SPEC.md) into a single gitignored
master, docs/V2.2-SPEC.md (+ a zh-CN mirror for review), so the whole V2.2
plan can be handed to one execution pass. Drop the CHANGELOG pointer to the
now-removed public roadmap; the Added/Changed entries already record what
actually shipped in 2.2.0.
Brings the released 2.1.1 line (sessions/ClaudeCodeUsage#43, monthly-cost/ClaudeCodeUsage#41, pricing/ClaudeCodeUsage#46,
account-switch/ClaudeCodeUsage#45, pt-BR/ClaudeCodeUsage#48) into the V2.2 branch and keeps the V2.2-unique
work (tokenDecimalPlaces, dashboardAutoRefresh, share-card + heatmap cores).
Took main's shipped versions of the overlapping quota settings (the clean
status-bar format already landed via ClaudeCodeUsage#43) and dropped the branch's now-redundant
duplicates; kept the accurate clean-format setting labels/help. CHANGELOG keeps
[2.2.0] on top of [2.1.1]. docs/ now fully gitignored.

compile clean; node --test 42/42.

Co-Authored-By: Claude <noreply@anthropic.com>
When a request errors, Claude Code retries and re-logs the same user prompt,
so an identical prompt can appear several times seconds apart around a
system:api_error record — inflating "Messages". Dedupe identical prompts that
recur within a short window (retry re-logs); genuine re-sends minutes/hours
later still count. Logic isolated in a pure, unit-tested module.

Verified on real sessions: removes only true retry re-logs, keeps repeats.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds a cache hit rate (cacheRead / input-side tokens) column to the All-time
monthly table, the This-month daily table, and both expanded drill-downs
(month→days, day→hours), so cache efficiency is readable per row. Reuses the
existing cacheHitRate/formatPercent helpers server-side and a small cacheHitPct
helper client-side; detail-row colspans bumped 8→9.

Co-Authored-By: Claude <noreply@anthropic.com>
Bucketing: the month/day breakdowns mixed a UTC day key with a local month
boundary, so a record just after local midnight on the 1st was filed under the
previous month's last day (visible as a stray "30th" inside This-Month). Day
and month keys now both derive from the configured timezone (empty = system)
via a pure, unit-tested dateKeys module.

Table scroll (2b): number cells no longer wrap — compact k/M numbers fit the
panel with no horizontal scrollbar; full integer numbers overflow so only the
table scrolls, while the daily bar chart keeps its own independent scroll.

Co-Authored-By: Claude <noreply@anthropic.com>
The All-time Token-composition bars are now clickable (each is a month): a
click expands that month's detail — which now includes a per-day composition
chart next to the daily chart and table — so the input/output/cache split is
readable day by day. Reuses the existing month-detail round-trip
(toggleMonthlyDetail → getDailyData), with a small client-side composition
renderer mirroring the server one.

Co-Authored-By: Claude <noreply@anthropic.com>
pt-BR shipped in 2.1.1 (ClaudeCodeUsage#48) with the strings, package.json enum and
SupportedLanguage type, but was missing from the dashboard language dropdown
(settings.ts enumValues) and every README's UI-language list — so users
couldn't actually pick it. Added it in all those places and noted it in
CLAUDE.md (which also flags that de-DE strings exist but are exposed nowhere).

Co-Authored-By: Claude <noreply@anthropic.com>
Pure, unit-tested heatmapSvg module: lays a calendar year of daily usage
(Jan 1 → today, no future padding, GitHub current-year style) into a
contribution grid and renders a self-contained SVG — Claude-orange intensity
ramp, title row (no month-label overlap), month + weekday labels, Less/More
legend, a bottom-left source watermark, per-day tooltips — for a GitHub profile
README. Not wired to a command yet; a real-data preview was generated.

Co-Authored-By: Claude <noreply@anthropic.com>
Pure, unit-tested heatmapSvg module for a GitHub profile README: trailing ~year
ending today (GitHub's default view, no future padding), Claude-orange intensity
ramp, a top-left summary ("5.3B tokens in Claude Code · 2026"), GitHub-style
per-day tooltips ("1.2M tokens on June 18th"), month + weekday labels, Less/More
legend, and a bottom-left source watermark. Not wired to a command yet.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds "Claude Code Usage: Export Token Heatmap (GitHub style SVG)" — builds a
per-day usage map (timezone-aware, via getDailyUsageMap) and writes the
contribution-graph SVG to a chosen file, offering to copy the Markdown embed
snippet for a GitHub profile README. Command-palette accessible.

Co-Authored-By: Claude <noreply@anthropic.com>
…fault off)

Adds a showHeatmap setting (default off). When on, the All tab shows a
GitHub-style yearly token heatmap at the top, built from allRecords via
getDailyUsageMap + renderHeatmapSvg. Inline SVG, so per-day hover tooltips work
in the dashboard (unlike GitHub's image-sanitised READMEs). Mainly a shareable
re-view of existing data, hence opt-in.

Co-Authored-By: Claude <noreply@anthropic.com>
…essages

Verifying the Messages count on real logs surfaced ~5 counted "prompts" that
were actually Claude Code's auto-injected "This session is being continued from
a previous conversation…" compaction summary (a user-role message the user never
typed). isSyntheticUserText now drops it, alongside interrupted-request and
slash-command echoes. (Tool-result user messages were already excluded.)

Co-Authored-By: Claude <noreply@anthropic.com>
)

The reporter suggested a dropdown of valid zones — the right fix, since it makes
an invalid value impossible to enter. The Timezone setting is now an enum
populated from Intl.supportedValuesOf('timeZone') ('' = system default). Kept a
validation guard in I18n.setTimezone as belt-and-suspenders for old synced
configs that already hold a bad hand-typed value (which otherwise made Intl
throw and crashed the dashboard). Also the explicit claude-sonnet-5 pricing
entry. Unit-tested.

Co-Authored-By: Claude <noreply@anthropic.com>
Shows a single dismissible notification the first time a new major.minor runs,
pointing at the dashboard — so users find new features, including the opt-in
default-off ones they'd otherwise never notice. Keyed by major.minor in
globalState (patch releases don't re-nag); skipped on fresh installs.

Co-Authored-By: Claude <noreply@anthropic.com>
New showEfficiency setting (default off — not everyone wants cost metrics).
When on, the Content tab gains a "Top 10 costliest conversations" panel: rows
ranked by cost, each expandable (native <details>, no JS) to its tokens,
cache-hit rate, top model and project. Same toggle will gate the
cost-per-message + cache-savings chips on Today/projects (next).

Co-Authored-By: Claude <noreply@anthropic.com>
…avings

Under the usage summary (Today / Month / All), gated by showEfficiency: an exact
"cost per message" chip (totalCost ÷ messages) and a "cache savings" chip
(cacheRead tokens × the per-model input−cacheRead price gap — what caching
actually saved vs. full input price). Off by default.

Co-Authored-By: Claude <noreply@anthropic.com>
…ort command

Batch 6 (V2.2 share card) — make the tested shareCard.ts core visible/exportable.

- shareCardSvg.ts: renderShareCardSvg(ShareCardData) -> SVG. No DOM, no
  html-to-image dep, no CSP concerns. Landscape 1200x630 social-card layout:
  header, big token hero (falls back to cost/sessions), up to four stat tiles,
  a per-day rhythm strip, badge pill, and watermark. Only draws fields present
  in ShareCardData, so privacy stays enforced by the type's shape.
- ClaudeDataLoader.buildShareInput(records, range): aggregate inputs for
  today / last 7 days / this month, timezone-bucketed to match the dashboard.
  Returns only aggregate numbers (no records, no identifiers).
- extension.ts: "Export Usage Share Card (SVG)" command — pick range, save,
  and open for review.
- 8 renderer tests (well-formed output, hero fallback, omitted sections,
  tiles/badge/rhythm, XSS-escaping, watermark toggle). 75/75 pass.

Co-Authored-By: Claude <noreply@anthropic.com>
Per spec the cost/message + cache-savings chips belong on Today (and
per-project), not on the Month / All-time summaries. renderUsageData now
takes an { efficiency } opt and only Today passes it, so the chips no longer
leak onto the other two scopes. Still opt-in via showEfficiency.

Co-Authored-By: Claude <noreply@anthropic.com>
Completes the "Today + projects" efficiency surfacing. Projects is a table,
so per-project cost-per-message reads better as a column than a summary chip.
Gated by showEfficiency (off by default); shows "—" when a project has no
counted messages. Non-sortable column — sortTable() reads data-sort-* row
attributes, so inserting it doesn't disturb the other columns' sorting.

Co-Authored-By: Claude <noreply@anthropic.com>
… Yh, session-delete opt-in, whats-new preview

Batch of the smaller items from Carl's review:

- Efficiency chips: add "Tokens / message"; show on Today AND Month AND
  All-time again (removed the Today-only scoping). Projects keeps its column.
- Timezone: trimmed the ~400-zone dropdown to a curated common set, each
  labelled with its live (DST-aware) UTC offset, e.g. "(UTC+08:00) Shanghai".
  Settings enum renderer now keeps a stored-but-uncurated value selectable.
- Quota tooltip: weekly reset countdown now "4d 12h" instead of "4.5d"
  (statusBar.formatCountdown); the compact status-bar form keeps "4.5d".
- Session delete: gated behind new opt-in "enableSessionDelete" (off by
  default) — it touches local history files, so it shouldn't be on for
  everyone. Resume tooltip now explains what resume does (EN/zh-CN/zh-TW).
- What's-new: extracted showWhatsNew(); added "Preview What's New" command so
  it's testable (a fresh F5 install otherwise just sets the baseline silently).

Compile clean, 75/75 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
The old panel just re-ranked sessions (a dupe of the Sessions tab). Carl wants
the Content tab's version to fit that tab's theme (AI advice / optimizer):
rank individual assistant turns and let each expand to explain itself.

- getCostliestMessages(records, limit): walks each session in timestamp order,
  attaches the preceding user prompt, and keeps the top-N billed turns by cost
  (bounded insertion). Each carries the full model id, the authoritative
  skill/plugin attribution, the 4 token types, cost, prompt, project.
- Store a truncated _promptText (300 chars) on the synthetic user-prompt
  records so the panel can show what triggered an expensive turn.
- Webview: renderCostliestMessages() — summary row = rank + prompt + cost;
  expands to the prompt (blockquote), model, skill, token breakdown, project.
  Precomputed in the extension and passed in (not re-walked per re-render).

Verified on real data (8855 records): top-10 with prompts + full model ids
(fable-5 / opus-4-8 / opus-4-7) attach correctly.

Co-Authored-By: Claude <noreply@anthropic.com>
…mposition, QR, full model, peak)

Addresses Carl's share-card review:
- Discoverable: an always-visible "Share card" panel on the All tab with an
  inline, responsive preview + "Export as SVG…" button (the command alone was
  unfindable). Export now matches the preview (composition on).
- More metrics: a token-composition stacked bar (the four billed token types)
  with a legend — off in DEFAULT_SECTIONS but on in the dashboard/export.
- Bar scale: the daily-rhythm strip now has a baseline, a peak gridline and a
  "peak <N>" label so the bars carry a scale.
- Full model name: prettyModelName() → "Opus 4.8" (not just "Opus"); the card
  shows the specific model.
- Traffic (引流): a real QR to the upstream repo bottom-right, wrapped in a
  link + "★ Star us on GitHub". QR is a static embedded asset (generated once
  with `qrcode`, then uninstalled — zero runtime deps). See shareCardQr.ts.
- Canvas grew to 1200×760 to fit the new blocks; layout verified overlap-free.

+6 tests (QR link, full model, composition bar, peak label, prettyModelName).
80/80 pass, compile clean.

Co-Authored-By: Claude <noreply@anthropic.com>
Carl723000 and others added 25 commits July 4, 2026 01:45
… + crisper copy

The cache-churn card read as a wall of text. Split it: a "💡" actionable
takeaway line (recoverable — keep momentum in the warm window), then the "a
switch can still be worth it" caveat as a smaller, top-bordered note on its own
line. Pills clarified ($ · cause · count). Reads as an insight now, not a
paragraph.

Co-Authored-By: Claude <noreply@anthropic.com>
…cache analyses

Second insight card (Carl's top pick — cache is the key cost lever): cache hit
rate per model, with the model family's nominal provider and a volume bar.
cacheStatsByModel() aggregates read ÷ input-side per model over 30 days. Real
data shows opus-4-8 97% / deepseek-v4-pro 98% / fable 96% etc. — so you can see
which models actually serve from cache. Tip: favour low-hit models for short,
self-contained tasks. (True cross-PROVIDER comparison needs pooled cross-user
data — reserved via the dataContribution scaffold.)

Also: the cache analyses (TTL / churn / by-model) now recompute at most WEEKLY
(analysisCache), not every render — Carl's call; they move slowly.

93/93 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
… hit rate

Carl's call: the durable, cross-user-comparable signal is how long each model's
cache actually stays warm — and it drifts over time — so make TTL the primary
metric. cacheStatsByModel() now also buckets same-model idle gaps per model and
infers a warm window; hit rate + volume ride along as secondary.

Real data is telling: DeepSeek-v4-pro stays warm ~240 min, Opus 4.8 ~60 min,
Fable 5 only ~2 min (bursty, rarely resumed after a gap). That per-model spread
is exactly what you can't see from a single global number.

Also fixes the bar/number ambiguity Carl flagged: the bar AND the bold number
are now the same metric (TTL); "—" shown when a model has too few gaps to
estimate. Hit% + token volume moved to a muted sub-line.

93/93 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
… skimmable template

When the cheap model (CCU_BOT_MODEL, default deepseek-v4-flash) says it can't
answer from the docs alone, escalate to a stronger model (CCU_BOT_MODEL_PRO,
default deepseek-v4-pro) with thinking on, and let it NAME a few repo source
files. The SCRIPT reads them — repo-relative text files only, no "..", size-
capped, must resolve inside the repo root — so there's still no agent tool and
no way for a malicious issue to make it read or run anything arbitrary. If it
still can't answer, its reply asks for the specific missing info/logs and
suggests the issue template.

Also gives every reply a skim-friendly shape: TL;DR/结论 first, then analysis,
then suggested next steps. Thinking param is best-effort (retries without it if
the endpoint rejects it), so it stays portable across third-party endpoints.

Co-Authored-By: Claude <noreply@anthropic.com>
…ssion without spending context

Carl's use case: after /clear or /compact he wants to RE-READ his prompts and
the model's answers to jog his memory, but resume (`claude --resume`) reloads
the whole session INTO context and costs tokens. This viewer is the zero-context
path — it just reads the session .jsonl and shows it.

- conversationLog.ts: pure, tested parser (.jsonl text -> ordered display turns).
  Keeps prompts + assistant text front and centre; carries thinking / tool_use /
  tool_result too. Skips meta + sidechain lines, dedupes by uuid, truncates per
  turn, supports "last N turns". 7 unit tests.
- conversationViewerHtml.ts: frontend design per Carl's ask — user PROMPTS are
  the star (accent rail + tint + a top "jump to your prompts" nav), model TEXT
  is a readable card, thinking / tool traffic is present but quiet (collapsed
  <details>, muted). No scripts (webview enableScripts:false); VS Code theme vars
  only; a read-only badge makes the zero-context promise explicit.
- webview.ts: an eye view action on Sessions rows (gated by the new setting) ->
  viewConversation message -> openConversationViewer() reads the file and opens a
  panel. settings.ts: showConversationViewer (features, default OFF).
- i18n: viewConversation button tooltip in all 7 languages. (Viewer panel chrome
  is English-first like the other experimental surfaces; folded into the
  pre-release i18n pass.)

100/100 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
…ed answers, default-hidden tools

Round of viewer feedback from Carl:
- Model answers now render Markdown (new dependency-free miniMarkdown.ts, 8
  tests) instead of showing raw source — much better to read inside the panel.
- Assistant answers get their OWN filled card (was plain), so they stand apart
  from both prompts (accent) and the muted tool traffic.
- Default is a clean CHAT view: thinking and tool activity are HIDDEN behind two
  pure-CSS toggles (checkbox hack, no scripts) — on open you see only prompts +
  answers.
- Opens on the last ~10 rounds; earlier rounds collapse into a <details>.
- Prompt nav items are now expandable to the full prompt text, each with a
  "jump ↓" link.

Co-Authored-By: Claude <noreply@anthropic.com>
The Duration column is the first→last wall-clock span, which is misleading for
long-lived sessions (one real session spans 957h but only ~12.5h was hands-on).
The new Active column sums the gaps between turns with each idle gap capped at
5 min (activeDurationBySession), so it reflects time actually spent. Sortable,
with a tooltip explaining the estimate; labelled in all 7 languages.

Co-Authored-By: Claude <noreply@anthropic.com>
… as a no-op

Two first-pass bot fixes (also going to main via PR):
- The PR first-pass now SKIPS pull requests authored by OWNER / MEMBER /
  COLLABORATOR. A maintainer's own finished PR doesn't need an auto first-pass
  (that review is for external contributors) — and ClaudeCodeUsage#66 showed it firing on our
  own PR and failing on the big self-referential diff.
- An empty model reply is now a soft no-op (exit 0) instead of a hard failure,
  so a benign blank response doesn't leave a red ✗ check.

Co-Authored-By: Claude <noreply@anthropic.com>
…latest marker

More viewer feedback from Carl:
- Assistant answers that aren't the round's FINAL output are marked "interim"
  and can be toggled off (default ON — intermediate results have value); the
  final answer of each round always stays.
- Markdown tables now render (added GFM table support to miniMarkdown + 2 tests).
- Prompt-nav jump link no longer clipped on long prompts — it sits outside the
  truncating text (flex), always visible; the caret still expands full text.
- The most recent prompt gets a "latest" badge in the nav for quick jumping.

Co-Authored-By: Claude <noreply@anthropic.com>
…ctions, C5 right-sizing

One round of Carl's feedback on sessions + insights:

- Active column: idle-gap cap raised 5m → 90m (reading/reviewing a diff is real
  work the log doesn't capture; the old cap badly under-counted). Column moved
  BEFORE Duration; header + cells carry the estimate tooltip. Help text updated
  in all 7 languages.
- Resume + Delete now share ONE opt-in (enableSessionActions, default off):
  both ACT on the user's Claude Code (reopen / trash a log), at odds with the
  extension being read-only, so they hide together. The read-only conversation
  viewer flips to default ON (showConversationViewer) — it only reads local logs.
- C5 "Premium models on lightweight turns": the compute premium spent running a
  top-tier model (output ≥ $20/M) on small-output turns (≤800 out — the
  translation / quick-edit signature), vs Haiku-4.5 rates. Surfaces a per-switch
  churn cost so it says "batch simple tasks on the cheap model", not "flip every
  turn". Real data: ~$19.74 over 2339 turns, mostly Opus. Weekly-cached.

110/110 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
- C5 "premium models on lightweight turns" is no longer rendered. Output size is
  a weak proxy for task difficulty, and the advice ("use a cheaper model for
  simple tasks") isn't something users lack — in practice they stay on the top
  model and tack simple work onto long tasks. A worthwhile version needs a real
  difficulty judgement (sampling prompt text via the opt-in AI-advice API, which
  must be clearly labelled). modelRightsizing() stays as dormant scaffolding.
- Viewer prompt-nav is capped to the last 10 prompts (matching the recent rounds
  shown) so the list is a consistent length and every jump lands in expanded
  content; a note flags any earlier prompts folded into "Show earlier".

110/110 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
…+ prompts

Bug (Carl): a long session with 79 prompts showed only the latest ~3. Cause: the
viewer capped at the last 500 RAW turns, but one prompt is followed by dozens of
tool turns, so 500 turns held only ~4 prompts.

Fix: parseConversation now caps by ROUNDS (a round = a prompt + its replies) via
maxRounds, with a raw-turn ceiling as a safety net. The viewer keeps the last 15
rounds (10 shown + a small "earlier" buffer). Parser also reports totalRounds;
the header now reads "N prompts total · … · showing last 15 of N rounds".
Verified on the real 79-prompt / 6798-turn session: nav shows the last 10
prompts, latest badge on the newest, ~0.6 MB html.

111/111 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
…ints

Next insights-roadmap card (session-health), implementing the checkpoint habit
Carl wanted surfaced: sessionHealth() measures how much of your output came from
a few very large single responses (≥4k output tokens — a big one-shot generation
with no human checkpoint mid-way). Real data: ~39% of output over 321 jumbo
turns (largest ≈50k). The card frames it as a gentle nudge (smaller checkpoints
= cheaper/faster review, catch a wrong direction early), not a verdict — a big
single turn is sometimes exactly right. Weekly-cached, opt-in (showInsights).

111/111 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
…sight

Two items from Carl's feedback:

- Conversation viewer now (re)uses a SINGLE panel: each "view" click re-reads
  the session .jsonl fresh and refreshes that panel (revealing it), instead of
  piling up a new tab per click. An ongoing session shows its latest turns.

- New insights card "Your active hours": activeHours() buckets non-cache work
  (input+output tokens) by hour-of-day in the user's timezone, with a 24-hour
  sparkline and the busiest contiguous 4-hour window + its share. Real data:
  peak 15:00–19:00, 35% of work. Tip ties it to protecting the peak window and
  keeping momentum in one warm session there. Weekly-cached, opt-in.

111/111 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
Next roadmap card. skillRoi() uses the authoritative _skill/_plugin attribution
Claude Code ≥2.1 stamps on usage lines: per skill, the cost spent while it was
active and the output it returned, with outPerUsd (output tokens per $) as the
ROI angle. Real data separates lean skills (lit-review ~15k tok/$, paper-plotting
~13.5k) from context-heavy ones (claude-api ~1.9k, code-review ~2.1k) — so you
can see which skills burn context for little output. Bar/number = cost; note
flags it's a proxy (cost attributed to the active skill, output isn't "value").
Weekly-cached, opt-in. (Budget-pacing card skipped for V2.2 per Carl.)

111/111 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
Carl: the right-hand figure was a bare dollar amount, unclear as "ROI" and not
matching the bar. Now the bar and the number are the SAME metric — output tokens
returned per $ (with a "/$" unit) — sorted by it so the bars rank; cost + turns
move to the muted sub-line.
…tings i18n sync

- Replaces the fileWatching on/off toggle with a discrete "Live refresh delay"
  choice: Off / 1 / 2 / 5 / 10 / 20 / 30s (fileWatchSeconds, default 2s ≈ old
  1.5s). The fs watcher uses it as the debounce; Off stops watching. Help makes
  clear this only re-reads LOCAL log files — no API call; the /usage quota fetch
  is throttled separately, so a short delay doesn't hammer the official API.
- Settings i18n sync (Carl's release check): localized the setting label/help in
  all 6 non-English locales for fileWatchSeconds, plus showInsights and
  showConversationViewer (previously English-only), and renamed the
  enableSessionDelete labels to enableSessionActions to match the merged setting.

111/111 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
…lier" was confusing

- Cache-write ("input cache miss") bars rendered transparent in every usage bar
  chart. Cause: .cache-creation-bar's gradient referenced var(--vscode-charts-pink),
  which VS Code doesn't define — an invalid color makes the whole gradient (and
  thus the background) invalid, so only the axis + value labels showed. Added a
  pink fallback so the gradient is valid.
- Conversation viewer: dropped the "Show earlier conversation (N rounds)" collapse.
  It was confusing — the top prompt-nav didn't reflect it, so you couldn't tell
  whether the earlier prompts were shown, and toggling it only changed the body.
  Now every loaded round renders flat and the nav lists every loaded prompt (all
  jump targets exist). Default load is the last 10 rounds ("showing last 10 of N").

111/111 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
- CHANGELOG [2.2.0]: added the conversation viewer, Experimental insights suite
  (cache-churn / warmth-by-model / big one-shot / active hours / skill ROI),
  Sessions "Active" column, live-refresh delay control, Chinese share-card units,
  the enableSessionActions merge + timezone-aware bucketing (Changed), the
  cache-write invisible-bars fix (Fixed), and the @types/glob removal (Removed).
- Refreshed the in-extension "What's New" 2.2 blurb to match.
- Removed the unused @types/glob devDependency (folds in ClaudeCodeUsage#63, thanks @zeyutang).

Co-Authored-By: Claude <noreply@anthropic.com>
ARCHITECTURE.md module table now lists sessionResume.ts, conversationLog.ts,
conversationViewerHtml.ts and miniMarkdown.ts, and the data-layer notes cover the
new insight methods (estimateCacheChurnCost, cacheStatsByModel, sessionHealth,
activeHours, skillRoi, activeDurationBySession, modelRightsizing).

Co-Authored-By: Claude <noreply@anthropic.com>
…e#62)

* fix: timezone bucketing and cache-write cost accuracy

* bucket Today/month/daily/hourly totals by the configured IANA zone
* keep the loader zone in lockstep with display; recompute on change
* split cache writes into 1h (2x) vs 5m (1.25x) when the log has the ttl
* add tests for zone bucketing and the cache-write split

* i18n: note timezone sets the daily cost boundary

* add the day-boundary clause to the timezone help in all six locales
* update the timezone description in README and the locale editions

* fix: changelog minor touch-up

* Maintainer edit: keep the cache-write TTL pricing; drop the timezone changes

The timezone-bucketing half overlaps with the shared zone-aware day-key rework
landing in V2.2, so this reduces the PR to just the cache-write TTL pricing
(pricing.ts + types.ts + pricing.test.ts) to merge cleanly. zeyutang's original
commits are preserved; the timezone work is welcome as a follow-up PR.

* Remove stray sample-card SVGs accidentally swept into the maintainer edit

---------

Co-authored-by: Carl <74130028+Carl723000@users.noreply.github.com>
…wn the @types/glob removal

- What's New for 2.2 is now newline bullets (• per feature) instead of one dense
  paragraph, so the toast is scannable. Copy unchanged (Carl approved it).
- Restore @types/glob locally: ClaudeCodeUsage#62-style, the removal now traces solely to
  zeyutang's merged ClaudeCodeUsage#63 rather than a duplicate local edit. It's a devDependency
  (never packaged), so the vsix is unaffected; the merge to main drops it.
…-polish

# Conflicts:
#	.github/workflows/claude.yml
#	ARCHITECTURE.md
#	CHANGELOG.md
@Carl723000
Carl723000 requested a review from jack21 as a code owner July 6, 2026 07:51
@github-actions github-actions Bot added the feature Minor bump — new feature label Jul 6, 2026
@Carl723000 Carl723000 added the minor Minor bump label Jul 6, 2026
@Carl723000
Carl723000 merged commit 3badd1c into ClaudeCodeUsage:main Jul 6, 2026
3 checks passed
@Carl723000
Carl723000 deleted the feat/v2.2-share-and-polish 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

feature Minor bump — new feature minor Minor bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants