cc-context-stats 1.12.1 → 1.13.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-context-stats",
3
- "version": "1.12.1",
3
+ "version": "1.13.0",
4
4
  "description": "Monitor your Claude Code session context in real-time - track token usage and never run out of context",
5
5
  "main": "scripts/statusline.js",
6
6
  "bin": {
@@ -114,35 +114,49 @@ function getMIColor(mi, utilization, greenColor, yellowColor, redColor) {
114
114
  /**
115
115
  * Determine context zone indicator (P/C/D/X/Z) based on token usage.
116
116
  * Returns { zone, colorName }.
117
+ * zoneConfig is an optional object of threshold overrides (0 = use default).
117
118
  */
118
- function getContextZone(usedTokens, contextWindowSize) {
119
+ function getContextZone(usedTokens, contextWindowSize, zoneConfig) {
119
120
  if (contextWindowSize === 0) {
120
121
  return { zone: 'Plan', colorName: 'green' };
121
122
  }
122
123
 
123
- const isLarge = contextWindowSize >= LARGE_MODEL_THRESHOLD;
124
+ const zc = zoneConfig || {};
125
+
126
+ const lmt = zc.large_model_threshold || LARGE_MODEL_THRESHOLD;
127
+ const isLarge = contextWindowSize >= lmt;
124
128
 
125
129
  if (isLarge) {
126
- if (usedTokens < ZONE_1M_P_MAX) {
130
+ const pMax = zc.zone_1m_plan_max || ZONE_1M_P_MAX;
131
+ const cMax = zc.zone_1m_code_max || ZONE_1M_C_MAX;
132
+ const dMax = zc.zone_1m_dump_max || ZONE_1M_D_MAX;
133
+ const xMax = zc.zone_1m_xdump_max || ZONE_1M_X_MAX;
134
+
135
+ if (usedTokens < pMax) {
127
136
  return { zone: 'Plan', colorName: 'green' };
128
137
  }
129
- if (usedTokens < ZONE_1M_C_MAX) {
138
+ if (usedTokens < cMax) {
130
139
  return { zone: 'Code', colorName: 'yellow' };
131
140
  }
132
- if (usedTokens < ZONE_1M_D_MAX) {
141
+ if (usedTokens < dMax) {
133
142
  return { zone: 'Dump', colorName: 'orange' };
134
143
  }
135
- if (usedTokens < ZONE_1M_X_MAX) {
144
+ if (usedTokens < xMax) {
136
145
  return { zone: 'ExDump', colorName: 'dark_red' };
137
146
  }
138
147
  return { zone: 'Dead', colorName: 'gray' };
139
148
  }
140
149
 
141
- // Standard models (< 500k context)
142
- const dumpZoneTokens = Math.floor(contextWindowSize * ZONE_STD_DUMP_ZONE);
143
- const warnStart = Math.max(0, dumpZoneTokens - ZONE_STD_WARN_BUFFER);
144
- const hardLimitTokens = Math.floor(contextWindowSize * ZONE_STD_HARD_LIMIT);
145
- const deadZoneTokens = Math.floor(contextWindowSize * ZONE_STD_DEAD_ZONE);
150
+ // Standard models
151
+ const dumpRatio = zc.zone_std_dump_ratio || ZONE_STD_DUMP_ZONE;
152
+ const warnBuf = zc.zone_std_warn_buffer || ZONE_STD_WARN_BUFFER;
153
+ const hardLim = zc.zone_std_hard_limit || ZONE_STD_HARD_LIMIT;
154
+ const deadRat = zc.zone_std_dead_ratio || ZONE_STD_DEAD_ZONE;
155
+
156
+ const dumpZoneTokens = Math.floor(contextWindowSize * dumpRatio);
157
+ const warnStart = Math.max(0, dumpZoneTokens - warnBuf);
158
+ const hardLimitTokens = Math.floor(contextWindowSize * hardLim);
159
+ const deadZoneTokens = Math.floor(contextWindowSize * deadRat);
146
160
 
147
161
  if (usedTokens < warnStart) {
148
162
  return { zone: 'Plan', colorName: 'green' };
@@ -284,6 +298,23 @@ const COLOR_CONFIG_KEYS = {
284
298
  color_separator: 'separator',
285
299
  };
286
300
 
301
+ // Zone threshold config keys (integer token counts)
302
+ const ZONE_INT_KEYS = new Set([
303
+ 'zone_1m_plan_max',
304
+ 'zone_1m_code_max',
305
+ 'zone_1m_dump_max',
306
+ 'zone_1m_xdump_max',
307
+ 'zone_std_warn_buffer',
308
+ 'large_model_threshold',
309
+ ]);
310
+
311
+ // Zone threshold config keys (float ratios 0-1)
312
+ const ZONE_FLOAT_KEYS = new Set([
313
+ 'zone_std_dump_ratio',
314
+ 'zone_std_hard_limit',
315
+ 'zone_std_dead_ratio',
316
+ ]);
317
+
287
318
  /**
288
319
  * Return the visible width of a string after stripping ANSI escape sequences.
289
320
  */
@@ -393,6 +424,7 @@ function readConfig() {
393
424
  showMI: false,
394
425
  miCurveBeta: 0,
395
426
  colors: {},
427
+ zoneConfig: {},
396
428
  };
397
429
  const configPath = path.join(os.homedir(), '.claude', 'statusline.conf');
398
430
 
@@ -464,6 +496,24 @@ show_session=true
464
496
  if (ansi) {
465
497
  config.colors[COLOR_CONFIG_KEYS[keyTrimmed]] = ansi;
466
498
  }
499
+ } else if (ZONE_INT_KEYS.has(keyTrimmed)) {
500
+ const v = parseInt(rawValue, 10);
501
+ if (!isNaN(v) && v > 0) {
502
+ config.zoneConfig[keyTrimmed] = v;
503
+ } else {
504
+ process.stderr.write(
505
+ `[statusline] warning: ${keyTrimmed} must be a positive integer, ignoring '${rawValue}'\n`
506
+ );
507
+ }
508
+ } else if (ZONE_FLOAT_KEYS.has(keyTrimmed)) {
509
+ const v = parseFloat(rawValue);
510
+ if (!isNaN(v) && v > 0 && v < 1) {
511
+ config.zoneConfig[keyTrimmed] = v;
512
+ } else {
513
+ process.stderr.write(
514
+ `[statusline] warning: ${keyTrimmed} must be between 0 and 1, ignoring '${rawValue}'\n`
515
+ );
516
+ }
467
517
  }
468
518
  }
469
519
  } catch (e) {
@@ -572,7 +622,7 @@ process.stdin.on('end', () => {
572
622
  : `${(freeTokens / 1000).toFixed(1)}k`;
573
623
 
574
624
  // Zone indicator — determines color for both context info and zone label
575
- const zoneResult = getContextZone(usedTokens, totalSize);
625
+ const zoneResult = getContextZone(usedTokens, totalSize, config.zoneConfig);
576
626
  const zoneAnsi = zoneAnsiColor(zoneResult.colorName);
577
627
 
578
628
  // Context info uses zone color (traffic-light), with per-property override