cc-context-stats 1.8.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/package.json +8 -1
  2. package/scripts/context-stats.sh +1 -1
  3. package/.editorconfig +0 -60
  4. package/.eslintrc.json +0 -35
  5. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -49
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -31
  7. package/.github/PULL_REQUEST_TEMPLATE.md +0 -33
  8. package/.github/dependabot.yml +0 -44
  9. package/.github/workflows/ci.yml +0 -294
  10. package/.github/workflows/release.yml +0 -151
  11. package/.pre-commit-config.yaml +0 -74
  12. package/.prettierrc +0 -33
  13. package/.shellcheckrc +0 -10
  14. package/CHANGELOG.md +0 -187
  15. package/CLAUDE.md +0 -66
  16. package/CODE_OF_CONDUCT.md +0 -59
  17. package/CONTRIBUTING.md +0 -240
  18. package/RELEASE_NOTES.md +0 -19
  19. package/SECURITY.md +0 -44
  20. package/TODOS.md +0 -72
  21. package/assets/logo/favicon.svg +0 -19
  22. package/assets/logo/logo-black.svg +0 -24
  23. package/assets/logo/logo-full.svg +0 -40
  24. package/assets/logo/logo-icon.svg +0 -27
  25. package/assets/logo/logo-mark.svg +0 -28
  26. package/assets/logo/logo-white.svg +0 -24
  27. package/assets/logo/logo-wordmark.svg +0 -6
  28. package/config/settings-example.json +0 -7
  29. package/config/settings-node.json +0 -7
  30. package/config/settings-python.json +0 -7
  31. package/docs/ARCHITECTURE.md +0 -128
  32. package/docs/CSV_FORMAT.md +0 -42
  33. package/docs/DEPLOYMENT.md +0 -71
  34. package/docs/DEVELOPMENT.md +0 -161
  35. package/docs/MODEL_INTELLIGENCE.md +0 -396
  36. package/docs/configuration.md +0 -118
  37. package/docs/context-stats.md +0 -143
  38. package/docs/installation.md +0 -255
  39. package/docs/scripts.md +0 -140
  40. package/docs/troubleshooting.md +0 -278
  41. package/images/claude-statusline-token-graph.gif +0 -0
  42. package/images/claude-statusline.png +0 -0
  43. package/images/context-status-dumbzone.png +0 -0
  44. package/images/context-status.png +0 -0
  45. package/images/statusline-detail.png +0 -0
  46. package/images/token-graph.jpeg +0 -0
  47. package/images/token-graph.png +0 -0
  48. package/images/v1.6.1.png +0 -0
  49. package/install +0 -351
  50. package/install.sh +0 -298
  51. package/jest.config.js +0 -11
  52. package/pyproject.toml +0 -115
  53. package/requirements-dev.txt +0 -12
  54. package/scripts/statusline-full.sh +0 -438
  55. package/scripts/statusline-git.sh +0 -88
  56. package/scripts/statusline-minimal.sh +0 -67
  57. package/scripts/statusline.py +0 -569
  58. package/src/claude_statusline/__init__.py +0 -11
  59. package/src/claude_statusline/__main__.py +0 -6
  60. package/src/claude_statusline/cli/__init__.py +0 -1
  61. package/src/claude_statusline/cli/context_stats.py +0 -542
  62. package/src/claude_statusline/cli/explain.py +0 -228
  63. package/src/claude_statusline/cli/statusline.py +0 -184
  64. package/src/claude_statusline/core/__init__.py +0 -1
  65. package/src/claude_statusline/core/colors.py +0 -124
  66. package/src/claude_statusline/core/config.py +0 -165
  67. package/src/claude_statusline/core/git.py +0 -78
  68. package/src/claude_statusline/core/state.py +0 -323
  69. package/src/claude_statusline/formatters/__init__.py +0 -1
  70. package/src/claude_statusline/formatters/layout.py +0 -67
  71. package/src/claude_statusline/formatters/time.py +0 -50
  72. package/src/claude_statusline/formatters/tokens.py +0 -70
  73. package/src/claude_statusline/graphs/__init__.py +0 -1
  74. package/src/claude_statusline/graphs/intelligence.py +0 -162
  75. package/src/claude_statusline/graphs/renderer.py +0 -401
  76. package/src/claude_statusline/graphs/statistics.py +0 -92
  77. package/src/claude_statusline/ui/__init__.py +0 -1
  78. package/src/claude_statusline/ui/icons.py +0 -93
  79. package/src/claude_statusline/ui/waiting.py +0 -62
  80. package/tests/bash/test_delta_parity.bats +0 -199
  81. package/tests/bash/test_install.bats +0 -29
  82. package/tests/bash/test_parity.bats +0 -315
  83. package/tests/bash/test_statusline_full.bats +0 -139
  84. package/tests/bash/test_statusline_git.bats +0 -42
  85. package/tests/bash/test_statusline_minimal.bats +0 -37
  86. package/tests/fixtures/json/comma_in_path.json +0 -31
  87. package/tests/fixtures/json/high_usage.json +0 -17
  88. package/tests/fixtures/json/low_usage.json +0 -17
  89. package/tests/fixtures/json/medium_usage.json +0 -17
  90. package/tests/fixtures/json/valid_full.json +0 -30
  91. package/tests/fixtures/json/valid_minimal.json +0 -9
  92. package/tests/fixtures/mi_test_vectors.json +0 -140
  93. package/tests/node/intelligence.test.js +0 -98
  94. package/tests/node/rotation.test.js +0 -89
  95. package/tests/node/statusline.test.js +0 -240
  96. package/tests/python/conftest.py +0 -84
  97. package/tests/python/test_colors.py +0 -105
  98. package/tests/python/test_config_colors.py +0 -78
  99. package/tests/python/test_data_pipeline.py +0 -446
  100. package/tests/python/test_explain.py +0 -177
  101. package/tests/python/test_icons.py +0 -152
  102. package/tests/python/test_intelligence.py +0 -314
  103. package/tests/python/test_layout.py +0 -127
  104. package/tests/python/test_state_rotation_validation.py +0 -232
  105. package/tests/python/test_statusline.py +0 -215
  106. package/tests/python/test_waiting.py +0 -127
@@ -1,396 +0,0 @@
1
- # Model Intelligence (MI) Metric — Implementation Plan
2
-
3
- > Inspired by the **Michelangelo** paper: *Long Context Evaluations Beyond Haystacks via Latent Structure Queries* (arXiv:2409.12640, Google DeepMind, Sep 2024)
4
-
5
- ## Context
6
-
7
- Users of cc-context-stats can see how much context remains, but have no indicator of **how well the model is likely performing** at the current context fill level. The Michelangelo paper demonstrates that LLM answer quality degrades predictably as context fills — with an initial sharp super-linear drop followed by linear/flat degradation. Different capabilities (reasoning, retrieval, self-awareness) degrade at different rates.
8
-
9
- This plan introduces a **Model Intelligence (MI)** score: a [0, 1] heuristic that estimates answer quality using only data already available in the CSV state entries. It complements the existing Smart/Dumb/Wrap Up Zone indicators with a continuous, multi-dimensional score.
10
-
11
- ## Key Insights from the Paper
12
-
13
- 1. **Performance degrades with context length** — All models show significant falloff, often starting before 32K tokens. There is an initial sharp super-linear drop, followed by either flattening or continued linear degradation.
14
-
15
- 2. **Three orthogonal evaluation dimensions** (each measures different aspects):
16
- - **MRCR**: Understanding ordering, distinguishing similar content, reproducing context (scored via string similarity [0,1])
17
- - **Latent List**: Tracking a latent data structure through operations (scored via exact match + normalized error [0,1])
18
- - **IDK**: Knowing what the model doesn't know (scored via accuracy [0,1])
19
-
20
- 3. **Higher complexity = steeper degradation** — As task complexity increases, performance falls off faster with context length.
21
-
22
- 4. **Cross-over behavior** — Models better at short context can become worse at long context.
23
-
24
- 5. **Perplexity ≠ reasoning quality** — Low perplexity does not predict good reasoning at long contexts.
25
-
26
- ## Formula Design
27
-
28
- ### Guard Clause
29
-
30
- If `context_window_size == 0` (old 2-field CSV entries, malformed data), return `MI = 1.0` with all sub-scores at defaults (CPS=1.0, ES=1.0, PS=0.5). This avoids division by zero and treats unknown-context entries optimistically.
31
-
32
- ### MI = 0.60 × CPS + 0.25 × ES + 0.15 × PS
33
-
34
- Three sub-scores, each inspired by a Michelangelo evaluation dimension. Weights are **hardcoded constants** (not configurable) to minimize cross-implementation sync burden.
35
-
36
- ### 1. Context Pressure Score (CPS) — weight: 0.60
37
-
38
- Maps to the paper's primary finding: performance degrades with context utilization.
39
-
40
- ```
41
- u = current_used_tokens / context_window_size (utilization ratio, 0 to 1+)
42
- CPS = max(0, 1 - u^β)
43
- ```
44
-
45
- Default `β = 1.5`. Configurable via `mi_curve_beta`. This creates the super-linear initial drop observed in the paper:
46
-
47
- | Utilization (u) | CPS (β=1.5) | CPS (β=1.0, linear) | CPS (β=2.0, quadratic) |
48
- |---|---|---|---|
49
- | 0.0 | 1.00 | 1.00 | 1.00 |
50
- | 0.2 | 0.91 | 0.80 | 0.96 |
51
- | 0.4 | 0.75 | 0.60 | 0.84 |
52
- | 0.6 | 0.54 | 0.40 | 0.64 |
53
- | 0.8 | 0.28 | 0.20 | 0.36 |
54
- | 1.0 | 0.00 | 0.00 | 0.00 |
55
-
56
- **Rationale:** β=1.5 reproduces the paper's observation that performance is good early, degrades significantly past ~50%, and becomes severely impaired above ~80%. Configurable via `mi_curve_beta`.
57
-
58
- ### 2. Efficiency Score (ES) — weight: 0.25
59
-
60
- Proxies context utilization quality (analogous to MRCR — is the model effectively re-using prior context?).
61
-
62
- ```
63
- total_context = entry.current_used_tokens # = current_input + cache_creation + cache_read
64
-
65
- if total_context == 0:
66
- ES = 1.0 # No context yet
67
- else:
68
- cache_hit_ratio = cache_read / total_context
69
- ES = 0.3 + 0.7 × cache_hit_ratio # [0.3, 1.0]
70
- ```
71
-
72
- **Note:** `total_context` is the same as `StateEntry.current_used_tokens` (state.py:132). Reuse the existing property in the package; compute inline in standalone scripts.
73
-
74
- - Floor of 0.3 prevents penalizing early-session entries (no cache available yet)
75
- - Full cache-read → ES=1.0
76
-
77
- **Rationale:** High cache-read ratio indicates the model is successfully re-using previously cached context rather than re-processing, suggesting better context utilization.
78
-
79
- ### 3. Productivity Score (PS) — weight: 0.15
80
-
81
- Proxies output quality (analogous to Latent List/IDK — is the model producing meaningful, actionable output?).
82
-
83
- **Deltas are computed as consecutive entry differences** (not cumulative totals):
84
- ```
85
- delta_lines_added = current.lines_added - previous.lines_added
86
- delta_lines_removed = current.lines_removed - previous.lines_removed
87
- delta_output_tokens = current.total_output_tokens - previous.total_output_tokens
88
- ```
89
-
90
- ```
91
- if no previous entry OR delta_output_tokens <= 0:
92
- PS = 0.5 # Neutral
93
- else:
94
- delta_lines = delta_lines_added + delta_lines_removed
95
- ratio = delta_lines / delta_output_tokens
96
- normalized = min(1.0, ratio / target) # target: 0.2 (hardcoded)
97
- PS = 0.2 + 0.8 × normalized # [0.2, 1.0]
98
- ```
99
-
100
- - Target: 0.2 lines/token (1 line per 5 output tokens) = perfect score, **hardcoded** (not configurable)
101
- - Floor of 0.2 for explanation-heavy sessions (still valid work)
102
- - Lowest weight (0.15) because it's the noisiest proxy
103
-
104
- **Rationale:** When the model produces concrete code changes relative to token expenditure, it is likely giving focused, relevant answers. When it produces many tokens with no code changes, it may be struggling.
105
-
106
- ### Color Thresholds (hardcoded)
107
-
108
- | MI Range | Color | Label | Interpretation |
109
- |---|---|---|---|
110
- | > 0.65 | Green | High Intelligence | Model is operating well |
111
- | 0.35–0.65 | Yellow | Degraded | Context pressure affecting quality |
112
- | < 0.35 | Red | Critical | Severely degraded, consider new session |
113
-
114
- ### Example Calculations
115
-
116
- **Fresh session** (u=0.1, 60% cache, 150 lines/1000 tokens):
117
- - CPS = 1 - 0.1^1.5 = 0.968
118
- - ES = 0.3 + 0.7 × 0.6 = 0.72
119
- - PS = 0.2 + 0.8 × min(1, 0.15/0.2) = 0.80
120
- - **MI = 0.60×0.968 + 0.25×0.72 + 0.15×0.80 = 0.581 + 0.180 + 0.120 = 0.88**
121
-
122
- **Mid-session** (u=0.5, 40% cache, 100 lines/1000 tokens):
123
- - CPS = 1 - 0.5^1.5 = 0.646
124
- - ES = 0.3 + 0.7 × 0.4 = 0.58
125
- - PS = 0.2 + 0.8 × min(1, 0.1/0.2) = 0.60
126
- - **MI = 0.60×0.646 + 0.25×0.58 + 0.15×0.60 = 0.388 + 0.145 + 0.090 = 0.62**
127
-
128
- **Late session** (u=0.85, 20% cache, 50 lines/1000 tokens):
129
- - CPS = 1 - 0.85^1.5 = 0.217
130
- - ES = 0.3 + 0.7 × 0.2 = 0.44
131
- - PS = 0.2 + 0.8 × min(1, 0.05/0.2) = 0.40
132
- - **MI = 0.60×0.217 + 0.25×0.44 + 0.15×0.40 = 0.130 + 0.110 + 0.060 = 0.30**
133
-
134
- ## Implementation Steps
135
-
136
- ### Step 1: Create `src/claude_statusline/graphs/intelligence.py`
137
-
138
- Core MI computation module:
139
- - `IntelligenceConfig` dataclass — beta only (weights, thresholds, productivity_target are hardcoded constants)
140
- - `IntelligenceScore` dataclass — cps, es, ps, mi, utilization (all floats)
141
- - `calculate_context_pressure(utilization, beta) → float`
142
- - `calculate_efficiency(entry: StateEntry) → float`
143
- - `calculate_productivity(current: StateEntry, previous: StateEntry | None) → float` — uses **consecutive entry diffs** for delta_lines and delta_output_tokens
144
- - `calculate_intelligence(current: StateEntry, previous: StateEntry | None, context_window_size: int, beta?) → IntelligenceScore`
145
- - **Guard clause:** if `context_window_size == 0`, return `IntelligenceScore(cps=1.0, es=1.0, ps=0.5, mi=1.0, utilization=0.0)`
146
- - `get_mi_color(mi) → str` — returns "green"/"yellow"/"red" using hardcoded thresholds (0.65/0.35)
147
- - `format_mi_score(mi) → str` — returns "0.82"
148
-
149
- Constants (hardcoded, not configurable):
150
- ```python
151
- MI_WEIGHT_CPS = 0.60
152
- MI_WEIGHT_ES = 0.25
153
- MI_WEIGHT_PS = 0.15
154
- MI_GREEN_THRESHOLD = 0.65
155
- MI_YELLOW_THRESHOLD = 0.35
156
- MI_PRODUCTIVITY_TARGET = 0.2
157
- ```
158
-
159
- ### Step 2: Create `tests/python/test_intelligence.py`
160
-
161
- Unit tests for all functions:
162
- - **CPS**: empty/full/half context, custom beta, clamping at 0
163
- - **CPS guard**: `context_window_size == 0` returns MI=1.0 with defaults
164
- - **ES**: no tokens, all cache read, no cache, mixed cache
165
- - **PS**: no previous entry, no output, high/zero/moderate productivity, capping
166
- - **PS deltas**: verify consecutive entry diff computation (not cumulative)
167
- - **Composite**: optimal/worst conditions, weight validation, bounds check
168
- - **Color**: green/yellow/red thresholds, boundary values
169
- - **Format**: two decimals, zero, one, rounding
170
- - **Statusline integration**: `show_mi=true` + `show_delta=false` produces MI output without delta display
171
-
172
- ### Step 2b: Create `tests/fixtures/mi_test_vectors.json`
173
-
174
- Shared test vectors for cross-implementation parity:
175
- ```json
176
- [
177
- {
178
- "description": "Fresh session",
179
- "input": { "current_used": 20000, "context_window": 200000, "cache_read": 12000, "current_input": 5000, "cache_creation": 3000, "prev_lines_added": 0, "prev_lines_removed": 0, "cur_lines_added": 150, "cur_lines_removed": 10, "prev_output": 0, "cur_output": 1000, "beta": 1.5 },
180
- "expected": { "cps": 0.968, "es": 0.72, "ps": 0.84, "mi": 0.887 }
181
- }
182
- ]
183
- ```
184
-
185
- 5-6 vectors covering: fresh session, mid-session, late session, no previous entry, context_window=0, no cache. Both Python and Node.js test suites read this file and assert results within ±0.01 tolerance.
186
-
187
- ### Step 3: Modify `src/claude_statusline/core/config.py`
188
-
189
- Add to `Config` dataclass (only 2 new fields):
190
- - `show_mi: bool = True`
191
- - `mi_curve_beta: float = 1.5`
192
-
193
- All other MI parameters (weights, thresholds, productivity_target) are **hardcoded constants** in `intelligence.py`, not configurable. This minimizes cross-implementation sync burden (2 config branches vs 8).
194
-
195
- Add parsing in `_read_config()`:
196
- - `show_mi`: boolean, same pattern as existing keys (`value_lower != "false"`)
197
- - `mi_curve_beta`: float, inline `try/except` — `try: self.mi_curve_beta = float(raw_value) except ValueError: pass`
198
-
199
- Add MI section to `_create_default()` config template:
200
- ```ini
201
- # Model Intelligence (MI) score display
202
- show_mi=true
203
-
204
- # MI degradation curve shape (higher = steeper initial drop)
205
- # mi_curve_beta=1.5
206
- ```
207
-
208
- Update `to_dict()` with both new fields.
209
-
210
- ### Step 4: Modify `src/claude_statusline/cli/statusline.py`
211
-
212
- **Key change:** Decouple state file reads from `show_delta`. Currently, the previous entry is only read inside `if config.show_delta:`. With MI, the previous entry must be read whenever `show_mi` OR `show_delta` is enabled.
213
-
214
- Restructure the state file logic:
215
- ```python
216
- # Read previous entry if needed for delta OR MI
217
- if config.show_delta or config.show_mi:
218
- state_file = StateFile(session_id)
219
- prev_entry = state_file.read_last_entry()
220
- # ... build current entry, append if changed ...
221
-
222
- if config.show_delta:
223
- # ... existing delta_info logic ...
224
-
225
- if config.show_mi:
226
- from claude_statusline.graphs.intelligence import calculate_intelligence, get_mi_color, format_mi_score
227
- mi_score = calculate_intelligence(entry, prev_entry, total_size, config.mi_curve_beta)
228
- mi_color_name = get_mi_color(mi_score.mi)
229
- mi_color = getattr(colors, mi_color_name)
230
- mi_info = f" {mi_color}MI:{format_mi_score(mi_score.mi)}{colors.reset}"
231
- ```
232
-
233
- Add `mi_info` to the output parts list (between `delta_info` and `ac_info`). Color-code using `get_mi_color()`.
234
-
235
- ### Step 5: Modify `src/claude_statusline/graphs/renderer.py`
236
-
237
- **Two changes:**
238
-
239
- **5a.** Add optional `label_fn: Callable[[int], str] | None = None` parameter to `render_timeseries()`. When provided, use it instead of `format_tokens()` for Y-axis labels. This allows the MI graph to display `0.62` instead of `620` when data is scaled ×1000. Default behavior (existing graphs) is unchanged.
240
-
241
- **5b.** In `render_summary()` (~line 318, after zone indicator), add MI score display:
242
- ```
243
- Model Intelligence: 0.62 (Context pressure is degrading answer quality)
244
- CPS: 0.54 ES: 0.72 PS: 0.60
245
- ```
246
- Accepts an optional `IntelligenceScore` parameter.
247
-
248
- ### Step 6: Modify `src/claude_statusline/cli/context_stats.py`
249
-
250
- - Add `"mi"` to `--type` choices
251
- - In `render_once()`: compute MI scores for each entry pair and render as timeseries graph (scale ×1000 for integer renderer)
252
- - Use `label_fn=lambda v: f"{v/1000:.2f}"` when calling `render_timeseries()` for the MI graph
253
- - Include MI in `"all"` graph type
254
- - Pass MI score to `render_summary()`
255
-
256
- ### Step 7: Modify `scripts/statusline.py` (standalone)
257
-
258
- Add a single self-contained `compute_mi()` function (not 4 separate functions) that takes raw values and returns `(mi, cps, es, ps)`. This reduces the sync surface from 4 functions to 1.
259
-
260
- ```python
261
- def compute_mi(used_tokens, context_window_size, cache_read, total_context,
262
- delta_lines, delta_output, beta=1.5):
263
- """Compute Model Intelligence score. Returns (mi, cps, es, ps)."""
264
- ...
265
- ```
266
-
267
- Add `show_mi` and `mi_curve_beta` config parsing (2 keys, matching the package). Add `MI:X.XX` to output. Decouple state file read from `show_delta` (same restructuring as Step 4).
268
-
269
- ### Step 8: Modify `scripts/statusline.js` (standalone Node.js)
270
-
271
- Port MI formula as a single `computeMI()` function (same signature as Python). Add `show_mi` and `mi_curve_beta` config parsing. Add `MI:X.XX` to output. Decouple state file read from `showDelta`.
272
-
273
- ```javascript
274
- function computeMI(usedTokens, contextWindowSize, cacheRead, totalContext,
275
- deltaLines, deltaOutput, beta = 1.5) {
276
- // Returns { mi, cps, es, ps }
277
- }
278
- ```
279
-
280
- ### Step 9: Add Node.js tests and shared test vectors
281
-
282
- - Create `tests/fixtures/mi_test_vectors.json` with 5-6 test vectors
283
- - Port core MI formula tests to `tests/node/intelligence.test.js`, reading from shared vectors
284
- - Update `tests/python/test_intelligence.py` to also read from shared vectors
285
- - Ensures cross-implementation parity within ±0.01 tolerance
286
-
287
- ## Critical Files
288
-
289
- | File | Action | Description |
290
- |---|---|---|
291
- | `src/claude_statusline/graphs/intelligence.py` | **Create** | Core MI computation module (hardcoded constants + configurable beta) |
292
- | `tests/python/test_intelligence.py` | **Create** | Unit tests for MI module (incl. guard clause, integration tests) |
293
- | `tests/fixtures/mi_test_vectors.json` | **Create** | Shared test vectors for cross-implementation parity |
294
- | `src/claude_statusline/core/config.py` | **Modify** | Add `show_mi` (bool) and `mi_curve_beta` (float) only |
295
- | `src/claude_statusline/cli/statusline.py` | **Modify** | Add MI score; decouple state read from `show_delta` |
296
- | `src/claude_statusline/cli/context_stats.py` | **Modify** | Add `--type mi` graph option |
297
- | `src/claude_statusline/graphs/renderer.py` | **Modify** | Add `label_fn` param to `render_timeseries()`; add MI to summary |
298
- | `scripts/statusline.py` | **Modify** | Single `compute_mi()` function; decouple state read |
299
- | `scripts/statusline.js` | **Modify** | Single `computeMI()` function; decouple state read |
300
- | `tests/node/intelligence.test.js` | **Create** | Node.js MI tests using shared vectors |
301
-
302
- ## Existing Utilities to Reuse
303
-
304
- - `StateEntry.current_used_tokens` property (`core/state.py:132`) — already computes `current_input_tokens + cache_creation + cache_read` (used for both CPS utilization and ES total_context)
305
- - `ColorManager` (`core/colors.py`) — for MI color coding
306
- - `fit_to_width()` (`formatters/layout.py`) — for statusline width management
307
- - `Config.load()` pattern (`core/config.py`) — extended with 2 new fields
308
- - `GraphRenderer.render_timeseries()` (`graphs/renderer.py`) — for MI graph (extended with `label_fn` parameter)
309
-
310
- **Not used**: `format_tokens()` — MI uses its own `f"{mi:.2f}"` format. `calculate_deltas()` — MI computes its own consecutive entry diffs internally.
311
-
312
- ## Configuration Options
313
-
314
- Only 2 config keys are exposed (weights, thresholds, and productivity target are hardcoded constants to minimize cross-implementation sync burden):
315
-
316
- ```ini
317
- # Model Intelligence (MI) score display
318
- # Shows a heuristic quality score based on context utilization
319
- show_mi=true
320
-
321
- # MI degradation curve shape (higher = steeper initial drop)
322
- # Based on Michelangelo paper's observed performance degradation
323
- # mi_curve_beta=1.5
324
- ```
325
-
326
- Hardcoded constants (in `intelligence.py`, `compute_mi()`, and `computeMI()`):
327
- - Weights: CPS=0.60, ES=0.25, PS=0.15
328
- - Thresholds: green > 0.65, yellow > 0.35, red below
329
- - Productivity target: 0.2 lines/token
330
-
331
- ## Display Integration
332
-
333
- ### Statusline output
334
-
335
- ```text
336
- [Opus] myproject | main [3] | 75k free (37.5%) [+2,500] MI:0.62 [AC:45k] abc123
337
- ```
338
-
339
- ### Context Stats CLI summary
340
-
341
- ```text
342
- Session Summary
343
- ────────────────────────────────────────────────
344
- Context Remaining: 75,000/200,000 (37%)
345
- >>> DUMB ZONE <<< (You are in the dumb zone - Dex Horthy says so)
346
- Model Intelligence: 0.62 (Context pressure is degrading answer quality)
347
- CPS: 0.54 ES: 0.72 PS: 0.60
348
- ```
349
-
350
- ### Context Stats MI graph (`--type mi`)
351
-
352
- ASCII timeseries graph of MI score over time, showing the degradation trajectory.
353
-
354
- ## Verification
355
-
356
- 1. **Unit tests**: `pytest tests/python/test_intelligence.py -v`
357
- 2. **All Python tests**: `source venv/bin/activate && pytest tests/python/ -v`
358
- 3. **Node.js tests**: `npm test` (includes `intelligence.test.js` with shared vectors)
359
- 4. **Cross-implementation parity**: Both Python and Node.js test suites read `tests/fixtures/mi_test_vectors.json` and assert results within ±0.01
360
- 5. **Manual statusline test**: Pipe JSON to statusline and verify `MI:X.XX` appears
361
- 6. **Manual statusline test (decoupled)**: Set `show_mi=true` + `show_delta=false` and verify MI appears without delta
362
- 7. **Manual context-stats test**: `context-stats --type mi --no-watch` — verify MI graph renders with decimal Y-axis labels
363
-
364
- ## Known Limitations
365
-
366
- 1. **Productivity Score is noisy for non-coding sessions** — Research/planning sessions have low PS even with high-quality answers. Mitigation: PS has lowest weight (0.15) and floor of 0.2.
367
-
368
- 2. **Cache hit ratio reflects API behavior, not reasoning quality** — Cache management is infrastructure, not model intelligence. Mitigation: ES weight is moderate (0.25) and presented as a heuristic proxy.
369
-
370
- 3. **Degradation curve is not calibrated to specific models** — The paper found different curves per model family. Mitigation: `mi_curve_beta` is configurable.
371
-
372
- 4. **Integer graph renderer** — MI scores (floats [0,1]) are scaled to [0, 1000] for the integer-based renderer, with Y-axis labels formatted as decimals via `label_fn`.
373
-
374
- 5. **MI adds file I/O when show_delta=false** — When `show_mi=true` and `show_delta=false`, the statusline reads the previous entry for PS calculation. Users who need minimal I/O can set `show_mi=false`.
375
-
376
- ## Review Decisions Log
377
-
378
- Decisions made during engineering review (2026-03-14):
379
-
380
- | # | Decision | Resolution |
381
- |---|---|---|
382
- | 1 | PS delta definition | Consecutive entry diffs (not cumulative totals) |
383
- | 2 | CPS division by zero | Guard clause: return MI=1.0 when context_window_size=0 |
384
- | 3 | MI vs show_delta coupling | Decoupled — MI reads prev entry independently |
385
- | 4 | Config surface area | Only `show_mi` + `mi_curve_beta` (hardcode the rest) |
386
- | 5 | MI formula DRY | Single `compute_mi()` / `computeMI()` in standalone scripts |
387
- | 6 | Module location | Keep in `graphs/` next to `statistics.py` |
388
- | 7 | Float config parsing | Inline try/except for `mi_curve_beta` |
389
- | 8 | MI graph Y-axis | Add `label_fn` parameter to `render_timeseries()` |
390
- | 9 | Cross-impl parity | Shared `tests/fixtures/mi_test_vectors.json` |
391
-
392
- ## TODOs (deferred)
393
-
394
- - **Shared test vectors**: Create `tests/fixtures/mi_test_vectors.json` with 5-6 vectors for cross-implementation parity (agreed during review, to be built during implementation)
395
- - **MI trend indicators**: Show `MI:0.62↓` or `MI:0.82↑` in statusline based on comparison with previous MI score (deferred — adds cross-impl sync burden)
396
- - **Per-model beta calibration**: Map known model IDs to empirically tuned beta values (deferred — requires empirical data we don't have yet)
@@ -1,118 +0,0 @@
1
- # Configuration
2
-
3
- The configuration file `~/.claude/statusline.conf` is automatically created with default settings on first run.
4
-
5
- Windows location: `%USERPROFILE%\.claude\statusline.conf`
6
-
7
- ## Settings
8
-
9
- ```bash
10
- # Autocompact setting - sync with Claude Code's /config
11
- autocompact=true # (default) Show reserved buffer for compacting
12
- autocompact=false # When autocompact is disabled via /config
13
-
14
- # Token display format
15
- token_detail=true # (default) Show exact token count: 64,000 free
16
- token_detail=false # Show abbreviated tokens: 64.0k free
17
-
18
- # Show token delta since last refresh
19
- show_delta=true # (default) Show delta like [+2,500]
20
- show_delta=false # Disable delta display
21
-
22
- # Show session_id in status line
23
- show_session=true # (default) Show session ID
24
- show_session=false # Hide session ID
25
-
26
- # Disable rotating text animations
27
- reduced_motion=false # (default) Animations enabled
28
- reduced_motion=true # Disable animations for accessibility
29
- ```
30
-
31
- ## Status Line Components
32
-
33
- ```
34
- [Opus 4.5] my-project | main [3] | 64,000 free (32.0%) [+2,500] [AC:45k] session_id
35
- ```
36
-
37
- | Component | Description | Color |
38
- | ------------- | ------------------------ | ---------------- |
39
- | `[Opus 4.5]` | Current AI model | Dim |
40
- | `my-project` | Current directory | Blue |
41
- | `main` | Git branch | Magenta |
42
- | `[3]` | Uncommitted changes | Cyan |
43
- | `64,000 free` | Available tokens | Green/Yellow/Red |
44
- | `(32.0%)` | Context usage percentage | - |
45
- | `[+2,500]` | Token delta | - |
46
- | `[AC:45k]` | Autocompact buffer | Dim |
47
- | `session_id` | Current session | Dim |
48
-
49
- ## Token Colors
50
-
51
- Context availability is color-coded:
52
-
53
- | Availability | Color |
54
- | ------------ | ------ |
55
- | > 50% | Green |
56
- | > 25% | Yellow |
57
- | <= 25% | Red |
58
-
59
- ## Autocompact Display
60
-
61
- - `[AC:45k]` - Autocompact enabled, 45k tokens reserved
62
- - `[AC:off]` - Autocompact disabled
63
-
64
- ## Token Display Formats
65
-
66
- | Setting | Display |
67
- | -------------------- | -------------------------------- |
68
- | `token_detail=true` | `64,000 free (32.0%)` `[+2,500]` |
69
- | `token_detail=false` | `64.0k free (32.0%)` `[+2.5k]` |
70
-
71
- ## Token Delta
72
-
73
- The `[+X,XXX]` indicator shows tokens consumed since last refresh:
74
-
75
- - Only positive deltas are shown
76
- - First run shows no delta (no baseline yet)
77
- - Each session has its own state file to avoid conflicts
78
-
79
- ## Session ID
80
-
81
- The session ID at the end helps:
82
-
83
- - Identify sessions when running multiple Claude Code instances
84
- - Correlate logs with specific sessions
85
- - Debug session-specific issues
86
-
87
- Double-click to select and copy. Set `show_session=false` to hide.
88
-
89
- ## Custom Colors
90
-
91
- Override any status line color with named colors or hex codes:
92
-
93
- ```bash
94
- # Available slots
95
- color_green=#7dcfff # Context >50% free
96
- color_yellow=bright_yellow # Context 25-50% free
97
- color_red=#f7768e # Context <25% free
98
- color_blue=bright_blue # Directory name
99
- color_magenta=#bb9af7 # Git branch
100
- color_cyan=bright_cyan # Git change count
101
- ```
102
-
103
- ### Supported color values
104
-
105
- **Named colors**: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `bright_black`, `bright_red`, `bright_green`, `bright_yellow`, `bright_blue`, `bright_magenta`, `bright_cyan`, `bright_white`
106
-
107
- **Hex colors**: Any `#rrggbb` value (requires terminal with 24-bit color support)
108
-
109
- Unrecognized color values are ignored with a warning to stderr. Omitted slots use defaults.
110
-
111
- ## Config File Format
112
-
113
- The config file uses simple `key=value` syntax:
114
-
115
- - No spaces around `=`
116
- - Lines starting with `#` are comments
117
- - Unrecognized keys are ignored
118
- - Missing keys use defaults shown above
@@ -1,143 +0,0 @@
1
- # Context Stats
2
-
3
- Real-time context monitoring for Claude Code sessions. Know when you're in the Smart Zone, Dumb Zone, or Wrap Up Zone.
4
-
5
- ## Context Zones
6
-
7
- Context Stats tracks your context usage and warns you as performance degrades:
8
-
9
- | Zone | Context Used | Status | Message |
10
- | ------------------- | ------------ | -------- | ----------------------------------------------- |
11
- | 🟢 **Smart Zone** | < 40% | Optimal | "You are in the smart zone" |
12
- | 🟡 **Dumb Zone** | 40-80% | Degraded | "You are in the dumb zone - Dex Horthy says so" |
13
- | 🔴 **Wrap Up Zone** | > 80% | Critical | "Better to wrap up and start a new session" |
14
-
15
- ## Usage
16
-
17
- By default, `context-stats` runs in live monitoring mode:
18
-
19
- ```bash
20
- # Live monitoring (default, refreshes every 2s)
21
- context-stats
22
-
23
- # Custom refresh interval
24
- context-stats -w 5
25
-
26
- # Show once and exit
27
- context-stats --no-watch
28
-
29
- # Show specific session
30
- context-stats <session_id>
31
- ```
32
-
33
- ### Graph Types
34
-
35
- ```bash
36
- context-stats --type delta # Context growth per interaction (default)
37
- context-stats --type cumulative # Total context usage over time
38
- context-stats --type both # Show both graphs
39
- context-stats --type io # Input/output token breakdown
40
- context-stats --type all # Show all graphs
41
- ```
42
-
43
- ### Diagnostic Dump
44
-
45
- The `explain` command shows how cc-context-stats interprets Claude Code's JSON context. Pipe any session JSON to stdin:
46
-
47
- ```bash
48
- echo '{"model":{"display_name":"Opus"},...}' | context-stats explain
49
- echo '{"model":{"display_name":"Opus"},...}' | context-stats explain --no-color
50
- ```
51
-
52
- Output includes model info, workspace, context window breakdown with derived values (free tokens, autocompact buffer), cost, session metadata, vim/agent extensions, active config, and raw JSON.
53
-
54
- ## Output
55
-
56
- ```
57
- Context Stats (my-project • abc123def)
58
-
59
- Context Growth Per Interaction
60
- Max: 4,787 Min: 0 Points: 254
61
-
62
- 4,787 │ ●
63
- │ ● ▒
64
- │ ●● ● ▒ ░
65
- │ ● ░ ░
66
- 2,052 │ ░ ● ● ● ░ ░ ●
67
- │ ░ ▒ ● ● ● ● ● ● ●░ ░ ▒ ●●
68
- │●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●
69
- 0 │●●●●●░▒●●●●▒▒●●▒░●●░▒▒▒▒▒●●●▒●▒●●▒●▒░●●▒●░●●▒●▒▒●▒
70
- └─────────────────────────────────────────────────
71
- 10:40 11:29 12:01
72
-
73
- Session Summary
74
- ----------------------------------------------------------------------------
75
- >>> DUMB ZONE <<< (You are in the dumb zone - Dex Horthy says so)
76
-
77
- Context Remaining: 43,038 (21%)
78
- Input Tokens: 59,015
79
- Output Tokens: 43,429
80
- Session Duration: 2h 29m
81
-
82
- Powered by cc-context-stats v1.8.0 - https://github.com/luongnv89/cc-context-stats
83
- ```
84
-
85
- ## Features
86
-
87
- - **Live Monitoring**: Automatic refresh every 2 seconds (configurable)
88
- - **Zone Awareness**: Color-coded status based on context usage
89
- - **Project Display**: Shows project name and session ID
90
- - **ASCII Graphs**: Smooth area charts with gradient fills
91
- - **Minimal Output**: Clean summary with just the essential info
92
-
93
- ## Graph Symbols
94
-
95
- | Symbol | Meaning |
96
- | ------ | ----------------------- |
97
- | `●` | Trend line |
98
- | `▒` | Medium fill (near line) |
99
- | `░` | Light fill (area below) |
100
- | `│` | Y-axis |
101
- | `└─` | X-axis |
102
-
103
- ## Watch Mode
104
-
105
- By default, context-stats runs in watch mode. Press `Ctrl+C` to exit.
106
-
107
- Features:
108
-
109
- - **Flicker-free updates**: Uses cursor repositioning for smooth redraws
110
- - **Live timestamp**: Shows refresh indicator in header
111
- - **Hidden cursor**: Clean display without cursor blinking
112
- - **Auto-adapt**: Responds to terminal size changes
113
-
114
- To disable watch mode and show graphs once:
115
-
116
- ```bash
117
- context-stats --no-watch
118
- ```
119
-
120
- ## Data Source
121
-
122
- Reads from `~/.claude/statusline/statusline.<session_id>.state` files, automatically created by the status line script.
123
-
124
- ## CLI Reference
125
-
126
- ```
127
- context-stats [session_id] [options]
128
-
129
- ARGUMENTS:
130
- session_id Optional session ID. If not provided, uses the latest session.
131
-
132
- OPTIONS:
133
- --type <type> Graph type to display:
134
- - delta: Context growth per interaction (default)
135
- - cumulative: Total context usage over time
136
- - io: Input/output tokens over time
137
- - both: Show cumulative and delta graphs
138
- - all: Show all graphs including I/O
139
- -w [interval] Set refresh interval in seconds (default: 2)
140
- --no-watch Show graphs once and exit (disable live monitoring)
141
- --no-color Disable color output
142
- --help Show help message
143
- ```