cctally 1.20.0 → 1.20.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [1.20.1] - 2026-05-28
9
+
10
+ ### Fixed
11
+ - **`cctally statusline` now computes the `today` segment over your *local* calendar day, matching every other reporting command (`daily`, `monthly`, `weekly`, …).** Previously the statusline hardcoded the bottom rung of its `display.tz` precedence ladder to `"UTC"` when neither `--timezone` nor `display.tz` was set in config, while every sibling command defaulted to `"local"`. For any UTC-offset user (i.e. nearly everyone) this meant the statusline's `today` cost dropped any entries that fell in the post-local-midnight / pre-UTC-midnight band — typically several dollars at the start of each local day — and the statusline silently disagreed with `cctally daily --since today --until today`. The fix matches the default that every other command already uses; users who had explicitly set `display.tz = "UTC"` see no behavior change. (#86 G follow-up)
12
+
8
13
  ## [1.20.0] - 2026-05-28
9
14
 
10
15
  ### Added
@@ -55,7 +55,12 @@ class StatuslineArgs:
55
55
  context_medium_threshold: int
56
56
  cctally_extensions: bool
57
57
  color: bool # ANSI on/off after auto-detect resolved
58
- display_tz_name: str # IANA name; "UTC" if config absent
58
+ display_tz_name: str # IANA name; resolved upstream via
59
+ # get_display_tz_pref(cfg) — defaults to
60
+ # DISPLAY_TZ_DEFAULT ("local") when no config
61
+ # nor CLI override, then converted to a real
62
+ # IANA via _local_tz_name() before reaching
63
+ # the kernel.
59
64
  debug: bool
60
65
 
61
66
 
package/bin/cctally CHANGED
@@ -4493,6 +4493,41 @@ def cmd_blocks(args: argparse.Namespace) -> int:
4493
4493
  return 0
4494
4494
 
4495
4495
 
4496
+ def _resolve_statusline_tz(cli_tz, cfg, warn_once):
4497
+ """Resolve the IANA tz_name for cmd_statusline using the same 3-rung
4498
+ precedence as every other reporting command:
4499
+
4500
+ CLI ``--timezone`` > ``config.display.tz`` > DISPLAY_TZ_DEFAULT ("local")
4501
+
4502
+ "local" is converted to a real IANA via ``_local_tz_name()`` before
4503
+ returning. Unknown IANA names emit a one-shot warning and fall back
4504
+ to ``"UTC"``. Returns a real IANA name (or ``"UTC"``) — never the
4505
+ literal sentinel ``"local"``.
4506
+
4507
+ Prior to #86 G follow-up, this defaulted to ``"UTC"`` when no config
4508
+ was set, so ``today`` computed on the UTC calendar day while
4509
+ ``cctally daily`` (and every other reporting command) used the local
4510
+ day — UTC-offset users saw a multi-hour lag between statusline and
4511
+ daily. Regression: tests/test_statusline.py::TestTzResolution.
4512
+ """
4513
+ tz_name = cli_tz
4514
+ if not tz_name:
4515
+ tz_name = get_display_tz_pref(cfg)
4516
+ if tz_name in ("local", "LOCAL"):
4517
+ try:
4518
+ tz_name = _local_tz_name() or "UTC"
4519
+ except Exception:
4520
+ tz_name = "UTC"
4521
+ try:
4522
+ ZoneInfo(tz_name)
4523
+ except (ZoneInfoNotFoundError, Exception):
4524
+ warn_once(
4525
+ f"cctally statusline: invalid timezone {tz_name!r}; using 'UTC'"
4526
+ )
4527
+ tz_name = "UTC"
4528
+ return tz_name
4529
+
4530
+
4496
4531
  def cmd_statusline(args: argparse.Namespace) -> int:
4497
4532
  """`cctally statusline` — one-line status summary for CC hooks.
4498
4533
 
@@ -4601,27 +4636,7 @@ def cmd_statusline(args: argparse.Namespace) -> int:
4601
4636
  )
4602
4637
  ext_on = True
4603
4638
 
4604
- # Display tz: CLI -z/--timezone > display.tz config > "UTC".
4605
- tz_name = getattr(args, "timezone", None)
4606
- if not tz_name:
4607
- display_block = cfg.get("display") if isinstance(cfg, dict) else None
4608
- if isinstance(display_block, dict):
4609
- tz_name = display_block.get("tz")
4610
- if not tz_name:
4611
- tz_name = "UTC"
4612
- if tz_name in ("local", "LOCAL"):
4613
- try:
4614
- tz_name = _local_tz_name() or "UTC"
4615
- except Exception:
4616
- tz_name = "UTC"
4617
- # Validate the IANA name; fall back to UTC with a one-shot warning.
4618
- try:
4619
- ZoneInfo(tz_name)
4620
- except (ZoneInfoNotFoundError, Exception):
4621
- warn_once(
4622
- f"cctally statusline: invalid timezone {tz_name!r}; using 'UTC'"
4623
- )
4624
- tz_name = "UTC"
4639
+ tz_name = _resolve_statusline_tz(getattr(args, "timezone", None), cfg, warn_once)
4625
4640
 
4626
4641
  # Color: explicit CLI > NO_COLOR env > TTY detect.
4627
4642
  if args.color is True or args.color is False:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cctally",
3
- "version": "1.20.0",
3
+ "version": "1.20.1",
4
4
  "description": "Claude Code usage tracker and local dashboard for Pro/Max subscription limits - weekly cost-per-percent trend, quota forecasts, threshold alerts. ccusage-compatible.",
5
5
  "homepage": "https://github.com/omrikais/cctally",
6
6
  "repository": {