Intermittent bug: Status line shows stale token count after /compact
Problem Summary
The status line intermittently shows stale (pre-compact) token counts after running /compact, while the /context command correctly shows the reduced post-compact count. The bug is not consistently reproducible.
Example observed behavior:
- Pre-compact: Status line shows 146k tokens
- Run
/compact - Post-compact:
/contextshows 97k tokens (correct) - Post-compact: Status line still shows 146k tokens (stale)
Expected Behavior
After /compact completes:
- Status line should immediately update to show reduced token count
- Status line count should match (or be close to)
/contextcount - Both should reflect the compacted conversation state
Actual Behavior
Occasionally after compact:
- Status line continues displaying pre-compact token count
/contextshows correct reduced count- Discrepancy persists across multiple status line refreshes
- Bug does not always occur - appears intermittent
Investigation & Ruled Out Causes
Conducted systematic testing to identify root cause:
✅ Tested: session_id changes after compact
Hypothesis: Compact creates new transcript with new session_id, but status line hook receives old session_id
Test method:
- Modified
.claude/settings.local.jsonto capture status line input:
``json``
"statusLine": {
"command": "tee /tmp/statusline-input.json | ./.claude/statusline.sh"
}
- Captured JSON input before compact
- Ran
/compact - Captured JSON input after compact
- Compared
session_idandtranscript_pathfields
Result: ❌ Not the cause
session_idremained identical before and after compact:d3da6f78-84d4-44b8-8e28-2189c1e9e2e6transcript_pathremained identical- Compact updated the transcript file in-place (same filename, updated mtime)
- Status line correctly received the current session_id
✅ Tested: Sub-agent causing session_id confusion
Hypothesis: When Task tool (sub-agent) runs, it may have its own session_id that persists in status line after completion
Test method:
- Launched general-purpose sub-agent with simple task
- Monitored status line JSON input during agent execution
- Checked session_id after agent completed
Result: ❌ Not the cause
session_idremained identical during and after sub-agent execution- No evidence of sub-agent session_id "leaking" into parent session
✅ Tested: Compact behavior in controlled scenario
Test method:
- Established baseline: Status line 30k,
/context74k - Ran
/compact - Measured post-compact: Status line 29k,
/context76k
Result: ❌ Bug did not reproduce
- Both status line and
/contextupdated correctly (small 1k reduction) - This test confirms the bug is intermittent, not constant
Possible Remaining Causes
Since the bug is intermittent and we've ruled out session_id issues:
- Auto-compact vs manual
/compact: Bug may only occur with auto-compact - Context size threshold: May only trigger at certain token counts (e.g., >150k)
- Multiple compacts in succession: Second/third compact may behave differently
- Timing/race condition: Status line hook called before transcript fully written/flushed
- Token calculator caching: File system or token calculator may cache results
- Transcript file locking: File may be locked/unavailable during compact operation
Diagnostic Infrastructure Added
To enable root cause analysis when bug occurs again, added comprehensive logging to status line script:
Log location: .claude/logs/statusline.log (JSON Lines format)
Each invocation logs:
{
"timestamp": "2025-10-01T12:21:38-05:00",
"session_id": "d3da6f78-84d4-44b8-8e28-2189c1e9e2e6",
"transcript_path": "/home/ikme/.claude/projects/.../transcript.jsonl",
"transcript_exists": true,
"transcript_mtime": "2025-10-01 12:21:37",
"token_count": "48",
"calculation_success": true,
"error": "null",
"display_output": "⚡ • 48k/200k (24%) • Sonnet 4.5"
}
Log rotation: Automatically keeps last 10,000 lines to prevent unbounded growth
Captured data enables analysis of:
- Whether session_id changed before/during/after compact
- Whether transcript file existed and was readable
- Whether token calculation succeeded or failed
- Exact timestamp and modification time correlation
- What output was displayed to user
Steps to Reproduce (If Known)
Unable to consistently reproduce. Bug occurs intermittently during normal usage with /compact.
To investigate further when bug occurs:
- Check
.claude/logs/statusline.logfor entries around compact time - Compare
session_idvalues before/after compact - Check
transcript_mtimeto verify file was updated - Look for
calculation_success: falseor error messages - Compare
token_countin log vs actual transcript tokens
Affected Components
- [x] Status line display
- [x] Token calculation
- [ ]
/compactcommand - [ ]
/contextcommand
System Information
- Claude Code Version: 2.0.2
- Operating System: Linux (WSL2)
- Status Line Script: Custom
.claude/statusline.shusing.claude/token-calculator.js
Additional Context
The status line uses a custom token calculator script that:
- Receives JSON input from Claude Code with
session_idandtranscript_path - Reads the transcript file
- Calculates tokens using
@anthropic-ai/tokenizer - Displays result in status line
The /context command uses Claude Code's internal token tracking, which may explain why it's always correct while the status line (which reads the file directly) can be stale.
Request
Please investigate why the status line hook occasionally receives or calculates stale token counts after compact. The logging infrastructure is now in place to diagnose the issue when it reproduces.
---
Generated via workflow-support with comprehensive investigation
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗