exe-watcher 0.2.14 → 0.2.16

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
@@ -2,7 +2,7 @@
2
2
  <img src="https://cdn.jsdelivr.net/gh/AskExe/exe-watcher@main/assets/owl-header.png" alt="WATCHER" width="520" />
3
3
  </p>
4
4
 
5
- <p align="center"><strong>The fuel gauge for your AI coding day — by <a href="https://github.com/AskExe">Exe AI</a>.</strong></p>
5
+ <p align="center"><strong>Real-time AI spend tracker for developers — by <a href="https://github.com/AskExe">Exe AI</a>.</strong></p>
6
6
 
7
7
  <p align="center">
8
8
  <a href="https://www.npmjs.com/package/exe-watcher"><img src="https://img.shields.io/npm/v/exe-watcher.svg" alt="npm version" /></a>
@@ -16,7 +16,7 @@
16
16
  <img src="https://raw.githubusercontent.com/AskExe/exe-watcher/main/assets/dashboard.jpg" alt="Watcher TUI dashboard" width="620" />
17
17
  </p>
18
18
 
19
- You're spending real money on AI coding tools every day. Watcher shows you exactly where it goes — cost, tokens, models, projects, and whether the AI is getting it right the first time or burning through retry loops. One command, zero cloud, everything local.
19
+ 8 providers. 5 time periods. 17 currencies. Every dollar your AI coding tools spend, tracked automatically from local session data. No API keys, no cloud, no wrappers.
20
20
 
21
21
  ```bash
22
22
  npm install -g exe-watcher
@@ -24,37 +24,75 @@ npm install -g exe-watcher
24
24
 
25
25
  ---
26
26
 
27
- ## What you get
27
+ ## Features
28
28
 
29
- **Dashboard** — Interactive TUI with gradient charts, responsive panels, keyboard navigation. Breaks down spend by day, project, model, activity type, tools, MCP servers, and shell commands. Auto-refreshes every 30 seconds.
29
+ ### Native macOS menubar app
30
30
 
31
- **One-shot rate** — For every category that involves edits, Watcher detects edit/test/fix retry cycles and shows you the percentage of turns where the AI got it right on the first try. Coding at 90% means 9 out of 10 edits landed without retries.
31
+ ```bash
32
+ exe-watcher menubar # install + launch
33
+ exe-watcher menubar --force # reinstall latest
34
+ ```
35
+
36
+ A Swift/SwiftUI popover that lives in your menu bar. Today's spend is always visible at a glance.
37
+
38
+ - **Period switcher** — Today, 7 Days, 30 Days, Month, All Time. Each period shows comparison to prior period (e.g. "+12% vs last 7d").
39
+ - **Provider tabs** — Switch between All, Claude, Codex, Cursor, etc. Only providers with actual spend appear. Cache prefetching makes tab switching instant.
40
+ - **Project spend** — Per-project cost breakdown across 24h / 7d / 30d.
41
+ - **Daily history heatmap** — 365 days of spend history, GitHub-contribution-style.
42
+ - **Subscription tracking** — Claude Pro ($20/mo), Claude Max ($200/mo), Cursor Pro ($20/mo) — see how much of your quota you've used.
43
+ - **Capacity estimation** — Derives your token limits from usage patterns when hard caps aren't published.
44
+ - **Cache hit %** — Track prompt caching efficiency across providers.
45
+ - **One-shot rate** — What percentage of edits land on the first try vs. retry loops.
46
+ - **Token optimization** — Surfaces waste patterns with estimated savings.
47
+ - **Multi-currency** — 17 currencies (USD, GBP, EUR, JPY, AUD, CAD, CHF, CNY, SEK, NOK, DKK, NZD, SGD, HKD, KRW, INR, BRL). ECB exchange rates, cached 24h.
48
+
49
+ Silent background refresh every 30 seconds. Launches at login via macOS Login Items. No loading spinners — all periods are pre-fetched on launch.
50
+
51
+ ### Interactive TUI dashboard
52
+
53
+ ```bash
54
+ exe-watcher # default: 7 days
55
+ exe-watcher today # today only
56
+ exe-watcher month # this calendar month
57
+ ```
32
58
 
33
- **Optimize** — Scans your sessions and `~/.claude/` config for waste: re-read files, low read:edit ratios, uncapped bash output, unused MCP servers, ghost agents, bloated CLAUDE.md files. Hands back exact, copy-paste fixes. Grades your setup A through F.
59
+ Full-screen terminal dashboard with gradient charts, responsive panels, and keyboard navigation. Breaks down spend by day, project, model, activity type, tools, MCP servers, and shell commands. Auto-refreshes every 30 seconds.
34
60
 
35
- **Compare** — Side-by-side model comparison on your own data. One-shot rate, retry rate, cost per edit, cache hit rate, delegation style, fast mode usage — broken down by task category.
61
+ **Keys:** `1`-`5` switch periods (Today / 7d / 30d / Month / All). `p` toggle providers. `c` compare mode. `o` optimize view. `q` quit.
36
62
 
37
- **Menubar** — Native macOS app showing today's cost in your menu bar. Period switcher, trend/forecast/pulse insights, activity breakdowns, per-project spend, and AI employee tracking. Launches at login, one command to install.
63
+ ### Optimize
38
64
 
39
- **Export** — CSV and JSON export for any time period. Pipe `--format json` output to `jq` for scripting.
65
+ ```bash
66
+ exe-watcher optimize # full scan
67
+ exe-watcher optimize -p week # scope to last 7 days
68
+ ```
69
+
70
+ Scans your sessions and `~/.claude/` config for waste: re-read files, low read:edit ratios, uncapped bash output, unused MCP servers, ghost agents, bloated CLAUDE.md files. Returns exact copy-paste fixes and estimated savings. Grades your setup A through F.
71
+
72
+ ### Compare
73
+
74
+ ```bash
75
+ exe-watcher compare # interactive model picker
76
+ ```
77
+
78
+ Side-by-side model comparison on your own data. One-shot rate, retry rate, cost per edit, cache hit rate, delegation style, fast mode usage — broken down by task category.
40
79
 
41
80
  ---
42
81
 
43
- ## Supported tools
82
+ ## Supported providers
44
83
 
45
- | Tool | Data source | Notes |
46
- |------|-------------|-------|
47
- | **Claude Code** | `~/.claude/projects/` | Full support |
48
- | **Claude Desktop** | `~/Library/Application Support/Claude/local-agent-mode-sessions/` | Full support |
84
+ | Provider | Data source | Notes |
85
+ |----------|-------------|-------|
86
+ | **Claude Code** | `~/.claude/projects/` | Full support — tokens, cost, cache, tools |
49
87
  | **Codex** (OpenAI) | `~/.codex/sessions/` | Full support |
50
88
  | **Cursor** | SQLite (`state.vscdb`) | Auto mode estimated at Sonnet pricing |
51
- | **cursor-agent** | CLI sessions | Full support |
89
+ | **Cursor Agent** | CLI sessions | Full support |
90
+ | **Copilot** | `~/.copilot/session-state/` | Output tokens only |
52
91
  | **OpenCode** | SQLite (`~/.local/share/opencode/`) | Subtask sessions excluded |
53
- | **Pi** | `~/.pi/agent/sessions/` | Full support |
54
92
  | **OMP** (Oh My Pi) | `~/.omp/agent/sessions/` | Full support |
55
- | **GitHub Copilot** | `~/.copilot/session-state/` | Output tokens only |
93
+ | **Pi** | `~/.pi/agent/sessions/` | Full support |
56
94
 
57
- Auto-detected. If multiple tools have data, press `p` in the dashboard to toggle. Provider plugin system makes adding new tools straightforward — see `src/providers/codex.ts` for the pattern.
95
+ All providers auto-detected. If multiple tools have data, press `p` in the dashboard to toggle between them. The provider plugin system makes adding new tools straightforward — each provider is a single file in `src/providers/`.
58
96
 
59
97
  ---
60
98
 
@@ -73,6 +111,9 @@ exe-watcher report --from 2026-04-01 --to 2026-04-10
73
111
  exe-watcher report --format json # structured JSON to stdout
74
112
  exe-watcher status # compact one-liner (today + month)
75
113
 
114
+ # Menubar data (used by the Swift app)
115
+ exe-watcher status --format menubar-json --period today --provider all
116
+
76
117
  # Filter
77
118
  exe-watcher report --provider claude # single provider
78
119
  exe-watcher report --project myapp # project substring match
@@ -86,52 +127,24 @@ exe-watcher export # CSV (today, 7d, 30d)
86
127
  exe-watcher export -f json # JSON export
87
128
  ```
88
129
 
89
- **Dashboard keys:** `1`-`5` switch periods (Today / 7d / 30d / Month / All). `p` toggle providers. `c` compare mode. `o` optimize view. `q` quit.
90
-
91
130
  **Flags work everywhere:** `--provider`, `--project`, `--exclude`, `--from`, `--to`, and `--format json` combine freely across all commands.
92
131
 
93
132
  ---
94
133
 
95
- ## Menubar app
96
-
97
- <!-- Screenshot: native macOS menubar popover with gold/purple Exe Foundry Bold theme -->
98
- <!-- To update: screencapture -w assets/menubar-v0.2.0.png (click the Watcher menubar icon) -->
99
-
100
- ```bash
101
- exe-watcher menubar
102
- ```
103
-
104
- Downloads, installs to `~/Applications`, and launches. Re-run with `--force` to reinstall. Native Swift + SwiftUI — silent background refresh every 60 seconds, no loading overlay. Pre-fetches all periods on launch so tab switching is instant. Launches at login automatically via macOS Login Items (toggleable in System Settings).
105
-
106
- **v0.2.0 additions:**
107
- - **Project Spend** — per-project cost breakdown across 24h / 7d / 30d
108
- - **AI Employees** — collapsible section with Memory counts (+ growth) and Employee Spend (model-aware pricing per agent)
109
- - **Dynamic provider tabs** — only shows providers that have actual spend data
110
- - **Quit button** — clean shutdown from the footer bar
111
- - **App icon** — gold EXE on dark purple (Exe Foundry Bold palette)
112
-
113
- **Compact mode** drops decimals in the menubar (e.g. `$110` instead of `$110.20`):
114
-
115
- ```bash
116
- defaults write ExeWatcherMenubar ExeWatcherMenubarCompact -bool true
117
- ```
118
-
119
- ---
120
-
121
134
  ## Configuration
122
135
 
123
136
  ### Currency
124
137
 
125
138
  ```bash
126
- exe-watcher currency GBP # any ISO 4217 code (162 currencies)
139
+ exe-watcher currency GBP # any supported ISO 4217 code
127
140
  exe-watcher currency --reset # back to USD
128
141
  ```
129
142
 
130
- Exchange rates from the European Central Bank via [Frankfurter](https://www.frankfurter.app/). Cached 24 hours. Applies everywhere: dashboard, menubar, exports.
143
+ Supported: USD, GBP, EUR, JPY, AUD, CAD, CHF, CNY, SEK, NOK, DKK, NZD, SGD, HKD, KRW, INR, BRL. Exchange rates from the ECB via [Frankfurter](https://www.frankfurter.app/), cached 24 hours. Applies everywhere: dashboard, menubar, exports.
131
144
 
132
145
  ### Plans
133
146
 
134
- Track spend against your subscription:
147
+ Track spend against your subscription quota:
135
148
 
136
149
  ```bash
137
150
  exe-watcher plan set claude-max # $200/month
@@ -141,6 +154,8 @@ exe-watcher plan set custom --monthly-usd 150 --provider claude
141
154
  exe-watcher plan set none # disable
142
155
  ```
143
156
 
157
+ The menubar shows a usage bar against your plan limit when a plan is active.
158
+
144
159
  ### Model aliases
145
160
 
146
161
  If a model shows `$0.00`, your provider's model name doesn't match LiteLLM pricing data. Map it:
@@ -155,6 +170,72 @@ Stored in `~/.config/exe-watcher/config.json`. User aliases override built-ins.
155
170
 
156
171
  ---
157
172
 
173
+ ## Exe OS integration
174
+
175
+ When [Exe OS](https://github.com/AskExe/exe-os) is installed, Watcher auto-detects it and adds an **AI Employees** section to the menubar with two panels:
176
+
177
+ - **Memory** — Per-agent memory count with 24h / 7d / 30d growth columns
178
+ - **Employee Spend** — Per-agent cost across 24h / 7d / 30d, using model-aware pricing (Opus, Sonnet, Haiku rates applied per-model)
179
+
180
+ How it works:
181
+
182
+ 1. Exe OS's SessionStart hook maps Claude Code sessions to agents via `~/.exe-os/session-cache/`
183
+ 2. The daemon computes `getAgentSpend()` with per-model pricing and writes `~/.exe-os/agent-stats.json` every 60 seconds
184
+ 3. Watcher reads the stats file — zero coupling, no auth, no direct database access
185
+ 4. Worktree-aware: agent worktree paths collapse into parent project names
186
+
187
+ The section appears automatically when exe-os is present and hides when it's not. Also shows daemon uptime and agent memory growth trends.
188
+
189
+ ---
190
+
191
+ ## Architecture
192
+
193
+ Two components, loosely coupled via CLI output:
194
+
195
+ ```
196
+ ┌──────────────────────────────────┐ ┌─────────────────────────────────┐
197
+ │ CLI (Node.js / TypeScript) │ │ Menubar App (Swift / SwiftUI) │
198
+ │ │ │ │
199
+ │ Reads provider session files │ JSON │ Calls CLI with --format │
200
+ │ Computes cost via LiteLLM rates ├─────►│ menubar-json │
201
+ │ Daily cache (v5, atomic writes) │ │ @Observable state management │
202
+ │ 365-day historical backfill │ │ 30s cache TTL, prefetch on │
203
+ │ Lock serialization for safety │ │ launch, concurrent fetch │
204
+ │ │ │ guards │
205
+ └──────────────────────────────────┘ └─────────────────────────────────┘
206
+ ```
207
+
208
+ **CLI pipeline:** Parse provider session files from disk → deduplicate by message ID → compute cost per token type (input, output, cache write, cache read, web search) → aggregate by period, project, model, activity → output as TUI, JSON, or CSV.
209
+
210
+ **Menubar app:** Calls `exe-watcher status --format menubar-json --period <period> --provider <provider>` → decodes JSON → renders SwiftUI popover. All 5 periods are pre-fetched on launch for instant tab switching. Security: no shell injection — validated argv array passed directly, no `/bin/zsh -c`.
211
+
212
+ **Deduplication** per provider: API message ID (Claude), cumulative token cross-check (Codex), conversation/timestamp (Cursor), session+message ID (OpenCode), responseId (Pi/OMP).
213
+
214
+ ---
215
+
216
+ ## Test suite
217
+
218
+ 637 tests across 3 layers:
219
+
220
+ | Layer | Framework | Count | What it covers |
221
+ |-------|-----------|-------|----------------|
222
+ | **CLI data integrity** | Vitest | 594 | Schema validation, provider sum consistency, period monotonicity, project spend accuracy, 365-day history, token sanity checks |
223
+ | **Swift state** | XCTest | 37 | Period windowing, cache isolation, prefetch logic, capacity estimation, CLI resolution, provider sum validation, JSON decode |
224
+ | **UI smoke** | XCTest + Accessibility | 6 | App launch, status item presence, popover display, period switching via macOS Accessibility APIs |
225
+
226
+ ```bash
227
+ # Run CLI tests
228
+ npm test
229
+
230
+ # Run Swift tests
231
+ cd mac && swift test
232
+
233
+ # Run UI tests
234
+ cd mac && xcodebuild test -scheme ExeWatcherUITests
235
+ ```
236
+
237
+ ---
238
+
158
239
  ## Activity tracking
159
240
 
160
241
  6 categories classified from tool usage patterns and keywords. No LLM calls, fully deterministic.
@@ -187,7 +268,7 @@ Starting points, not verdicts. A single experimental session with 60% cache hit
187
268
 
188
269
  ## How it works
189
270
 
190
- Reads session data directly from disk. No wrapper, no proxy, no API keys needed. Pricing from [LiteLLM](https://github.com/BerriAI/litellm) (auto-cached 24h). Handles input, output, cache write, cache read, and web search costs. Deduplicates messages by API message ID (Claude), cumulative token cross-check (Codex), conversation/timestamp (Cursor), session+message ID (OpenCode), or responseId (Pi/OMP).
271
+ Reads session data directly from disk. No wrapper, no proxy, no API keys needed. Pricing from [LiteLLM](https://github.com/BerriAI/litellm) (auto-cached 24h). Handles input, output, cache write, cache read, and web search costs.
191
272
 
192
273
  **Environment variables:**
193
274
 
@@ -195,63 +276,56 @@ Reads session data directly from disk. No wrapper, no proxy, no API keys needed.
195
276
  |----------|-------------|
196
277
  | `CLAUDE_CONFIG_DIR` | Override Claude data directory (default: `~/.claude`) |
197
278
  | `CODEX_HOME` | Override Codex data directory (default: `~/.codex`) |
279
+ | `EXE_WATCHER_CACHE_DIR` | Override cache directory (default: `~/.cache/exe-watcher`) |
198
280
 
199
281
  ---
200
282
 
201
283
  ## Contributing
202
284
 
203
- Contributions welcome. The provider plugin system is the easiest entry point — each provider is a single file in `src/providers/`. See `src/providers/codex.ts` for the pattern.
285
+ Contributions welcome. The provider plugin system is the easiest entry point — each provider is a single file in `src/providers/`.
204
286
 
205
287
  ```
206
288
  src/
207
- cli.ts Entry point (Commander.js)
208
- dashboard.tsx TUI (Ink — React for terminals)
209
- parser.ts Session reader, dedup, date filter
210
- models.ts LiteLLM pricing engine
211
- classifier.ts Activity classifier (6 categories)
212
- compare-stats.ts Model comparison engine
213
- menubar-json.ts Menubar payload builder (agent spend, project spend)
214
- export.ts CSV/JSON export
215
- config.ts Config management
216
- currency.ts Currency conversion
217
- providers/ One file per supported tool
218
- mac/ Native macOS menubar app (Swift + SwiftUI)
289
+ cli.ts Entry point (Commander.js)
290
+ dashboard.tsx TUI (Ink — React for terminals)
291
+ parser.ts Session reader, dedup, date filter
292
+ models.ts LiteLLM pricing engine
293
+ classifier.ts Activity classifier (6 categories)
294
+ compare-stats.ts Model comparison engine
295
+ menubar-json.ts Menubar payload builder (agent spend, project spend)
296
+ export.ts CSV/JSON export
297
+ config.ts Config management
298
+ currency.ts Currency conversion
299
+ providers/ One file per supported tool
300
+ mac/ Native macOS menubar app (Swift + SwiftUI)
301
+ tests/ CLI data integrity tests (Vitest)
219
302
  ```
220
303
 
221
304
  ---
222
305
 
223
- ## Exe OS integration
224
-
225
- If [Exe OS](https://github.com/AskExe/exe-os) is installed, Watcher auto-detects it and shows a live **AI Employees** section in the menubar with two sub-panels:
226
-
227
- - **Memory** — per-agent memory count with 24h / 7d / 30d growth columns
228
- - **Employee Spend** — per-agent cost across 24h / 7d / 30d, using model-aware pricing (Opus, Sonnet, Haiku rates applied per-model from the daemon's token data)
229
-
230
- No configuration needed. The section appears when exe-os is present and hides when it's not. The data pipeline: exe-os SessionStart hook maps Claude Code sessions to agents, the daemon computes `getAgentSpend()` with per-model pricing, writes `~/.exe-os/agent-stats.json` every 60 seconds, and Watcher reads this file — zero coupling, no auth, no direct database access.
231
-
232
- ---
233
-
234
306
  ## Origin & attribution
235
307
 
236
308
  Watcher is forked from [codeburn](https://github.com/getagentseal/codeburn) by [AgentSeal](https://github.com/getagentseal) (MIT license). We forked rather than contributed upstream because our roadmap diverges significantly:
237
309
 
238
310
  **What we changed:**
239
- - Rebranded to Watcher with the Exe Foundry Bold design system (gold + purple palette, owl icon)
240
- - Consolidated activity categories from 13 → 6 (less overlap, clearer signal)
241
- - Fixed double-counting bugs in the menubar JSON pipeline (cache + fresh parse overlap)
242
- - Performance: 7-day and 30-day queries from 2-5 seconds down to ~1 second (parse today only, use daily cache for history)
243
- - Menubar: removed loading overlay entirely — silent background refresh, pre-fetched periods for instant tab switching
244
- - Added exe-os agent memory and spend integration (auto-detected, model-aware pricing)
245
- - Per-project spend breakdown in the menubar (24h / 7d / 30d)
246
- - Launch at login via SMAppService, quit button, macOS app icon
247
- - Dark mode forced on popover, dynamic provider tabs (no empty states)
311
+ - Rebranded to Watcher with the Exe Foundry Bold design system
312
+ - 8 provider support (added Cursor Agent, Copilot, OMP, Pi, OpenCode)
313
+ - Native macOS menubar app with multi-period views, provider tabs, project spend, and subscription tracking
314
+ - Exe OS integration — per-agent spend and memory tracking for AI employee teams
315
+ - Daily cache system (v5) with atomic writes and cold-start 365-day backfill
316
+ - Capacity estimation from usage patterns
317
+ - Multi-currency support (17 currencies)
318
+ - 637-test suite across CLI, Swift state, and UI smoke layers
319
+ - Consolidated activity categories from 13 to 6
320
+ - Fixed double-counting bugs in the menubar JSON pipeline
321
+ - Performance: 7-day and 30-day queries from 2-5s down to ~1s via daily cache
248
322
 
249
323
  **Why we forked:**
250
- - We need full control over the data pipeline to integrate with exe-os (our AI employee operating system)
324
+ - Full control over the data pipeline to integrate with exe-os (our AI employee operating system)
251
325
  - Our classification model, provider support, and UI direction serve a different user base (AI-first teams running multi-agent workflows)
252
326
  - MIT license allows this — we give full credit to AgentSeal for the foundation
253
327
 
254
- Thank you to AgentSeal for building the original. If you just want a clean cost tracker without exe-os integration, [codeburn](https://github.com/getagentseal/codeburn) is excellent.
328
+ Thank you to AgentSeal for building the original. If you want a clean cost tracker without exe-os integration, [codeburn](https://github.com/getagentseal/codeburn) is excellent.
255
329
 
256
330
  ---
257
331
 
package/dist/cli.js CHANGED
@@ -133,9 +133,9 @@ function getModelCosts(model) {
133
133
  const prefixFallback = findPrefixMatch(new Map(Object.entries(FALLBACK_PRICING)), canonical);
134
134
  return mergeModelCosts(prefixFetched, prefixFallback);
135
135
  }
136
- function calculateCost(model, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, webSearchRequests, speed = "standard") {
136
+ function calculateCost(model, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, webSearchRequests, speed = "standard", tierInputTokens) {
137
137
  const baseCosts = getModelCosts(model);
138
- const costs = applyContextTier(baseCosts, inputTokens);
138
+ const costs = applyContextTier(baseCosts, tierInputTokens ?? inputTokens);
139
139
  if (!costs) return 0;
140
140
  const multiplier = speed === "fast" ? costs.fastMultiplier : 1;
141
141
  return multiplier * (inputTokens * costs.inputCostPerToken + outputTokens * costs.outputCostPerToken + cacheCreationTokens * costs.cacheWriteCostPerToken + cacheReadTokens * costs.cacheReadCostPerToken + webSearchRequests * costs.webSearchCostPerRequest);
@@ -2546,13 +2546,17 @@ function createParser(source, seenKeys) {
2546
2546
  const dedupKey = `codex:${source.path}:${timestamp}:${cumulativeTotal}`;
2547
2547
  if (seenKeys.has(dedupKey)) continue;
2548
2548
  seenKeys.add(dedupKey);
2549
+ const totalPromptInputTokens = uncachedInputTokens + cachedInputTokens;
2550
+ const billableOutputTokens = outputTokens;
2549
2551
  const costUSD = calculateCost(
2550
2552
  model,
2551
2553
  uncachedInputTokens,
2552
- outputTokens + reasoningTokens,
2554
+ billableOutputTokens,
2553
2555
  0,
2554
2556
  cachedInputTokens,
2555
- 0
2557
+ 0,
2558
+ "standard",
2559
+ totalPromptInputTokens
2556
2560
  );
2557
2561
  yield {
2558
2562
  provider: "codex",
@@ -3811,7 +3815,7 @@ import { createHash as createHash3, randomBytes as randomBytes5 } from "crypto";
3811
3815
  import { existsSync as existsSync3 } from "fs";
3812
3816
  import { mkdir as mkdir7, open as open5, readFile as readFile7, rename as rename6, unlink as unlink3 } from "fs/promises";
3813
3817
  import { join as join16 } from "path";
3814
- var DAILY_CACHE_VERSION = 5;
3818
+ var DAILY_CACHE_VERSION = 6;
3815
3819
  var DEFAULT_DAILY_CACHE_SCOPE = "global";
3816
3820
  var DAILY_CACHE_FILENAME = "daily-cache.json";
3817
3821
  function getCachePath3(scopeKey) {
@@ -7120,6 +7124,20 @@ program.command("status").description("Compact status output (today + week + mon
7120
7124
  c = addNewDays(c, gapDays, yesterdayStr, coveredThrough ? { coveredThrough } : void 0);
7121
7125
  await saveDailyCache(c);
7122
7126
  }
7127
+ const updatedOldest = c.days.length > 0 ? c.days[0].date : null;
7128
+ const neededStart = new Date(todayStart.getTime() - (selectedPeriodHistoryDays - 1) * MS_PER_DAY4);
7129
+ const fullBackfillStart = new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY4);
7130
+ const clampedNeeded = neededStart < fullBackfillStart ? fullBackfillStart : neededStart;
7131
+ if (updatedOldest && clampedNeeded.getTime() < new Date(updatedOldest).getTime()) {
7132
+ const backEnd = new Date(new Date(updatedOldest).getTime() - MS_PER_DAY4);
7133
+ if (clampedNeeded.getTime() <= backEnd.getTime()) {
7134
+ const backRange = { start: clampedNeeded, end: backEnd };
7135
+ const backProjects = filterProjectsByName(await parseAllSessions(backRange, "all"), opts.project, opts.exclude);
7136
+ const backDays = fillMissingDays(backRange.start, backRange.end, aggregateProjectsIntoDays(backProjects));
7137
+ c = addNewDays(c, backDays, yesterdayStr);
7138
+ await saveDailyCache(c);
7139
+ }
7140
+ }
7123
7141
  return c;
7124
7142
  });
7125
7143
  let currentData;