Statusline JSON: expose /context's conceptual token count (Messages-sum), not just API-billed used_percentage

Resolved 💬 3 comments Opened Apr 11, 2026 by ShayanNasiri Closed Apr 14, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

After /compact, the context_window.used_percentage field in the statusline JSON and the "Free space" row in /context disagree
by ~14 percentage points for roughly the prompt-cache TTL (~5 minutes). Third-party statuslines that render free space based
on the documented formula cannot match what /context shows, because the underlying conceptual-token number isn't exposed.

Please add a field to context_window (or context_window.current_usage) that reflects the conceptual post-compact token count —
the same number /context uses to compute its "Free space" row from the category breakdown (System + Tools + MCP + Memory +
Messages + …).

Why the current fields are insufficient

The documented formula for used_percentage is:

used_percentage = (input_tokens + cache_creation_input_tokens + cache_read_input_tokens) / context_window_size

This tracks API billing. After /compact, cache_read_input_tokens still contains the pre-compact prefix (~25 k tokens on a 200
k window) until the prompt cache ages out or subsequent calls overwrite it. So used_percentage is inflated relative to the
conversation's actual conceptual size.

/context itself computes "Free space" from the category breakdown sum, not from used_percentage. You can see this in a
post-compact session: the /context header percentage and the per-category sum don't match each other. For example, in one of
my sessions:

  • /context header: 96.6 k used (48 %) — from used_percentage
  • /context category sum: 72.8 k (System 6.2 k + Tools 8 k + Memory 0.994 k + Skills 2.9 k + Messages 54.7 k)
  • "Free space: 94.2 k (47.1 %)" — derived from the category sum
  • Gap: 23.8 k tokens of stale prompt-cache prefix

A statusline built on the documented contract will render "35 % free" while /context reports "49 % free" — a 14 pp gap that
looks like a bug to users but is actually faithful to the JSON.

What I've already ruled out

  • total_input_tokens is not a reliable proxy. In a compacted session it happened to match Messages (53 292 vs 54 700, 1.03×),

but on a fresh session it was 1.59× the Messages number (89 140 vs 141 800). It's tracking something else.

  • The discrepancy isn't a rounding error — it's systematically ~14 pp on a 200 k window until the cache turns over.
  • This isn't fixable in the statusline binary; the field simply isn't in the JSON.

Proposed Solution

Add one of:

  1. context_window.conceptual_used_tokens — same number /context's category-sum uses. Third-party statuslines can compute

free_pct = 100 − conceptual_used_tokens / context_window_size × 100 − autocompact_pct and match /context exactly.

  1. context_window.conceptual_used_percentage — pre-computed, equivalent.
  2. context_window.breakdown — the full category map ({system, tools, mcp, memory, messages, …}) that /context renders. Bonus:

lets statuslines surface category-specific warnings ("Tools section is eating 40 % of your window").

Option 3 is the richest; option 1 is the smallest change and solves the reported bug.

Repro

  1. Run a Claude Code session until it has meaningful content (~50 % used).
  2. Run /compact.
  3. Within ~5 minutes, compare the statusline's rendered free space against /context's "Free space" row.
  4. Expected: they agree. Actual: statusline is ~14 pp lower.

Context

I maintain a native C statusline (ShayanNasiri/claude-modern-status-bar) that implements the documented contract precisely. The formula is correct, the rendering is correct, the JSON input is faithful to the docs — but the number doesn't match /context because the JSON itself doesn't carry the conceptual count. This would fix it for every third-party statusline, not just mine.

Alternative Solutions

_No response_

Priority

Medium - Would be very helpful

Feature Category

Configuration and settings

Use Case Example

_No response_

Additional Context

_No response_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗