[BUG] /usage heatmap misplaces usage by one weekday row; contradicts "Most active day" stat

Resolved 💬 1 comment Opened Jun 10, 2026 by erikvanderschaaf Closed Jun 10, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Title: [BUG] /usage activity heatmap plots usage one weekday row off (week-start / off-by-one)

Description

The activity heatmap shown by /usage (a.k.a. /stats) maps each day's usage to
the wrong weekday row — every day appears shifted down by exactly one row
relative to the Mon/Wed/Fri row labels. This looks like a Sunday-start vs.
Monday-start week mismatch (off-by-one) between the row labels and the plotted data.

What I see

      Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun
      ····················································
  Mon ····················································
      ···············································░▒·▒█
  Wed ··············································▓▓█·█░
      ··············································▒█▓·░
  Fri ··············································▒·█·▓
      ···············································░···

Reading rows by their labels (Sun top → Sat bottom):

| Row label | Glyphs | Plausible? |
|-----------|--------|-----------|
| Sun | zero | ok |
| Mon | zero | ❌ I work every Monday — should be busy |
| Tue | busy | ok |
| Wed | busy | ok |
| Thu | busy | ok |
| Fri | busy | ❌ Friday is my fixed day off — should be ~empty |
| Sat | faint | ❌ I never work Saturdays |

Why it's an off-by-one (not timezone)

A timezone offset can only move usage by hours, so it can never turn busy
Mondays blank or an empty day-off Friday into the busiest-looking row. But if you
realign the chart up by one row, everything matches my real schedule exactly:

| Displayed as | Actually my | Matches reality? |
|--------------|-------------|------------------|
| Tue | Mon | ✅ work |
| Wed | Tue | ✅ work |
| Thu | Wed | ✅ work |
| Fri | Thu | ✅ work |
| Sat (faint) | Fri | ✅ day off, occasional bit of work |
| Sun / Mon | Sat / Sun | ✅ weekend, zero |

So the underlying usage data appears correct — it's just rendered one weekday row
too low. The row labels (Mon/Wed/Fri) and the plotted data disagree on which
day each row represents.

Corroborating evidence: headline stat disagrees with the grid

The dialog also reports "Most active day: Jun 2". June 2, 2026 was a Tuesday.
That text stat is computed directly from the per-date totals (date → weekday mapped
correctly), so Jun 2 genuinely was the busiest day.

But on the grid, the Jun 2 column is faint in the Tuesday row — the dark cell is
the one directly below it, in the Wednesday row. In other words, two views of the
exact same dataset disagree:

  • Text stat ("Most active day: Jun 2") → maps the date to Tuesday (correct).
  • Heatmap → plots Jun 2's intensity in the Wednesday row (one row too low).

This isolates the bug to the heatmap's row placement (not the underlying data, and
not a timezone effect): the same day is labeled correctly in text but drawn one
weekday row off in the grid.

Expected behavior

Each day's usage should appear in the row matching its actual weekday, consistent
with the Mon/Wed/Fri labels — and consistent with the "Most active day" text stat.

Actual behavior

All usage is plotted one weekday row lower than the labels indicate.

Environment

  • Claude Code: 2.1.170
  • OS: Linux (WSL2) — Windows Subsystem for Linux, kernel 6.6.114.1-microsoft-standard-WSL2, x86_64
  • Timezone: Europe/Amsterdam (CEST, UTC+2)

Notes

The heatmap buckets days by UTC (per the Claude Code Analytics API docs), but that
is a separate concern — the misalignment here is a whole-day weekday shift, not an
hours-level UTC offset.

What Should Happen?

Each day's usage should appear in the row matching its actual weekday — consistent
with both the Mon/Wed/Fri row labels and the "Most active day" text stat.

Concretely, shifting the plotted data up by one row produces a grid that matches
my real schedule (busy Mon–Thu, faint Fri day-off, empty weekend) and puts Jun 2's
dark cell on the Tuesday row where the headline stat says it belongs:

      Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun
      ····················································
  Mon ···············································░▒·▒█
      ··············································▓▓█·█░
  Wed ··············································▒█▓·░
      ··············································▒·█·▓
  Fri ···············································░···
      ····················································
  • MonThu rows: busy ✅
  • Fri row: a single faint cell (occasional work on my day off) ✅
  • Sat/Sun rows: empty ✅
  • The dark cell in the Jun 2 column now sits on the Tuesday row, agreeing with

"Most active day: Jun 2". ✅

Error Messages/Logs

Steps to Reproduce

Steps to reproduce

  1. Use Claude Code regularly enough to build up a recognizable weekly pattern (e.g.

I work Mon–Thu and take Fridays off).

  1. Run /usage (or /stats) and open the activity heatmap / contribution graph.
  2. Compare each weekday row against when you actually used Claude — and cross-check

the "Most active day" text stat against the cell shading in that day's column.

Observed: every day's usage is drawn one weekday row below its true weekday. The
"Most active day: Jun 2" (a Tuesday) text stat does not match the grid, where the
Jun 2 column is dark on the Wednesday row and faint on the Tuesday row.

Claude Model

None

Is this a regression?

_No response_

Last Working Version

_No response_

Claude Code Version

2.1.170

Platform

Other

Operating System

Ubuntu/Debian Linux

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

This whole bug report has been generated by Claude Code itself

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗