openclaw - 💡(How to fix) Fix claude-cli runtime sessions show "?/<limit>" for context usage in /status [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#78634Fetched 2026-05-07 03:34:29
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
2
Timeline (top)
closed ×1commented ×1

Root Cause

The transcript usage reader at src/gateway/session-utils.fs.ts:1228 only flips totalTokensFresh = true when the transcript has a literal top-level totalTokens field:

if (typeof totalTokens === "number") {
  snapshot.totalTokens = totalTokens;
  snapshot.totalTokensFresh = true;
}

Claude CLI's transcript format reports usage using Anthropic's native shape (input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens), with no top-level totalTokens field. The extractor reads the components correctly into inputTokens, outputTokens, cacheRead, cacheWrite, but never sums them into totalTokens, so totalTokensFresh stays false.

In src/status/status-message.ts:629 the freshness flag gates the display:

let totalTokens =
    freshTotalTokens ??
    (entry?.totalTokensFresh === false
      ? undefined                              // taken
      : (entry?.totalTokens ?? input + output));

And at src/status/status-message.ts:628:

const allowTranscriptContextUsage = entry?.totalTokensFresh !== false;

Both paths are blocked, so the display falls through to "?".

Code Example

if (typeof totalTokens === "number") {
  snapshot.totalTokens = totalTokens;
  snapshot.totalTokensFresh = true;
}

---

let totalTokens =
    freshTotalTokens ??
    (entry?.totalTokensFresh === false
      ? undefined                              // taken
      : (entry?.totalTokens ?? input + output));

---

const allowTranscriptContextUsage = entry?.totalTokensFresh !== false;

---

const computed = (typeof totalTokens === "number")
  ? totalTokens
  : (typeof usage?.input === "number" ? usage.input : 0)
    + (typeof usage?.output === "number" ? usage.output : 0)
    + (typeof usage?.cacheRead === "number" ? usage.cacheRead : 0)
    + (typeof usage?.cacheWrite === "number" ? usage.cacheWrite : 0);
if (computed > 0) {
  snapshot.totalTokens = computed;
  snapshot.totalTokensFresh = true;
}
RAW_BUFFERClick to expand / collapse

Symptom

For agents running on the claude-cli runtime, /status shows the current token count as "?":

📚 Context: ?/800k · 🧹 Compactions: 0

The session has accurate per-turn usage data (inputTokens, outputTokens, cacheRead, cacheWrite are all populated), but the displayed total never appears. Other lines (🧮 Tokens, 🗄️ Cache) work correctly.

This is purely a display issue. Compaction and overflow handling are driven by runtime API responses and are unaffected.

Repro

  1. Configure an agent on the claude-cli runtime with a non-trivial context.
  2. Have one or more turns of conversation.
  3. Run /status.
  4. Observe 📚 Context: ?/<limit> despite the session entry containing valid inputTokens, outputTokens, cacheRead, cacheWrite.

Root cause

The transcript usage reader at src/gateway/session-utils.fs.ts:1228 only flips totalTokensFresh = true when the transcript has a literal top-level totalTokens field:

if (typeof totalTokens === "number") {
  snapshot.totalTokens = totalTokens;
  snapshot.totalTokensFresh = true;
}

Claude CLI's transcript format reports usage using Anthropic's native shape (input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens), with no top-level totalTokens field. The extractor reads the components correctly into inputTokens, outputTokens, cacheRead, cacheWrite, but never sums them into totalTokens, so totalTokensFresh stays false.

In src/status/status-message.ts:629 the freshness flag gates the display:

let totalTokens =
    freshTotalTokens ??
    (entry?.totalTokensFresh === false
      ? undefined                              // taken
      : (entry?.totalTokens ?? input + output));

And at src/status/status-message.ts:628:

const allowTranscriptContextUsage = entry?.totalTokensFresh !== false;

Both paths are blocked, so the display falls through to "?".

Suggested fix

In the transcript reader, when totalTokens is missing, compute it from the present components:

const computed = (typeof totalTokens === "number")
  ? totalTokens
  : (typeof usage?.input === "number" ? usage.input : 0)
    + (typeof usage?.output === "number" ? usage.output : 0)
    + (typeof usage?.cacheRead === "number" ? usage.cacheRead : 0)
    + (typeof usage?.cacheWrite === "number" ? usage.cacheWrite : 0);
if (computed > 0) {
  snapshot.totalTokens = computed;
  snapshot.totalTokensFresh = true;
}

This restores accurate context usage display for claude-cli sessions without changing any execution behavior.

Environment

OpenClaw 2026.5.3 (Docker, openclaw-custom:2026.5.2 base).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING