ccstatusline 2.1.6 → 2.1.7

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/README.md CHANGED
@@ -46,15 +46,16 @@
46
46
 
47
47
  ## 🆕 Recent Updates
48
48
 
49
- ### v2.1.0 - v2.1.6 - Usage widgets, links, new git insertions / deletions widgets, and reliability fixes
49
+ ### v2.1.0 - v2.1.7 - Usage widgets, links, new git insertions / deletions widgets, and reliability fixes
50
50
 
51
- - **🧩 New Usage widgets (v2.1.0)** - Added **Session Usage**, **Weekly Usage**, **Reset Timer**, and **Context Bar** widgets.
51
+ - **🧩 New Usage widgets (v2.1.0)** - Added **Session Usage**, **Weekly Usage**, **Block Reset Timer**, and **Context Bar** widgets.
52
52
  - **📊 More accurate counts (v2.1.0)** - Usage/context widgets now use new statusline JSON metrics when available for more accurate token and context counts.
53
53
  - **🪟 Windows empty file bug fix (v2.1.1)** - Fixed a Windows issue that could create an empty `c:\dev\null` file.
54
54
  - **🔗 New Link widget (v2.1.3)** - Added a new **Link** widget with clickable OSC8 rendering, preview parity, and raw mode support.
55
55
  - **➕ New Git Insertions widget (v2.1.4)** - Added a dedicated Git widget that shows only uncommitted insertions (e.g., `+42`).
56
56
  - **➖ New Git Deletions widget (v2.1.4)** - Added a dedicated Git widget that shows only uncommitted deletions (e.g., `-10`).
57
57
  - **🧠 Context format fallback fix (v2.1.6)** - When `context_window_size` is missing, context widgets now infer 1M models from long-context labels such as `[1m]` and `1M context` in model identifiers.
58
+ - **⏳ Weekly reset timer split (v2.1.7)** - Added a separate `Weekly Reset Timer` widget.
58
59
 
59
60
  ### v2.0.26 - v2.0.29 - Performance, git internals, and workflow improvements
60
61
 
@@ -426,7 +427,8 @@ bun run example
426
427
  - **Session Name** - Shows the session name set via `/rename` command in Claude Code
427
428
  - **Claude Session ID** - Shows the current Claude Code session ID from status JSON
428
429
  - **Block Timer** - Shows time elapsed in current 5-hour block or progress bar
429
- - **Reset Timer** - Shows time remaining until the current 5-hour block resets
430
+ - **Block Reset Timer** - Shows time remaining until the current 5-hour block resets
431
+ - **Weekly Reset Timer** - Shows time remaining until the weekly usage window resets
430
432
  - **Current Working Directory** - Shows current working directory with segment limit, fish-style abbreviation, and optional `~` home abbreviation
431
433
  - **Version** - Shows Claude Code version
432
434
  - **Output Style** - Shows the currently set output style in Claude Code
@@ -528,6 +530,8 @@ Widget-specific shortcuts:
528
530
  - **Git widgets**: `h` toggle hide `no git` output
529
531
  - **Context % widgets**: `u` toggle used vs remaining display
530
532
  - **Block Timer**: `p` cycle display mode (time/full bar/short bar)
533
+ - **Block Reset Timer**: `p` cycle display mode (time/full bar/short bar)
534
+ - **Weekly Reset Timer**: `p` cycle display mode (time/full bar/short bar)
531
535
  - **Current Working Dir**: `h` home abbreviation, `s` segment editor, `f` fish-style path
532
536
  - **Custom Command**: `e` command, `w` max width, `t` timeout, `p` preserve ANSI colors
533
537
  - **Link**: `u` URL, `e` link text
@@ -51478,7 +51478,7 @@ import { execSync as execSync3 } from "child_process";
51478
51478
  import * as fs5 from "fs";
51479
51479
  import * as path4 from "path";
51480
51480
  var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
51481
- var PACKAGE_VERSION = "2.1.6";
51481
+ var PACKAGE_VERSION = "2.1.7";
51482
51482
  function getPackageVersion() {
51483
51483
  if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
51484
51484
  return PACKAGE_VERSION;
@@ -55690,12 +55690,14 @@ var CACHE_MAX_AGE = 180;
55690
55690
  var LOCK_MAX_AGE = 30;
55691
55691
  var TOKEN_CACHE_MAX_AGE = 3600;
55692
55692
  var FIVE_HOUR_BLOCK_MS = 5 * 60 * 60 * 1000;
55693
+ var SEVEN_DAY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
55693
55694
  var UsageErrorSchema = exports_external.enum(["no-credentials", "timeout", "api-error", "parse-error"]);
55694
55695
  var UsageCredentialsSchema = exports_external.object({ claudeAiOauth: exports_external.object({ accessToken: exports_external.string().nullable().optional() }).optional() });
55695
55696
  var CachedUsageDataSchema = exports_external.object({
55696
55697
  sessionUsage: exports_external.number().nullable().optional(),
55697
55698
  sessionResetAt: exports_external.string().nullable().optional(),
55698
55699
  weeklyUsage: exports_external.number().nullable().optional(),
55700
+ weeklyResetAt: exports_external.string().nullable().optional(),
55699
55701
  extraUsageEnabled: exports_external.boolean().nullable().optional(),
55700
55702
  extraUsageLimit: exports_external.number().nullable().optional(),
55701
55703
  extraUsageUsed: exports_external.number().nullable().optional(),
@@ -55705,10 +55707,12 @@ var CachedUsageDataSchema = exports_external.object({
55705
55707
  var UsageApiResponseSchema = exports_external.object({
55706
55708
  five_hour: exports_external.object({
55707
55709
  utilization: exports_external.number().nullable().optional(),
55708
- reset_at: exports_external.string().nullable().optional(),
55709
55710
  resets_at: exports_external.string().nullable().optional()
55710
55711
  }).optional(),
55711
- seven_day: exports_external.object({ utilization: exports_external.number().nullable().optional() }).optional(),
55712
+ seven_day: exports_external.object({
55713
+ utilization: exports_external.number().nullable().optional(),
55714
+ resets_at: exports_external.string().nullable().optional()
55715
+ }).optional(),
55712
55716
  extra_usage: exports_external.object({
55713
55717
  is_enabled: exports_external.boolean().nullable().optional(),
55714
55718
  monthly_limit: exports_external.number().nullable().optional(),
@@ -55738,6 +55742,7 @@ function parseCachedUsageData(rawJson) {
55738
55742
  sessionUsage: parsed.sessionUsage ?? undefined,
55739
55743
  sessionResetAt: parsed.sessionResetAt ?? undefined,
55740
55744
  weeklyUsage: parsed.weeklyUsage ?? undefined,
55745
+ weeklyResetAt: parsed.weeklyResetAt ?? undefined,
55741
55746
  extraUsageEnabled: parsed.extraUsageEnabled ?? undefined,
55742
55747
  extraUsageLimit: parsed.extraUsageLimit ?? undefined,
55743
55748
  extraUsageUsed: parsed.extraUsageUsed ?? undefined,
@@ -55752,8 +55757,9 @@ function parseUsageApiResponse(rawJson) {
55752
55757
  }
55753
55758
  return {
55754
55759
  sessionUsage: parsed.five_hour?.utilization ?? undefined,
55755
- sessionResetAt: parsed.five_hour?.resets_at ?? parsed.five_hour?.reset_at ?? undefined,
55760
+ sessionResetAt: parsed.five_hour?.resets_at ?? undefined,
55756
55761
  weeklyUsage: parsed.seven_day?.utilization ?? undefined,
55762
+ weeklyResetAt: parsed.seven_day?.resets_at ?? undefined,
55757
55763
  extraUsageEnabled: parsed.extra_usage?.is_enabled ?? undefined,
55758
55764
  extraUsageLimit: parsed.extra_usage?.monthly_limit ?? undefined,
55759
55765
  extraUsageUsed: parsed.extra_usage?.used_credits ?? undefined,
@@ -55934,16 +55940,16 @@ function fetchUsageData() {
55934
55940
  function clamp(value, min, max) {
55935
55941
  return Math.max(min, Math.min(max, value));
55936
55942
  }
55937
- function buildUsageWindow(resetAtMs, nowMs) {
55938
- if (!Number.isFinite(resetAtMs) || !Number.isFinite(nowMs)) {
55943
+ function buildUsageWindow(resetAtMs, nowMs, durationMs) {
55944
+ if (!Number.isFinite(resetAtMs) || !Number.isFinite(nowMs) || !Number.isFinite(durationMs) || durationMs <= 0) {
55939
55945
  return null;
55940
55946
  }
55941
- const startAtMs = resetAtMs - FIVE_HOUR_BLOCK_MS;
55942
- const elapsedMs = clamp(nowMs - startAtMs, 0, FIVE_HOUR_BLOCK_MS);
55943
- const remainingMs = FIVE_HOUR_BLOCK_MS - elapsedMs;
55944
- const elapsedPercent = elapsedMs / FIVE_HOUR_BLOCK_MS * 100;
55947
+ const startAtMs = resetAtMs - durationMs;
55948
+ const elapsedMs = clamp(nowMs - startAtMs, 0, durationMs);
55949
+ const remainingMs = durationMs - elapsedMs;
55950
+ const elapsedPercent = elapsedMs / durationMs * 100;
55945
55951
  return {
55946
- sessionDurationMs: FIVE_HOUR_BLOCK_MS,
55952
+ sessionDurationMs: durationMs,
55947
55953
  elapsedMs,
55948
55954
  remainingMs,
55949
55955
  elapsedPercent,
@@ -55958,14 +55964,14 @@ function getUsageWindowFromResetAt(sessionResetAt, nowMs = Date.now()) {
55958
55964
  if (Number.isNaN(resetAtMs)) {
55959
55965
  return null;
55960
55966
  }
55961
- return buildUsageWindow(resetAtMs, nowMs);
55967
+ return buildUsageWindow(resetAtMs, nowMs, FIVE_HOUR_BLOCK_MS);
55962
55968
  }
55963
55969
  function getUsageWindowFromBlockMetrics(blockMetrics, nowMs = Date.now()) {
55964
55970
  const startAtMs = blockMetrics.startTime.getTime();
55965
55971
  if (Number.isNaN(startAtMs)) {
55966
55972
  return null;
55967
55973
  }
55968
- return buildUsageWindow(startAtMs + FIVE_HOUR_BLOCK_MS, nowMs);
55974
+ return buildUsageWindow(startAtMs + FIVE_HOUR_BLOCK_MS, nowMs, FIVE_HOUR_BLOCK_MS);
55969
55975
  }
55970
55976
  function resolveUsageWindowWithFallback(usageData, blockMetrics, nowMs = Date.now()) {
55971
55977
  const usageWindow = getUsageWindowFromResetAt(usageData.sessionResetAt, nowMs);
@@ -55978,6 +55984,19 @@ function resolveUsageWindowWithFallback(usageData, blockMetrics, nowMs = Date.no
55978
55984
  }
55979
55985
  return getUsageWindowFromBlockMetrics(fallbackMetrics, nowMs);
55980
55986
  }
55987
+ function getWeeklyUsageWindowFromResetAt(weeklyResetAt, nowMs = Date.now()) {
55988
+ if (!weeklyResetAt) {
55989
+ return null;
55990
+ }
55991
+ const resetAtMs = Date.parse(weeklyResetAt);
55992
+ if (Number.isNaN(resetAtMs)) {
55993
+ return null;
55994
+ }
55995
+ return buildUsageWindow(resetAtMs, nowMs, SEVEN_DAY_WINDOW_MS);
55996
+ }
55997
+ function resolveWeeklyUsageWindow(usageData, nowMs = Date.now()) {
55998
+ return getWeeklyUsageWindowFromResetAt(usageData.weeklyResetAt, nowMs);
55999
+ }
55981
56000
  function formatUsageDuration(durationMs) {
55982
56001
  const clampedMs = Math.max(0, durationMs);
55983
56002
  const elapsedHours = Math.floor(clampedMs / (1000 * 60 * 60));
@@ -56692,7 +56711,7 @@ class WeeklyUsageWidget {
56692
56711
  return true;
56693
56712
  }
56694
56713
  }
56695
- // src/widgets/ResetTimer.ts
56714
+ // src/widgets/BlockResetTimer.ts
56696
56715
  function makeTimerProgressBar2(percent, width) {
56697
56716
  const clampedPercent = Math.max(0, Math.min(100, percent));
56698
56717
  const filledWidth = Math.floor(clampedPercent / 100 * width);
@@ -56700,15 +56719,15 @@ function makeTimerProgressBar2(percent, width) {
56700
56719
  return "█".repeat(filledWidth) + "░".repeat(emptyWidth);
56701
56720
  }
56702
56721
 
56703
- class ResetTimerWidget {
56722
+ class BlockResetTimerWidget {
56704
56723
  getDefaultColor() {
56705
56724
  return "brightBlue";
56706
56725
  }
56707
56726
  getDescription() {
56708
- return "Shows time remaining until current 5hr block reset";
56727
+ return "Shows time remaining until current 5hr block reset window";
56709
56728
  }
56710
56729
  getDisplayName() {
56711
- return "Reset Timer";
56730
+ return "Block Reset Timer";
56712
56731
  }
56713
56732
  getCategory() {
56714
56733
  return "Usage";
@@ -56771,6 +56790,85 @@ class ResetTimerWidget {
56771
56790
  return true;
56772
56791
  }
56773
56792
  }
56793
+ // src/widgets/WeeklyResetTimer.ts
56794
+ function makeTimerProgressBar3(percent, width) {
56795
+ const clampedPercent = Math.max(0, Math.min(100, percent));
56796
+ const filledWidth = Math.floor(clampedPercent / 100 * width);
56797
+ const emptyWidth = width - filledWidth;
56798
+ return "█".repeat(filledWidth) + "░".repeat(emptyWidth);
56799
+ }
56800
+
56801
+ class WeeklyResetTimerWidget {
56802
+ getDefaultColor() {
56803
+ return "brightBlue";
56804
+ }
56805
+ getDescription() {
56806
+ return "Shows time remaining until weekly usage reset";
56807
+ }
56808
+ getDisplayName() {
56809
+ return "Weekly Reset Timer";
56810
+ }
56811
+ getCategory() {
56812
+ return "Usage";
56813
+ }
56814
+ getEditorDisplay(item) {
56815
+ return {
56816
+ displayText: this.getDisplayName(),
56817
+ modifierText: getUsageDisplayModifierText(item)
56818
+ };
56819
+ }
56820
+ handleEditorAction(action, item) {
56821
+ if (action === "toggle-progress") {
56822
+ return cycleUsageDisplayMode(item);
56823
+ }
56824
+ if (action === "toggle-invert") {
56825
+ return toggleUsageInverted(item);
56826
+ }
56827
+ return null;
56828
+ }
56829
+ render(item, context, settings) {
56830
+ const displayMode = getUsageDisplayMode(item);
56831
+ const inverted = isUsageInverted(item);
56832
+ if (context.isPreview) {
56833
+ const previewPercent = inverted ? 90 : 10;
56834
+ if (isUsageProgressMode(displayMode)) {
56835
+ const barWidth = getUsageProgressBarWidth(displayMode);
56836
+ const progressBar = makeTimerProgressBar3(previewPercent, barWidth);
56837
+ return formatRawOrLabeledValue(item, "Weekly Reset ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
56838
+ }
56839
+ return formatRawOrLabeledValue(item, "Weekly Reset: ", "36hr 30m");
56840
+ }
56841
+ const usageData = fetchUsageData();
56842
+ const window2 = resolveWeeklyUsageWindow(usageData);
56843
+ if (!window2) {
56844
+ if (usageData.error) {
56845
+ return getUsageErrorMessage(usageData.error);
56846
+ }
56847
+ return null;
56848
+ }
56849
+ if (isUsageProgressMode(displayMode)) {
56850
+ const barWidth = getUsageProgressBarWidth(displayMode);
56851
+ const percent = inverted ? window2.remainingPercent : window2.elapsedPercent;
56852
+ const progressBar = makeTimerProgressBar3(percent, barWidth);
56853
+ const percentage = percent.toFixed(1);
56854
+ return formatRawOrLabeledValue(item, "Weekly Reset ", `[${progressBar}] ${percentage}%`);
56855
+ }
56856
+ const remainingTime = formatUsageDuration(window2.remainingMs);
56857
+ return formatRawOrLabeledValue(item, "Weekly Reset: ", remainingTime);
56858
+ }
56859
+ getCustomKeybinds() {
56860
+ return [
56861
+ { key: "p", label: "(p)rogress toggle", action: "toggle-progress" },
56862
+ { key: "v", label: "in(v)ert fill", action: "toggle-invert" }
56863
+ ];
56864
+ }
56865
+ supportsRawValue() {
56866
+ return true;
56867
+ }
56868
+ supportsColors(item) {
56869
+ return true;
56870
+ }
56871
+ }
56774
56872
  // src/widgets/ContextBar.ts
56775
56873
  function getDisplayMode(item) {
56776
56874
  return item.metadata?.display === "progress" ? "progress" : "progress-short";
@@ -57078,7 +57176,8 @@ var widgetRegistry = new Map([
57078
57176
  ["free-memory", new FreeMemoryWidget],
57079
57177
  ["session-usage", new SessionUsageWidget],
57080
57178
  ["weekly-usage", new WeeklyUsageWidget],
57081
- ["reset-timer", new ResetTimerWidget],
57179
+ ["reset-timer", new BlockResetTimerWidget],
57180
+ ["weekly-reset-timer", new WeeklyResetTimerWidget],
57082
57181
  ["context-bar", new ContextBarWidget]
57083
57182
  ]);
57084
57183
  function getWidget(type) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstatusline",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "A customizable status line formatter for Claude Code CLI",
5
5
  "module": "src/ccstatusline.ts",
6
6
  "type": "module",