exe-watcher 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cache-dir.ts","../src/models.ts","../src/bash-utils.ts","../src/cursor-cache.ts","../src/sqlite.ts","../src/providers/cursor.ts","../src/providers/opencode.ts","../src/providers/cursor-agent.ts","../src/cli.ts","../src/menubar-installer.ts","../src/export.ts","../src/types.ts","../src/currency.ts","../src/config.ts","../src/day-aggregator.ts","../src/parser.ts","../src/fs-utils.ts","../src/providers/claude.ts","../src/providers/codex.ts","../src/providers/copilot.ts","../src/providers/pi.ts","../src/providers/index.ts","../src/classifier.ts","../src/format.ts","../src/menubar-json.ts","../src/daily-cache.ts","../src/dashboard.tsx","../src/optimize.ts","../src/context-budget.ts","../src/compare.tsx","../src/compare-stats.ts","../src/plan-usage.ts","../src/plans.ts","../src/cli-date.ts"],"sourcesContent":["import { join } from 'path'\nimport { homedir } from 'os'\n\n/**\n * Shared cache directory resolver. Checks, in order:\n * 1. EXE_WATCHER_CACHE_DIR (user override)\n * 2. XDG_CACHE_HOME/exe-watcher (Linux/NixOS convention)\n * 3. ~/.cache/exe-watcher (default)\n */\nexport function getCacheDir(): string {\n const explicit = process.env['EXE_WATCHER_CACHE_DIR']\n if (explicit) return explicit\n\n const xdgCache = process.env['XDG_CACHE_HOME']\n return join(xdgCache || join(homedir(), '.cache'), 'exe-watcher')\n}\n","import { readFile, mkdir, rename, unlink } from 'fs/promises'\nimport { open } from 'fs/promises'\nimport { join } from 'path'\nimport { randomBytes } from 'crypto'\n\nimport { getCacheDir } from './cache-dir.js'\n\nexport type ModelCosts = {\n inputCostPerToken: number\n outputCostPerToken: number\n cacheWriteCostPerToken: number\n cacheReadCostPerToken: number\n webSearchCostPerRequest: number\n fastMultiplier: number\n}\n\ntype LiteLLMEntry = {\n input_cost_per_token?: number\n output_cost_per_token?: number\n cache_creation_input_token_cost?: number\n cache_read_input_token_cost?: number\n provider_specific_entry?: { fast?: number }\n}\n\nconst LITELLM_URL = 'https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json'\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000\nconst WEB_SEARCH_COST = 0.01\n\nconst FALLBACK_PRICING: Record<string, ModelCosts> = {\n 'claude-opus-4-7': { inputCostPerToken: 5e-6, outputCostPerToken: 25e-6, cacheWriteCostPerToken: 6.25e-6, cacheReadCostPerToken: 0.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 6 },\n 'claude-opus-4-6': { inputCostPerToken: 5e-6, outputCostPerToken: 25e-6, cacheWriteCostPerToken: 6.25e-6, cacheReadCostPerToken: 0.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 6 },\n 'claude-opus-4-5': { inputCostPerToken: 5e-6, outputCostPerToken: 25e-6, cacheWriteCostPerToken: 6.25e-6, cacheReadCostPerToken: 0.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-opus-4-1': { inputCostPerToken: 15e-6, outputCostPerToken: 75e-6, cacheWriteCostPerToken: 18.75e-6, cacheReadCostPerToken: 1.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-opus-4': { inputCostPerToken: 15e-6, outputCostPerToken: 75e-6, cacheWriteCostPerToken: 18.75e-6, cacheReadCostPerToken: 1.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-sonnet-4-6': { inputCostPerToken: 3e-6, outputCostPerToken: 15e-6, cacheWriteCostPerToken: 3.75e-6, cacheReadCostPerToken: 0.3e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-sonnet-4-5': { inputCostPerToken: 3e-6, outputCostPerToken: 15e-6, cacheWriteCostPerToken: 3.75e-6, cacheReadCostPerToken: 0.3e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-sonnet-4': { inputCostPerToken: 3e-6, outputCostPerToken: 15e-6, cacheWriteCostPerToken: 3.75e-6, cacheReadCostPerToken: 0.3e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-3-7-sonnet': { inputCostPerToken: 3e-6, outputCostPerToken: 15e-6, cacheWriteCostPerToken: 3.75e-6, cacheReadCostPerToken: 0.3e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-3-5-sonnet': { inputCostPerToken: 3e-6, outputCostPerToken: 15e-6, cacheWriteCostPerToken: 3.75e-6, cacheReadCostPerToken: 0.3e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-haiku-4-5': { inputCostPerToken: 1e-6, outputCostPerToken: 5e-6, cacheWriteCostPerToken: 1.25e-6, cacheReadCostPerToken: 0.1e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'claude-3-5-haiku': { inputCostPerToken: 0.8e-6, outputCostPerToken: 4e-6, cacheWriteCostPerToken: 1e-6, cacheReadCostPerToken: 0.08e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-4o': { inputCostPerToken: 2.5e-6, outputCostPerToken: 10e-6, cacheWriteCostPerToken: 2.5e-6, cacheReadCostPerToken: 1.25e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-4o-mini': { inputCostPerToken: 0.15e-6, outputCostPerToken: 0.6e-6, cacheWriteCostPerToken: 0.15e-6, cacheReadCostPerToken: 0.075e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gemini-2.5-pro': { inputCostPerToken: 1.25e-6, outputCostPerToken: 10e-6, cacheWriteCostPerToken: 1.25e-6, cacheReadCostPerToken: 0.315e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5.3-codex': { inputCostPerToken: 2.5e-6, outputCostPerToken: 10e-6, cacheWriteCostPerToken: 2.5e-6, cacheReadCostPerToken: 1.25e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5.4': { inputCostPerToken: 2.5e-6, outputCostPerToken: 10e-6, cacheWriteCostPerToken: 2.5e-6, cacheReadCostPerToken: 1.25e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5.4-mini': { inputCostPerToken: 0.4e-6, outputCostPerToken: 1.6e-6, cacheWriteCostPerToken: 0.4e-6, cacheReadCostPerToken: 0.2e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5': { inputCostPerToken: 2.5e-6, outputCostPerToken: 10e-6, cacheWriteCostPerToken: 2.5e-6, cacheReadCostPerToken: 1.25e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5-mini': { inputCostPerToken: 0.4e-6, outputCostPerToken: 1.6e-6, cacheWriteCostPerToken: 0.4e-6, cacheReadCostPerToken: 0.2e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-4.1': { inputCostPerToken: 2e-6, outputCostPerToken: 8e-6, cacheWriteCostPerToken: 2e-6, cacheReadCostPerToken: 0.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-4.1-mini': { inputCostPerToken: 0.4e-6, outputCostPerToken: 1.6e-6, cacheWriteCostPerToken: 0.4e-6, cacheReadCostPerToken: 0.1e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-4.1-nano': { inputCostPerToken: 0.1e-6, outputCostPerToken: 0.4e-6, cacheWriteCostPerToken: 0.1e-6, cacheReadCostPerToken: 0.025e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'o3': { inputCostPerToken: 2e-6, outputCostPerToken: 8e-6, cacheWriteCostPerToken: 2e-6, cacheReadCostPerToken: 0.5e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'o4-mini': { inputCostPerToken: 1.1e-6, outputCostPerToken: 4.4e-6, cacheWriteCostPerToken: 1.1e-6, cacheReadCostPerToken: 0.275e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'codex-mini-latest': { inputCostPerToken: 1.5e-6, outputCostPerToken: 6e-6, cacheWriteCostPerToken: 1.5e-6, cacheReadCostPerToken: 0.375e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'codex-mini': { inputCostPerToken: 1.5e-6, outputCostPerToken: 6e-6, cacheWriteCostPerToken: 1.5e-6, cacheReadCostPerToken: 0.375e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5.1-codex': { inputCostPerToken: 1.25e-6, outputCostPerToken: 10e-6, cacheWriteCostPerToken: 1.25e-6, cacheReadCostPerToken: 0.625e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5.1-codex-mini': { inputCostPerToken: 0.25e-6, outputCostPerToken: 2e-6, cacheWriteCostPerToken: 0.25e-6, cacheReadCostPerToken: 0.125e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'gpt-5.2-codex': { inputCostPerToken: 1.75e-6, outputCostPerToken: 14e-6, cacheWriteCostPerToken: 1.75e-6, cacheReadCostPerToken: 0.875e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'MiniMax-M2.7-highspeed': { inputCostPerToken: 0.6e-6, outputCostPerToken: 2.4e-6, cacheWriteCostPerToken: 0.375e-6, cacheReadCostPerToken: 0.06e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n 'MiniMax-M2.7': { inputCostPerToken: 0.3e-6, outputCostPerToken: 1.2e-6, cacheWriteCostPerToken: 0.375e-6, cacheReadCostPerToken: 0.06e-6, webSearchCostPerRequest: WEB_SEARCH_COST, fastMultiplier: 1 },\n}\n\nlet pricingCache: Map<string, ModelCosts> | null = null\n\nfunction getCachePath(): string {\n return join(getCacheDir(), 'litellm-pricing.json')\n}\n\nfunction parseLiteLLMEntry(entry: LiteLLMEntry): ModelCosts | null {\n if (entry.input_cost_per_token === undefined || entry.output_cost_per_token === undefined) return null\n return {\n inputCostPerToken: entry.input_cost_per_token,\n outputCostPerToken: entry.output_cost_per_token,\n cacheWriteCostPerToken: entry.cache_creation_input_token_cost ?? entry.input_cost_per_token * 1.25,\n cacheReadCostPerToken: entry.cache_read_input_token_cost ?? entry.input_cost_per_token * 0.1,\n webSearchCostPerRequest: WEB_SEARCH_COST,\n fastMultiplier: entry.provider_specific_entry?.fast ?? 1,\n }\n}\n\nasync function fetchAndCachePricing(): Promise<Map<string, ModelCosts>> {\n const response = await fetch(LITELLM_URL)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n const data = await response.json() as Record<string, LiteLLMEntry>\n const pricing = new Map<string, ModelCosts>()\n\n for (const [name, entry] of Object.entries(data)) {\n const costs = parseLiteLLMEntry(entry)\n if (!costs) continue\n pricing.set(name, costs)\n // Also index by stripped name so lookups work without provider prefix:\n // 'anthropic/claude-opus-4-6' is also queryable as 'claude-opus-4-6'.\n // First write wins so direct-provider entries take precedence over re-hosters.\n const stripped = name.replace(/^[^/]+\\//, '')\n if (stripped !== name && !pricing.has(stripped)) pricing.set(stripped, costs)\n }\n\n await mkdir(getCacheDir(), { recursive: true })\n const finalPath = getCachePath()\n const tmpPath = `${finalPath}.${randomBytes(8).toString('hex')}.tmp`\n const handle = await open(tmpPath, 'w', 0o600)\n try {\n await handle.writeFile(JSON.stringify({\n timestamp: Date.now(),\n data: Object.fromEntries(pricing),\n }), { encoding: 'utf-8' })\n await handle.sync()\n } finally {\n await handle.close()\n }\n try {\n await rename(tmpPath, finalPath)\n } catch (err) {\n try { await unlink(tmpPath) } catch { /* ignore */ }\n throw err\n }\n\n return pricing\n}\n\nasync function loadCachedPricing(): Promise<Map<string, ModelCosts> | null> {\n try {\n const raw = await readFile(getCachePath(), 'utf-8')\n const cached = JSON.parse(raw) as { timestamp: number; data: Record<string, ModelCosts> }\n if (Date.now() - cached.timestamp > CACHE_TTL_MS) return null\n return new Map(Object.entries(cached.data))\n } catch {\n return null\n }\n}\n\nexport async function loadPricing(): Promise<void> {\n const cached = await loadCachedPricing()\n if (cached) {\n pricingCache = cached\n return\n }\n\n try {\n pricingCache = await fetchAndCachePricing()\n } catch {\n pricingCache = new Map(Object.entries(FALLBACK_PRICING))\n }\n}\n\n// Known model name variants that providers emit but LiteLLM/fallback don't index under.\n// OMP emits 'anthropic--claude-4.6-opus' (double-dash, dot version, tier-last).\n// getCanonicalName strips any 'provider/' prefix first, so only the post-strip\n// forms need to be listed here.\nconst BUILTIN_ALIASES: Record<string, string> = {\n 'anthropic--claude-4.6-opus': 'claude-opus-4-6',\n 'anthropic--claude-4.6-sonnet': 'claude-sonnet-4-6',\n 'anthropic--claude-4.5-opus': 'claude-opus-4-5',\n 'anthropic--claude-4.5-sonnet': 'claude-sonnet-4-5',\n 'anthropic--claude-4.5-haiku': 'claude-haiku-4-5',\n}\n\nlet userAliases: Record<string, string> = {}\n\n// Called once during CLI startup after config is loaded.\n// User aliases take precedence over built-ins.\nexport function setModelAliases(aliases: Record<string, string>): void {\n userAliases = aliases\n}\n\nfunction resolveAlias(model: string): string {\n if (Object.hasOwn(userAliases, model)) return userAliases[model]!\n if (Object.hasOwn(BUILTIN_ALIASES, model)) return BUILTIN_ALIASES[model]!\n return model\n}\nfunction getCanonicalName(model: string): string {\n return model\n .replace(/@.*$/, '') // strip pin: claude-sonnet-4-6@20250929 -> claude-sonnet-4-6\n .replace(/-\\d{8}$/, '') // strip date: claude-sonnet-4-20250514 -> claude-sonnet-4\n .replace(/^[^/]+\\//, '') // strip provider prefix: anthropic/foo -> foo\n}\n\nexport function getModelCosts(model: string): ModelCosts | null {\n const canonical = resolveAlias(getCanonicalName(model))\n\n // Our curated prices (official direct API pricing) take precedence over\n // LiteLLM which may return third-party provider markups (e.g. Vertex AI\n // charges $1/$5 for Haiku 3.5 vs Anthropic direct at $0.80/$4).\n // Exact matches only here — prefix matching happens below after LiteLLM.\n if (Object.hasOwn(FALLBACK_PRICING, canonical)) return FALLBACK_PRICING[canonical]!\n\n if (pricingCache?.has(canonical)) return pricingCache.get(canonical)!\n\n for (const [key, costs] of pricingCache ?? new Map()) {\n if (canonical.startsWith(key)) return costs\n }\n\n for (const [key, costs] of Object.entries(FALLBACK_PRICING)) {\n if (canonical.startsWith(key)) return costs\n }\n\n return null\n}\n\nexport function calculateCost(\n model: string,\n inputTokens: number,\n outputTokens: number,\n cacheCreationTokens: number,\n cacheReadTokens: number,\n webSearchRequests: number,\n speed: 'standard' | 'fast' = 'standard',\n): number {\n const costs = getModelCosts(model)\n if (!costs) return 0\n\n const multiplier = speed === 'fast' ? costs.fastMultiplier : 1\n\n return multiplier * (\n inputTokens * costs.inputCostPerToken +\n outputTokens * costs.outputCostPerToken +\n cacheCreationTokens * costs.cacheWriteCostPerToken +\n cacheReadTokens * costs.cacheReadCostPerToken +\n webSearchRequests * costs.webSearchCostPerRequest\n )\n}\n\nexport function getShortModelName(model: string): string {\n const canonical = resolveAlias(getCanonicalName(model))\n const shortNames: Record<string, string> = {\n 'claude-opus-4-7': 'Opus 4.7',\n 'claude-opus-4-6': 'Opus 4.6',\n 'claude-opus-4-5': 'Opus 4.5',\n 'claude-opus-4-1': 'Opus 4.1',\n 'claude-opus-4': 'Opus 4',\n 'claude-sonnet-4-6': 'Sonnet 4.6',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'claude-haiku-4-5': 'Haiku 4.5',\n 'claude-3-5-haiku': 'Haiku 3.5',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n 'gpt-4.1-nano': 'GPT-4.1 Nano',\n 'gpt-4.1-mini': 'GPT-4.1 Mini',\n 'gpt-4.1': 'GPT-4.1',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5.3-codex': 'GPT-5.3 Codex',\n 'gpt-5-mini': 'GPT-5 Mini',\n 'gpt-5': 'GPT-5',\n 'gemini-2.5-pro': 'Gemini 2.5 Pro',\n 'o4-mini': 'o4-mini',\n 'o3': 'o3',\n 'MiniMax-M2.7-highspeed': 'MiniMax M2.7 Highspeed',\n 'MiniMax-M2.7': 'MiniMax M2.7',\n }\n for (const [key, name] of Object.entries(shortNames)) {\n if (canonical.startsWith(key)) return name\n }\n return canonical\n}\n","import { basename } from 'path'\n\nfunction stripQuotedStrings(command: string): string {\n return command.replace(/\"[^\"]*\"|'[^']*'/g, match => ' '.repeat(match.length))\n}\n\nexport function extractBashCommands(command: string): string[] {\n if (!command || !command.trim()) return []\n\n const stripped = stripQuotedStrings(command)\n\n const separatorRegex = /\\s*(?:&&|;|\\|)\\s*/g\n const separators: Array<{ start: number; end: number }> = []\n let match: RegExpExecArray | null\n\n while ((match = separatorRegex.exec(stripped)) !== null) {\n separators.push({ start: match.index, end: match.index + match[0].length })\n }\n\n const ranges: Array<[number, number]> = []\n let cursor = 0\n for (const sep of separators) {\n ranges.push([cursor, sep.start])\n cursor = sep.end\n }\n ranges.push([cursor, command.length])\n\n const commands: string[] = []\n for (const [start, end] of ranges) {\n const segment = command.slice(start, end).trim()\n if (!segment) continue\n\n const tokens = segment.split(/\\s+/)\n let i = 0\n while (i < tokens.length && /^\\w+=/.test(tokens[i]!)) i++\n const base = i < tokens.length ? basename(tokens[i]!) : ''\n\n if (base && base !== 'cd' && base !== 'true' && base !== 'false') {\n commands.push(base)\n }\n }\n\n return commands\n}\n","import { readFile, mkdir, stat, rename } from 'fs/promises'\nimport { open } from 'fs/promises'\nimport { join } from 'path'\nimport { randomBytes } from 'crypto'\n\nimport { getCacheDir } from './cache-dir.js'\nimport type { ParsedProviderCall } from './providers/types.js'\n\ntype ResultCache = {\n dbMtimeMs: number\n dbSizeBytes: number\n calls: ParsedProviderCall[]\n}\n\nconst CACHE_FILE = 'cursor-results.json'\n\nfunction getCachePath(): string {\n return join(getCacheDir(), CACHE_FILE)\n}\n\nasync function getDbFingerprint(dbPath: string): Promise<{ mtimeMs: number; size: number } | null> {\n try {\n const s = await stat(dbPath)\n return { mtimeMs: s.mtimeMs, size: s.size }\n } catch {\n return null\n }\n}\n\nexport async function readCachedResults(dbPath: string): Promise<ParsedProviderCall[] | null> {\n try {\n const fp = await getDbFingerprint(dbPath)\n if (!fp) return null\n\n const raw = await readFile(getCachePath(), 'utf-8')\n const cache = JSON.parse(raw) as ResultCache\n\n if (cache.dbMtimeMs === fp.mtimeMs && cache.dbSizeBytes === fp.size) {\n return cache.calls\n }\n return null\n } catch {\n return null\n }\n}\n\nexport async function writeCachedResults(dbPath: string, calls: ParsedProviderCall[]): Promise<void> {\n try {\n const fp = await getDbFingerprint(dbPath)\n if (!fp) return\n\n const dir = getCacheDir()\n await mkdir(dir, { recursive: true })\n const cache: ResultCache = {\n dbMtimeMs: fp.mtimeMs,\n dbSizeBytes: fp.size,\n calls,\n }\n const finalPath = getCachePath()\n const tmpPath = `${finalPath}.${randomBytes(8).toString('hex')}.tmp`\n const handle = await open(tmpPath, 'w', 0o600)\n try {\n await handle.writeFile(JSON.stringify(cache), { encoding: 'utf-8' })\n await handle.sync()\n } finally {\n await handle.close()\n }\n await rename(tmpPath, finalPath)\n } catch {}\n}\n","import { createRequire } from 'node:module'\n\n/// Thin SQLite read-only wrapper over Node's built-in `node:sqlite` module (stable in\n/// Node 24, experimental in Node 22 / 23). Replaces the earlier `better-sqlite3` binding\n/// so the dependency graph no longer pulls in the deprecated `prebuild-install` package\n/// (issue #75). Works across Cursor and OpenCode session DBs, both of which we only read.\n\nconst requireForSqlite = createRequire(import.meta.url)\n\ntype Row = Record<string, unknown>\n\nexport type SqliteDatabase = {\n query<T extends Row = Row>(sql: string, params?: unknown[]): T[]\n close(): void\n}\n\ntype DatabaseSyncCtor = new (path: string, options?: { readOnly?: boolean }) => {\n prepare(sql: string): { all(...params: unknown[]): Row[] }\n close(): void\n}\n\nlet DatabaseSync: DatabaseSyncCtor | null = null\nlet loadAttempted = false\nlet loadError: string | null = null\n\n/// Lazily imports `node:sqlite`. On Node 22/23 it emits an ExperimentalWarning the first\n/// time the module is loaded; we silence that specific warning once so dashboards aren't\n/// preceded by a scary stderr line every run. Any other warnings (including future\n/// non-SQLite ones) are left untouched.\nfunction loadDriver(): boolean {\n if (loadAttempted) return DatabaseSync !== null\n loadAttempted = true\n\n const origEmit = process.emit.bind(process)\n let restored = false\n const restore = () => {\n if (restored) return\n restored = true\n process.emit = origEmit\n }\n\n // Node's `process.emit` signature is overloaded; we intercept the 'warning' channel\n // only and proxy everything else through unchanged. The `any` cast avoids chasing the\n // overload union which isn't worth its verbosity for a single-purpose shim.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n process.emit = function patchedEmit(this: NodeJS.Process, event: string, ...args: any[]): boolean {\n if (event === 'warning') {\n const warning = args[0] as { name?: string; message?: string } | undefined\n if (\n warning?.name === 'ExperimentalWarning' &&\n typeof warning.message === 'string' &&\n /SQLite/i.test(warning.message)\n ) {\n return false\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (origEmit as any).call(this, event, ...args)\n } as typeof process.emit\n\n try {\n const mod = requireForSqlite('node:sqlite') as { DatabaseSync: DatabaseSyncCtor }\n DatabaseSync = mod.DatabaseSync\n return true\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n loadError =\n 'SQLite-based providers (Cursor, OpenCode) need Node 22+ with the node:sqlite module.\\n' +\n `Current Node: ${process.version}.\\n` +\n 'Upgrade Node (https://nodejs.org) and run exe-watcher again.\\n' +\n `(underlying error: ${message})`\n return false\n } finally {\n restore()\n }\n}\n\nexport function isSqliteAvailable(): boolean {\n return loadDriver()\n}\n\nexport function getSqliteLoadError(): string {\n return loadError ?? 'SQLite driver not available'\n}\n\nexport function openDatabase(path: string): SqliteDatabase {\n if (!loadDriver() || DatabaseSync === null) {\n throw new Error(getSqliteLoadError())\n }\n\n const db = new DatabaseSync(path, { readOnly: true })\n\n return {\n query<T extends Row = Row>(sql: string, params: unknown[] = []): T[] {\n return db.prepare(sql).all(...params) as T[]\n },\n close() {\n db.close()\n },\n }\n}\n","import { existsSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\n\nimport { calculateCost } from '../models.js'\nimport { readCachedResults, writeCachedResults } from '../cursor-cache.js'\nimport { isSqliteAvailable, getSqliteLoadError, openDatabase, type SqliteDatabase } from '../sqlite.js'\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js'\n\nconst CURSOR_DEFAULT_MODEL = 'claude-sonnet-4-5'\n\nconst modelDisplayNames: Record<string, string> = {\n 'claude-4.5-opus-high-thinking': 'Opus 4.5 (Thinking)',\n 'claude-4-opus': 'Opus 4',\n 'claude-4-sonnet-thinking': 'Sonnet 4 (Thinking)',\n 'claude-4.5-sonnet-thinking': 'Sonnet 4.5 (Thinking)',\n 'claude-4.6-sonnet': 'Sonnet 4.6',\n 'composer-1': 'Composer 1',\n 'grok-code-fast-1': 'Grok Code Fast',\n 'gemini-3-pro': 'Gemini 3 Pro',\n 'gpt-5.1-codex-high': 'GPT-5.1 Codex',\n 'gpt-5': 'GPT-5',\n 'gpt-4.1': 'GPT-4.1',\n 'default': 'Auto (Sonnet est.)',\n}\n\ntype BubbleRow = {\n input_tokens: number | null\n output_tokens: number | null\n model: string | null\n created_at: string | null\n conversation_id: string | null\n user_text: string | null\n code_blocks: string | null\n}\n\nfunction getCursorDbPath(): string {\n if (process.platform === 'darwin') {\n return join(homedir(), 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'state.vscdb')\n }\n if (process.platform === 'win32') {\n return join(homedir(), 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'state.vscdb')\n }\n return join(homedir(), '.config', 'Cursor', 'User', 'globalStorage', 'state.vscdb')\n}\n\ntype CodeBlock = { languageId?: string }\n\nfunction extractLanguages(codeBlocksJson: string | null): string[] {\n if (!codeBlocksJson) return []\n try {\n const blocks = JSON.parse(codeBlocksJson) as CodeBlock[]\n if (!Array.isArray(blocks)) return []\n const langs = new Set<string>()\n for (const block of blocks) {\n if (block.languageId && block.languageId !== 'plaintext') {\n langs.add(block.languageId)\n }\n }\n return [...langs]\n } catch {\n return []\n }\n}\n\nfunction resolveModel(raw: string | null): string {\n if (!raw || raw === 'default') return CURSOR_DEFAULT_MODEL\n return raw\n}\n\nfunction modelForDisplay(raw: string | null): string {\n if (!raw || raw === 'default') return 'default'\n return raw\n}\n\nconst BUBBLE_QUERY_BASE = `\n SELECT\n json_extract(value, '$.tokenCount.inputTokens') as input_tokens,\n json_extract(value, '$.tokenCount.outputTokens') as output_tokens,\n json_extract(value, '$.modelInfo.modelName') as model,\n json_extract(value, '$.createdAt') as created_at,\n json_extract(value, '$.conversationId') as conversation_id,\n substr(json_extract(value, '$.text'), 1, 500) as user_text,\n json_extract(value, '$.codeBlocks') as code_blocks\n FROM cursorDiskKV\n WHERE key LIKE 'bubbleId:%'\n AND json_extract(value, '$.tokenCount.inputTokens') > 0\n`\n\nconst USER_MESSAGES_QUERY = `\n SELECT\n json_extract(value, '$.conversationId') as conversation_id,\n json_extract(value, '$.createdAt') as created_at,\n substr(json_extract(value, '$.text'), 1, 500) as text\n FROM cursorDiskKV\n WHERE key LIKE 'bubbleId:%'\n AND json_extract(value, '$.type') = 1\n AND json_extract(value, '$.createdAt') > ?\n ORDER BY json_extract(value, '$.createdAt') ASC\n`\n\nconst BUBBLE_QUERY_SINCE = BUBBLE_QUERY_BASE + `\n AND json_extract(value, '$.createdAt') > ?\n ORDER BY json_extract(value, '$.createdAt') ASC\n`\n\nfunction validateSchema(db: SqliteDatabase): boolean {\n try {\n const rows = db.query<{ cnt: number }>(\n \"SELECT COUNT(*) as cnt FROM cursorDiskKV WHERE key LIKE 'bubbleId:%' LIMIT 1\"\n )\n return rows.length > 0\n } catch {\n return false\n }\n}\n\ntype UserMsgRow = { conversation_id: string; created_at: string; text: string }\n\nfunction buildUserMessageMap(db: SqliteDatabase, timeFloor: string): Map<string, string[]> {\n const map = new Map<string, string[]>()\n try {\n const rows = db.query<UserMsgRow>(USER_MESSAGES_QUERY, [timeFloor])\n for (const row of rows) {\n if (!row.conversation_id || !row.text) continue\n const existing = map.get(row.conversation_id) ?? []\n existing.push(row.text)\n map.set(row.conversation_id, existing)\n }\n } catch {}\n return map\n}\n\nfunction parseBubbles(db: SqliteDatabase, seenKeys: Set<string>): { calls: ParsedProviderCall[] } {\n const results: ParsedProviderCall[] = []\n let skipped = 0\n\n const DEFAULT_LOOKBACK_DAYS = 35\n const timeFloor = new Date(Date.now() - DEFAULT_LOOKBACK_DAYS * 24 * 60 * 60 * 1000).toISOString()\n\n const userMessages = buildUserMessageMap(db, timeFloor)\n\n let rows: BubbleRow[]\n try {\n rows = db.query<BubbleRow>(BUBBLE_QUERY_SINCE, [timeFloor])\n } catch {\n return { calls: results }\n }\n\n for (const row of rows) {\n try {\n const inputTokens = row.input_tokens ?? 0\n const outputTokens = row.output_tokens ?? 0\n if (inputTokens === 0 && outputTokens === 0) continue\n\n const createdAt = row.created_at ?? ''\n const conversationId = row.conversation_id ?? 'unknown'\n const dedupKey = `cursor:${conversationId}:${createdAt}:${inputTokens}:${outputTokens}`\n\n if (seenKeys.has(dedupKey)) continue\n seenKeys.add(dedupKey)\n\n const pricingModel = resolveModel(row.model)\n const displayModel = modelForDisplay(row.model)\n\n const costUSD = calculateCost(pricingModel, inputTokens, outputTokens, 0, 0, 0)\n\n const timestamp = createdAt || ''\n const convMessages = userMessages.get(conversationId) ?? []\n const userQuestion = convMessages.length > 0 ? convMessages.shift()! : ''\n const assistantText = row.user_text ?? ''\n const userText = (userQuestion + ' ' + assistantText).trim()\n\n const languages = extractLanguages(row.code_blocks)\n const hasCode = languages.length > 0\n\n const cursorTools: string[] = hasCode ? ['cursor:edit', ...languages.map(l => `lang:${l}`)] : []\n\n results.push({\n provider: 'cursor',\n model: displayModel,\n inputTokens,\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: 0,\n cachedInputTokens: 0,\n reasoningTokens: 0,\n webSearchRequests: 0,\n costUSD,\n tools: cursorTools,\n bashCommands: [],\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: userText,\n sessionId: conversationId,\n })\n } catch {\n skipped++\n }\n }\n\n if (skipped > 0) {\n process.stderr.write(`exe-watcher: skipped ${skipped} unreadable Cursor entries\\n`)\n }\n\n return { calls: results }\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n if (!isSqliteAvailable()) {\n process.stderr.write(getSqliteLoadError() + '\\n')\n return\n }\n\n const cached = await readCachedResults(source.path)\n if (cached) {\n for (const call of cached) {\n if (seenKeys.has(call.deduplicationKey)) continue\n seenKeys.add(call.deduplicationKey)\n yield call\n }\n return\n }\n\n let db: SqliteDatabase\n try {\n db = openDatabase(source.path)\n } catch (err) {\n process.stderr.write(`exe-watcher: cannot open Cursor database: ${err instanceof Error ? err.message : err}\\n`)\n return\n }\n\n try {\n if (!validateSchema(db)) {\n process.stderr.write('exe-watcher: Cursor storage format not recognized. You may need to update Exe Watcher.\\n')\n return\n }\n\n const { calls } = parseBubbles(db, seenKeys)\n\n await writeCachedResults(source.path, calls)\n\n for (const call of calls) {\n yield call\n }\n } finally {\n db.close()\n }\n },\n }\n}\n\nexport function createCursorProvider(dbPathOverride?: string): Provider {\n return {\n name: 'cursor',\n displayName: 'Cursor',\n\n modelDisplayName(model: string): string {\n return modelDisplayNames[model] ?? model\n },\n\n toolDisplayName(rawTool: string): string {\n return rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n if (!isSqliteAvailable()) return []\n\n const dbPath = dbPathOverride ?? getCursorDbPath()\n if (!existsSync(dbPath)) return []\n\n return [{ path: dbPath, project: 'cursor', provider: 'cursor' }]\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys)\n },\n }\n}\n\nexport const cursor = createCursorProvider()\n","import { readdir } from 'fs/promises'\nimport { join } from 'path'\nimport { homedir } from 'os'\n\nimport { calculateCost, getShortModelName } from '../models.js'\nimport { extractBashCommands } from '../bash-utils.js'\nimport { isSqliteAvailable, getSqliteLoadError, openDatabase, type SqliteDatabase } from '../sqlite.js'\nimport type {\n Provider,\n SessionSource,\n SessionParser,\n ParsedProviderCall,\n} from './types.js'\n\ntype MessageRow = {\n id: string\n time_created: number\n data: string\n}\n\ntype PartRow = {\n message_id: string\n data: string\n}\n\ntype SessionRow = {\n id: string\n directory: string\n title: string\n time_created: number\n}\n\ntype MessageData = {\n role: string\n modelID?: string\n cost?: number\n tokens?: {\n input?: number\n output?: number\n reasoning?: number\n cache?: { read?: number; write?: number }\n }\n}\n\ntype PartData = {\n type: string\n text?: string\n tool?: string\n state?: { input?: { command?: string } }\n}\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read: 'Read',\n edit: 'Edit',\n write: 'Write',\n glob: 'Glob',\n grep: 'Grep',\n task: 'Agent',\n fetch: 'WebFetch',\n search: 'WebSearch',\n todo: 'TodoWrite',\n skill: 'Skill',\n patch: 'Patch',\n}\n\nfunction sanitize(dir: string): string {\n return dir.replace(/^\\//, '').replace(/\\//g, '-')\n}\n\nfunction getDataDir(dataDir?: string): string {\n const base =\n dataDir ??\n process.env['XDG_DATA_HOME'] ??\n join(homedir(), '.local', 'share')\n return join(base, 'opencode')\n}\n\nasync function findDbFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir)\n return entries\n .filter((f) => f.startsWith('opencode') && f.endsWith('.db'))\n .map((f) => join(dir, f))\n } catch {\n return []\n }\n}\n\nfunction parseTimestamp(raw: number): string {\n const ms = raw < 1e12 ? raw * 1000 : raw\n return new Date(ms).toISOString()\n}\n\nfunction validateSchema(db: SqliteDatabase): boolean {\n try {\n db.query<{ cnt: number }>(\n \"SELECT COUNT(*) as cnt FROM session LIMIT 1\"\n )\n db.query<{ cnt: number }>(\n \"SELECT COUNT(*) as cnt FROM message LIMIT 1\"\n )\n return true\n } catch {\n return false\n }\n}\n\nfunction createParser(\n source: SessionSource,\n seenKeys: Set<string>,\n): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n if (!isSqliteAvailable()) {\n process.stderr.write(getSqliteLoadError() + '\\n')\n return\n }\n\n // Path is encoded as `${dbPath}:${sessionId}`. Session IDs are UUIDs\n // (no colons), so the last segment after splitting on ':' is always\n // the session ID. Rejoining handles Windows drive letters (C:\\...).\n const segments = source.path.split(':')\n const sessionId = segments[segments.length - 1]!\n const dbPath = segments.slice(0, -1).join(':')\n\n let db: SqliteDatabase\n try {\n db = openDatabase(dbPath)\n } catch (err) {\n process.stderr.write(`exe-watcher: cannot open OpenCode database: ${err instanceof Error ? err.message : err}\\n`)\n return\n }\n\n try {\n if (!validateSchema(db)) {\n process.stderr.write('exe-watcher: OpenCode storage format not recognized. You may need to update Exe Watcher.\\n')\n return\n }\n\n const messages = db.query<MessageRow>(\n 'SELECT id, time_created, data FROM message WHERE session_id = ? ORDER BY time_created ASC',\n [sessionId],\n )\n\n const parts = db.query<PartRow>(\n 'SELECT message_id, data FROM part WHERE session_id = ? ORDER BY message_id, id',\n [sessionId],\n )\n\n const partsByMsg = new Map<string, PartData[]>()\n for (const part of parts) {\n try {\n const parsed = JSON.parse(part.data) as PartData\n const list = partsByMsg.get(part.message_id) ?? []\n list.push(parsed)\n partsByMsg.set(part.message_id, list)\n } catch {\n // skip corrupt part data\n }\n }\n\n let currentUserMessage = ''\n\n for (const msg of messages) {\n let data: MessageData\n try {\n data = JSON.parse(msg.data) as MessageData\n } catch {\n continue\n }\n\n if (data.role === 'user') {\n const textParts = (partsByMsg.get(msg.id) ?? [])\n .filter((p) => p.type === 'text')\n .map((p) => p.text ?? '')\n .filter(Boolean)\n if (textParts.length > 0) {\n currentUserMessage = textParts.join(' ')\n }\n continue\n }\n\n if (data.role !== 'assistant') continue\n\n const tokens = {\n input: data.tokens?.input ?? 0,\n output: data.tokens?.output ?? 0,\n reasoning: data.tokens?.reasoning ?? 0,\n cacheRead: data.tokens?.cache?.read ?? 0,\n cacheWrite: data.tokens?.cache?.write ?? 0,\n }\n\n const allZero =\n tokens.input === 0 &&\n tokens.output === 0 &&\n tokens.reasoning === 0 &&\n tokens.cacheRead === 0 &&\n tokens.cacheWrite === 0\n if (allZero && (data.cost ?? 0) === 0) continue\n\n const msgParts = partsByMsg.get(msg.id) ?? []\n const toolParts = msgParts.filter((p) => p.type === 'tool')\n const tools = toolParts\n .map((p) => toolNameMap[p.tool ?? ''] ?? p.tool ?? '')\n .filter(Boolean)\n\n const bashCommands = toolParts\n .filter((p) => p.tool === 'bash' && typeof p.state?.input?.command === 'string')\n .flatMap((p) => extractBashCommands(p.state!.input!.command!))\n\n const dedupKey = `opencode:${sessionId}:${msg.id}`\n if (seenKeys.has(dedupKey)) continue\n seenKeys.add(dedupKey)\n\n const model = data.modelID ?? 'unknown'\n let costUSD = calculateCost(\n model,\n tokens.input,\n tokens.output + tokens.reasoning,\n tokens.cacheWrite,\n tokens.cacheRead,\n 0,\n )\n\n if (costUSD === 0 && typeof data.cost === 'number' && data.cost > 0) {\n costUSD = data.cost\n }\n\n yield {\n provider: 'opencode',\n model,\n inputTokens: tokens.input,\n outputTokens: tokens.output,\n cacheCreationInputTokens: tokens.cacheWrite,\n cacheReadInputTokens: tokens.cacheRead,\n cachedInputTokens: tokens.cacheRead,\n reasoningTokens: tokens.reasoning,\n webSearchRequests: 0,\n costUSD,\n tools,\n bashCommands,\n timestamp: parseTimestamp(msg.time_created),\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: currentUserMessage,\n sessionId,\n }\n }\n } finally {\n db.close()\n }\n },\n }\n}\n\nasync function discoverFromDb(dbPath: string): Promise<SessionSource[]> {\n let db: SqliteDatabase\n try {\n db = openDatabase(dbPath)\n } catch {\n return []\n }\n\n try {\n const rows = db.query<SessionRow>(\n 'SELECT id, directory, title, time_created FROM session WHERE time_archived IS NULL AND parent_id IS NULL ORDER BY time_created DESC',\n )\n\n return rows.map((row) => ({\n path: `${dbPath}:${row.id}`,\n project: row.directory ? sanitize(row.directory) : sanitize(row.title),\n provider: 'opencode',\n }))\n } catch {\n return []\n } finally {\n db.close()\n }\n}\n\nexport function createOpenCodeProvider(dataDir?: string): Provider {\n const dir = getDataDir(dataDir)\n\n return {\n name: 'opencode',\n displayName: 'OpenCode',\n\n modelDisplayName(model: string): string {\n const stripped = model.replace(/^[^/]+\\//, '')\n return getShortModelName(stripped)\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n if (!isSqliteAvailable()) return []\n\n const dbPaths = await findDbFiles(dir)\n if (dbPaths.length === 0) return []\n\n const sessions: SessionSource[] = []\n for (const dbPath of dbPaths) {\n sessions.push(...await discoverFromDb(dbPath))\n }\n return sessions\n },\n\n createSessionParser(\n source: SessionSource,\n seenKeys: Set<string>,\n ): SessionParser {\n return createParser(source, seenKeys)\n },\n }\n}\n\nexport const opencode = createOpenCodeProvider()\n","import { createHash } from 'crypto'\nimport { existsSync } from 'fs'\nimport { readdir, readFile, stat } from 'fs/promises'\nimport { join, basename } from 'path'\nimport { homedir } from 'os'\n\nimport { calculateCost } from '../models.js'\nimport { openDatabase, type SqliteDatabase } from '../sqlite.js'\nimport type {\n Provider,\n SessionSource,\n SessionParser,\n ParsedProviderCall,\n} from './types.js'\n\ntype ConversationSummary = {\n conversationId: string\n model: string | null\n title: string | null\n updatedAt: string | null\n}\n\ntype AssistantTurn = {\n body: string\n reasoning: string\n tools: string[]\n}\n\ntype ParsedTurn = {\n userMessage: string\n assistant: AssistantTurn\n}\n\nconst CURSOR_AGENT_DEFAULT_MODEL = 'claude-sonnet-4-5'\nconst CHARS_PER_TOKEN = 4\nconst MAX_USER_TEXT_LENGTH = 500\nconst DIGITS_ONLY = /^\\d+$/\nconst UUID_LIKE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\nconst USER_MARKER = /^\\s*user:\\s*/i\nconst ASSISTANT_MARKER = /^\\s*A:\\s*/\nconst THINKING_MARKER = /^\\s*\\[Thinking\\]\\s*/\nconst TOOL_CALL_MARKER = /^\\s*\\[Tool call\\]\\s*(.+?)\\s*$/i\nconst TOOL_RESULT_MARKER = /^\\s*\\[Tool result\\]\\b/i\nconst USER_QUERY_OPEN = '<user_query>'\nconst USER_QUERY_CLOSE = '</user_query>'\nconst CONVERSATION_SUMMARY_QUERY = `\n SELECT conversationId, model, title, updatedAt\n FROM conversation_summaries\n WHERE conversationId = ?\n`\n\nconst modelDisplayNames: Record<string, string> = {\n 'claude-4.5-opus-high-thinking': 'Opus 4.5 (Thinking)',\n 'claude-4-opus': 'Opus 4',\n 'claude-4-sonnet-thinking': 'Sonnet 4 (Thinking)',\n 'claude-4.5-sonnet-thinking': 'Sonnet 4.5 (Thinking)',\n 'claude-4.6-sonnet': 'Sonnet 4.6',\n 'composer-1': 'Composer 1',\n 'grok-code-fast-1': 'Grok Code Fast',\n 'gemini-3-pro': 'Gemini 3 Pro',\n 'gpt-5.1-codex-high': 'GPT-5.1 Codex',\n 'gpt-5': 'GPT-5',\n 'gpt-4.1': 'GPT-4.1',\n default: 'Auto (Sonnet est.)',\n}\n\nfunction getCursorAgentBaseDir(baseDirOverride?: string): string {\n if (baseDirOverride) return baseDirOverride\n // Windows paths unverified; tracked as Open Question 3 in issue #55.\n return join(homedir(), '.cursor')\n}\n\nfunction getProjectsDir(baseDir: string): string {\n return join(baseDir, 'projects')\n}\n\nfunction getAttributionDbPath(baseDir: string): string {\n return join(baseDir, 'ai-tracking', 'ai-code-tracking.db')\n}\n\nfunction estimateTokens(charCount: number): number {\n if (charCount <= 0) return 0\n return Math.ceil(charCount / CHARS_PER_TOKEN)\n}\n\nfunction parseToolName(raw: string): string {\n const clean = raw.trim()\n if (clean.length === 0) return 'unknown'\n return clean.toLowerCase().replace(/\\s+/g, '-')\n}\n\nfunction normalizeTimestamp(raw: string | number | null | undefined): string | null {\n if (raw === null || raw === undefined) return null\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (trimmed.length === 0) return null\n if (DIGITS_ONLY.test(trimmed)) {\n const num = Number(trimmed)\n if (!Number.isNaN(num)) {\n const ms = num < 1e12 ? num * 1000 : num\n return new Date(ms).toISOString()\n }\n }\n const parsed = new Date(trimmed)\n if (!Number.isNaN(parsed.getTime())) return parsed.toISOString()\n return null\n }\n\n const ms = raw < 1e12 ? raw * 1000 : raw\n return new Date(ms).toISOString()\n}\n\nfunction prettifyProjectId(raw: string): string {\n if (!raw) return raw\n\n if (DIGITS_ONLY.test(raw)) {\n const num = Number(raw)\n if (!Number.isNaN(num) && raw.length >= 13) {\n const iso = new Date(num).toISOString()\n return `cursor-agent:${iso}`\n }\n }\n\n // Strip encoded home directory prefix on macOS (-Users-<user>-...)\n // and Windows (-C-Users-<user>-... or -<Drive>-Users-<user>-...)\n const withoutPrefix = raw.replace(/^-(?:[A-Za-z]-)?Users-[^-]+-?/, '')\n const parts = withoutPrefix.split('-').filter(Boolean)\n if (parts.length > 0) return parts[parts.length - 1]!\n\n return raw\n}\n\nfunction resolveModel(raw: string | null | undefined): string {\n if (!raw || raw === 'default') return CURSOR_AGENT_DEFAULT_MODEL\n return raw\n}\n\nfunction toConversationId(transcriptPath: string): string {\n const filename = basename(transcriptPath, '.txt')\n if (filename.length === 36 && UUID_LIKE.test(filename)) return filename\n return createHash('sha1').update(transcriptPath).digest('hex').slice(0, 16)\n}\n\nfunction extractUserQuery(userBlock: string): string {\n const chunks: string[] = []\n let cursor = 0\n\n while (cursor < userBlock.length) {\n const openIndex = userBlock.indexOf(USER_QUERY_OPEN, cursor)\n if (openIndex === -1) break\n const start = openIndex + USER_QUERY_OPEN.length\n const closeIndex = userBlock.indexOf(USER_QUERY_CLOSE, start)\n if (closeIndex === -1) {\n chunks.push(userBlock.slice(start).trim())\n break\n }\n chunks.push(userBlock.slice(start, closeIndex).trim())\n cursor = closeIndex + USER_QUERY_CLOSE.length\n }\n\n const combined = chunks.filter(Boolean).join(' ').replace(/\\s+/g, ' ').trim()\n return combined.slice(0, MAX_USER_TEXT_LENGTH)\n}\n\nfunction parseTranscript(raw: string): { turns: ParsedTurn[]; recognized: boolean } {\n const lines = raw.split(/\\r?\\n/)\n let recognized = false\n\n const pendingUsers: string[] = []\n const turns: ParsedTurn[] = []\n\n let active: 'none' | 'user' | 'assistant' = 'none'\n let userLines: string[] = []\n let assistantLines: string[] = []\n\n const flushUser = () => {\n if (userLines.length === 0) return\n const userQuery = extractUserQuery(userLines.join('\\n'))\n if (userQuery.length > 0) pendingUsers.push(userQuery)\n userLines = []\n }\n\n const flushAssistant = () => {\n if (assistantLines.length === 0) return\n\n let output = ''\n let reasoning = ''\n const toolsByTurn: Record<string, boolean> = Object.create(null)\n\n for (const line of assistantLines) {\n if (TOOL_RESULT_MARKER.test(line)) continue\n\n const thinkingMatch = line.match(THINKING_MARKER)\n if (thinkingMatch) {\n const body = line.replace(THINKING_MARKER, '').trim()\n if (body.length > 0) reasoning += `${body}\\n`\n continue\n }\n\n const toolMatch = line.match(TOOL_CALL_MARKER)\n if (toolMatch) {\n const parsedTool = parseToolName(toolMatch[1] ?? '')\n const toolKey = `cursor:${parsedTool}`\n toolsByTurn[toolKey] = true\n continue\n }\n\n output += `${line}\\n`\n }\n\n if (pendingUsers.length > 0) {\n const userMessage = pendingUsers.shift()!\n const tools = Object.keys(toolsByTurn)\n turns.push({\n userMessage,\n assistant: {\n body: output.trim(),\n reasoning: reasoning.trim(),\n tools,\n },\n })\n }\n\n assistantLines = []\n }\n\n for (const line of lines) {\n if (USER_MARKER.test(line)) {\n recognized = true\n if (active === 'user') flushUser()\n if (active === 'assistant') flushAssistant()\n active = 'user'\n userLines = [line.replace(USER_MARKER, '')]\n continue\n }\n\n if (ASSISTANT_MARKER.test(line)) {\n recognized = true\n if (active === 'user') flushUser()\n if (active === 'assistant') flushAssistant()\n active = 'assistant'\n assistantLines = [line.replace(ASSISTANT_MARKER, '')]\n continue\n }\n\n if (active === 'user') {\n userLines.push(line)\n continue\n }\n\n if (active === 'assistant') {\n assistantLines.push(line)\n }\n }\n\n if (active === 'user') flushUser()\n if (active === 'assistant') flushAssistant()\n\n return { turns, recognized }\n}\n\nfunction createParser(\n source: SessionSource,\n seenKeys: Set<string>,\n dbPath: string,\n summariesByConversationId: Record<string, ConversationSummary | undefined>,\n): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n const conversationId = toConversationId(source.path)\n\n let summary = summariesByConversationId[conversationId]\n let db: SqliteDatabase | null = null\n\n try {\n if (!summary) {\n if (existsSync(dbPath)) {\n try {\n db = openDatabase(dbPath)\n const rows = db.query<{\n conversationId: string\n model: string | null\n title: string | null\n updatedAt: string | number | null\n }>(CONVERSATION_SUMMARY_QUERY, [conversationId])\n\n if (rows.length > 0) {\n const row = rows[0]!\n summary = {\n conversationId: row.conversationId,\n model: row.model,\n title: row.title,\n updatedAt: normalizeTimestamp(row.updatedAt),\n }\n summariesByConversationId[conversationId] = summary\n }\n } catch {\n summary = undefined\n }\n }\n }\n\n const transcript = await readFile(source.path, 'utf-8')\n const parsed = parseTranscript(transcript)\n\n if (!parsed.recognized) {\n process.stderr.write(`exe-watcher: skipped ${basename(source.path)}: unrecognized cursor-agent transcript format\\n`)\n return\n }\n\n let timestamp = summary?.updatedAt ?? null\n if (!timestamp) {\n const fileStat = await stat(source.path)\n timestamp = fileStat.mtime.toISOString()\n }\n\n const model = resolveModel(summary?.model ?? null)\n\n for (let turnIndex = 0; turnIndex < parsed.turns.length; turnIndex++) {\n const turn = parsed.turns[turnIndex]!\n const inputTokens = estimateTokens(turn.userMessage.length)\n const outputTokens = estimateTokens(turn.assistant.body.length)\n const reasoningTokens = estimateTokens(turn.assistant.reasoning.length)\n const deduplicationKey = `cursor-agent:${conversationId}:${turnIndex}`\n\n if (seenKeys.has(deduplicationKey)) continue\n seenKeys.add(deduplicationKey)\n\n const costUSD = calculateCost(\n model,\n inputTokens,\n outputTokens + reasoningTokens,\n 0,\n 0,\n 0,\n )\n\n yield {\n provider: 'cursor-agent',\n model,\n inputTokens,\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: 0,\n cachedInputTokens: 0,\n reasoningTokens,\n webSearchRequests: 0,\n costUSD,\n tools: turn.assistant.tools,\n bashCommands: [],\n timestamp,\n speed: 'standard',\n deduplicationKey,\n userMessage: turn.userMessage,\n sessionId: conversationId,\n }\n }\n } finally {\n db?.close()\n }\n },\n }\n}\n\nexport function createCursorAgentProvider(baseDirOverride?: string): Provider {\n const baseDir = getCursorAgentBaseDir(baseDirOverride)\n const projectsDir = getProjectsDir(baseDir)\n const dbPath = getAttributionDbPath(baseDir)\n const summariesByConversationId: Record<string, ConversationSummary | undefined> = Object.create(null)\n\n return {\n name: 'cursor-agent',\n displayName: 'Cursor Agent',\n\n modelDisplayName(model: string): string {\n if (model === 'default') return modelDisplayNames.default\n const label = modelDisplayNames[model] ?? model\n return `${label} (est.)`\n },\n\n toolDisplayName(rawTool: string): string {\n return rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n if (!existsSync(projectsDir)) return []\n\n const projectEntries = await readdir(projectsDir, { withFileTypes: true })\n const sources: SessionSource[] = []\n\n for (const entry of projectEntries) {\n if (!entry.isDirectory()) continue\n\n const projectId = prettifyProjectId(entry.name)\n const transcriptDir = join(projectsDir, entry.name, 'agent-transcripts')\n if (!existsSync(transcriptDir)) continue\n\n const transcriptEntries = await readdir(transcriptDir, { withFileTypes: true })\n for (const transcript of transcriptEntries) {\n if (!transcript.isFile()) continue\n if (!transcript.name.endsWith('.txt')) continue\n\n const transcriptPath = join(transcriptDir, transcript.name)\n sources.push({\n path: transcriptPath,\n project: projectId,\n provider: 'cursor-agent',\n })\n }\n }\n\n return sources\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys, dbPath, summariesByConversationId)\n },\n }\n}\n\nexport const cursor_agent = createCursorAgentProvider()\n","import { existsSync, readFileSync, statSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { Command } from 'commander'\nimport { installMenubarApp } from './menubar-installer.js'\nimport { exportCsv, exportJson, type PeriodExport } from './export.js'\nimport { loadPricing, setModelAliases } from './models.js'\nimport { parseAllSessions, filterProjectsByName } from './parser.js'\nimport { convertCost } from './currency.js'\nimport { renderStatusBar } from './format.js'\nimport { type PeriodData, type ProviderCost, type AgentStatsPayload } from './menubar-json.js'\nimport { buildMenubarPayload, computeAgentSpend, mergeAgentSpend, buildProjectSpend, estimateAgentCosts } from './menubar-json.js'\nimport { addNewDays, getDaysInRange, loadDailyCache, saveDailyCache, withDailyCacheLock } from './daily-cache.js'\nimport { aggregateProjectsIntoDays, buildPeriodDataFromDays, dateKey } from './day-aggregator.js'\nimport { CATEGORY_LABELS, type DateRange, type ProjectSummary, type TaskCategory } from './types.js'\nimport { renderDashboard } from './dashboard.js'\nimport { parseDateRangeFlags } from './cli-date.js'\nimport { runOptimize, scanAndDetect } from './optimize.js'\nimport { renderCompare } from './compare.js'\nimport { getAllProviders } from './providers/index.js'\nimport { clearPlan, readConfig, readPlan, saveConfig, savePlan, getConfigFilePath, type PlanId } from './config.js'\nimport { clampResetDay, getPlanUsageOrNull, type PlanUsage } from './plan-usage.js'\nimport { getPresetPlan, isPlanId, isPlanProvider, planDisplayName } from './plans.js'\nimport { createRequire } from 'node:module'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json')\nimport { loadCurrency, getCurrency, isValidCurrencyCode } from './currency.js'\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000\nconst BACKFILL_DAYS = 365\n\nfunction toDateString(date: Date): string {\n return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`\n}\n\nfunction getDateRange(period: string): { range: DateRange; label: string } {\n const now = new Date()\n const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)\n\n switch (period) {\n case 'today': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n return { range: { start, end }, label: `Today (${toDateString(start)})` }\n }\n case 'yesterday': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1)\n const yesterdayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 23, 59, 59, 999)\n return { range: { start, end: yesterdayEnd }, label: `Yesterday (${toDateString(start)})` }\n }\n case 'week': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7)\n return { range: { start, end }, label: 'Last 7 Days' }\n }\n case 'month': {\n const start = new Date(now.getFullYear(), now.getMonth(), 1)\n return { range: { start, end }, label: `${now.toLocaleString('default', { month: 'long' })} ${now.getFullYear()}` }\n }\n case '30days': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 30)\n return { range: { start, end }, label: 'Last 30 Days' }\n }\n case 'all': {\n // Cap \"All Time\" to the last 6 months. Older data is rarely actionable for a cost\n // tracker and keeps the parse path bounded so providers like Codex/Cursor with sparse\n // data still load in seconds.\n const start = new Date(now.getFullYear(), now.getMonth() - 6, now.getDate())\n return { range: { start, end }, label: 'Last 6 months' }\n }\n default: {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7)\n return { range: { start, end }, label: 'Last 7 Days' }\n }\n }\n}\n\ntype Period = 'today' | 'week' | '30days' | 'month' | 'all'\n\nfunction toPeriod(s: string): Period {\n if (s === 'today') return 'today'\n if (s === 'month') return 'month'\n if (s === '30days') return '30days'\n if (s === 'all') return 'all'\n return 'week'\n}\n\nfunction collect(val: string, acc: string[]): string[] {\n acc.push(val)\n return acc\n}\n\nfunction parseNumber(value: string): number {\n return Number(value)\n}\n\nfunction parseInteger(value: string): number {\n return parseInt(value, 10)\n}\n\ntype JsonPlanSummary = {\n id: PlanId\n budget: number\n spent: number\n percentUsed: number\n status: 'under' | 'near' | 'over'\n projectedMonthEnd: number\n daysUntilReset: number\n periodStart: string\n periodEnd: string\n}\n\nfunction toJsonPlanSummary(planUsage: PlanUsage): JsonPlanSummary {\n return {\n id: planUsage.plan.id,\n budget: convertCost(planUsage.budgetUsd),\n spent: convertCost(planUsage.spentApiEquivalentUsd),\n percentUsed: Math.round(planUsage.percentUsed * 10) / 10,\n status: planUsage.status,\n projectedMonthEnd: convertCost(planUsage.projectedMonthUsd),\n daysUntilReset: planUsage.daysUntilReset,\n periodStart: planUsage.periodStart.toISOString(),\n periodEnd: planUsage.periodEnd.toISOString(),\n }\n}\n\nasync function runJsonReport(period: Period, provider: string, project: string[], exclude: string[]): Promise<void> {\n await loadPricing()\n const { range, label } = getDateRange(period)\n const projects = filterProjectsByName(await parseAllSessions(range, provider), project, exclude)\n const report: ReturnType<typeof buildJsonReport> & { plan?: JsonPlanSummary } = buildJsonReport(projects, label, period)\n const planUsage = await getPlanUsageOrNull()\n if (planUsage) {\n report.plan = toJsonPlanSummary(planUsage)\n }\n console.log(JSON.stringify(report, null, 2))\n}\n\nconst program = new Command()\n .name('exe-watcher')\n .description('See where your AI coding tokens go - by task, tool, model, and project')\n .version(version)\n .option('--verbose', 'print warnings to stderr on read failures and skipped files')\n\nprogram.hook('preAction', async (thisCommand) => {\n const config = await readConfig()\n setModelAliases(config.modelAliases ?? {})\n if (thisCommand.opts<{ verbose?: boolean }>().verbose) {\n process.env['EXE_WATCHER_VERBOSE'] = '1'\n }\n await loadCurrency()\n})\n\nfunction buildJsonReport(projects: ProjectSummary[], period: string, periodKey: string) {\n const sessions = projects.flatMap(p => p.sessions)\n const { code } = getCurrency()\n\n const totalCostUSD = projects.reduce((s, p) => s + p.totalCostUSD, 0)\n const totalCalls = projects.reduce((s, p) => s + p.totalApiCalls, 0)\n const totalSessions = projects.reduce((s, p) => s + p.sessions.length, 0)\n const totalInput = sessions.reduce((s, sess) => s + sess.totalInputTokens, 0)\n const totalOutput = sessions.reduce((s, sess) => s + sess.totalOutputTokens, 0)\n const totalCacheRead = sessions.reduce((s, sess) => s + sess.totalCacheReadTokens, 0)\n const totalCacheWrite = sessions.reduce((s, sess) => s + sess.totalCacheWriteTokens, 0)\n // Match src/menubar-json.ts:cacheHitPercent: reads over reads+fresh-input. cache_write\n // counts tokens being stored, not served, so it doesn't belong in the denominator.\n const cacheHitDenom = totalInput + totalCacheRead\n const cacheHitPercent = cacheHitDenom > 0 ? Math.round((totalCacheRead / cacheHitDenom) * 1000) / 10 : 0\n\n const dailyMap: Record<string, { cost: number; calls: number }> = {}\n for (const sess of sessions) {\n for (const turn of sess.turns) {\n if (!turn.timestamp) { continue }\n const day = dateKey(turn.timestamp)\n if (!dailyMap[day]) { dailyMap[day] = { cost: 0, calls: 0 } }\n for (const call of turn.assistantCalls) {\n dailyMap[day].cost += call.costUSD\n dailyMap[day].calls += 1\n }\n }\n }\n const daily = Object.entries(dailyMap).sort().map(([date, d]) => ({\n date,\n cost: convertCost(d.cost),\n calls: d.calls,\n }))\n\n const projectList = projects.map(p => ({\n name: p.project,\n path: p.projectPath,\n cost: convertCost(p.totalCostUSD),\n avgCostPerSession: p.sessions.length > 0\n ? convertCost(p.totalCostUSD / p.sessions.length)\n : null,\n calls: p.totalApiCalls,\n sessions: p.sessions.length,\n }))\n\n const modelMap: Record<string, { calls: number; cost: number; inputTokens: number; outputTokens: number; cacheReadTokens: number; cacheWriteTokens: number }> = {}\n for (const sess of sessions) {\n for (const [model, d] of Object.entries(sess.modelBreakdown)) {\n if (!modelMap[model]) { modelMap[model] = { calls: 0, cost: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 } }\n modelMap[model].calls += d.calls\n modelMap[model].cost += d.costUSD\n modelMap[model].inputTokens += d.tokens.inputTokens\n modelMap[model].outputTokens += d.tokens.outputTokens\n modelMap[model].cacheReadTokens += d.tokens.cacheReadInputTokens\n modelMap[model].cacheWriteTokens += d.tokens.cacheCreationInputTokens\n }\n }\n const models = Object.entries(modelMap)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([name, { cost, ...rest }]) => ({ name, ...rest, cost: convertCost(cost) }))\n\n const catMap: Record<string, { turns: number; cost: number; editTurns: number; oneShotTurns: number }> = {}\n for (const sess of sessions) {\n for (const [cat, d] of Object.entries(sess.categoryBreakdown)) {\n if (!catMap[cat]) { catMap[cat] = { turns: 0, cost: 0, editTurns: 0, oneShotTurns: 0 } }\n catMap[cat].turns += d.turns\n catMap[cat].cost += d.costUSD\n catMap[cat].editTurns += d.editTurns\n catMap[cat].oneShotTurns += d.oneShotTurns\n }\n }\n const activities = Object.entries(catMap)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([cat, d]) => ({\n category: CATEGORY_LABELS[cat as TaskCategory] ?? cat,\n cost: convertCost(d.cost),\n turns: d.turns,\n editTurns: d.editTurns,\n oneShotTurns: d.oneShotTurns,\n oneShotRate: d.editTurns > 0 ? Math.round((d.oneShotTurns / d.editTurns) * 1000) / 10 : null,\n }))\n\n const toolMap: Record<string, number> = {}\n const mcpMap: Record<string, number> = {}\n const bashMap: Record<string, number> = {}\n for (const sess of sessions) {\n for (const [tool, d] of Object.entries(sess.toolBreakdown)) {\n toolMap[tool] = (toolMap[tool] ?? 0) + d.calls\n }\n for (const [server, d] of Object.entries(sess.mcpBreakdown)) {\n mcpMap[server] = (mcpMap[server] ?? 0) + d.calls\n }\n for (const [cmd, d] of Object.entries(sess.bashBreakdown)) {\n bashMap[cmd] = (bashMap[cmd] ?? 0) + d.calls\n }\n }\n\n const sortedMap = (m: Record<string, number>) =>\n Object.entries(m).sort(([, a], [, b]) => b - a).map(([name, calls]) => ({ name, calls }))\n\n const topSessions = projects\n .flatMap(p => p.sessions.map(s => ({ project: p.project, sessionId: s.sessionId, date: s.firstTimestamp ? dateKey(s.firstTimestamp) : null, cost: convertCost(s.totalCostUSD), calls: s.apiCalls })))\n .sort((a, b) => b.cost - a.cost)\n .slice(0, 5)\n\n return {\n generated: new Date().toISOString(),\n currency: code,\n period,\n periodKey,\n overview: {\n cost: convertCost(totalCostUSD),\n calls: totalCalls,\n sessions: totalSessions,\n cacheHitPercent,\n tokens: {\n input: totalInput,\n output: totalOutput,\n cacheRead: totalCacheRead,\n cacheWrite: totalCacheWrite,\n },\n },\n daily,\n projects: projectList,\n models,\n activities,\n tools: sortedMap(toolMap),\n mcpServers: sortedMap(mcpMap),\n shellCommands: sortedMap(bashMap),\n topSessions,\n }\n}\n\nprogram\n .command('report', { isDefault: true })\n .description('Interactive usage dashboard')\n .option('-p, --period <period>', 'Starting period: today, week, 30days, month, all', 'week')\n .option('--from <date>', 'Start date (YYYY-MM-DD). Overrides --period when set')\n .option('--to <date>', 'End date (YYYY-MM-DD). Overrides --period when set')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .option('--format <format>', 'Output format: tui, json', 'tui')\n .option('--project <name>', 'Show only projects matching name (repeatable)', collect, [])\n .option('--exclude <name>', 'Exclude projects matching name (repeatable)', collect, [])\n .option('--refresh <seconds>', 'Auto-refresh interval in seconds (0 to disable)', parseInt, 30)\n .action(async (opts) => {\n let customRange: DateRange | null = null\n try {\n customRange = parseDateRangeFlags(opts.from, opts.to)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`\\n Error: ${message}\\n`)\n process.exit(1)\n }\n\n const period = toPeriod(opts.period)\n if (opts.format === 'json') {\n await loadPricing()\n if (customRange) {\n const label = `${opts.from ?? 'all'} to ${opts.to ?? 'today'}`\n const projects = filterProjectsByName(\n await parseAllSessions(customRange, opts.provider),\n opts.project,\n opts.exclude,\n )\n console.log(JSON.stringify(buildJsonReport(projects, label, 'custom'), null, 2))\n } else {\n await runJsonReport(period, opts.provider, opts.project, opts.exclude)\n }\n return\n }\n await renderDashboard(period, opts.provider, opts.refresh, opts.project, opts.exclude, customRange)\n })\n\nfunction buildPeriodData(label: string, projects: ProjectSummary[]): PeriodData {\n const sessions = projects.flatMap(p => p.sessions)\n const catTotals: Record<string, { turns: number; cost: number; editTurns: number; oneShotTurns: number }> = {}\n const modelTotals: Record<string, { calls: number; cost: number }> = {}\n let inputTokens = 0, outputTokens = 0, cacheReadTokens = 0, cacheWriteTokens = 0\n\n for (const sess of sessions) {\n inputTokens += sess.totalInputTokens\n outputTokens += sess.totalOutputTokens\n cacheReadTokens += sess.totalCacheReadTokens\n cacheWriteTokens += sess.totalCacheWriteTokens\n for (const [cat, d] of Object.entries(sess.categoryBreakdown)) {\n if (!catTotals[cat]) catTotals[cat] = { turns: 0, cost: 0, editTurns: 0, oneShotTurns: 0 }\n catTotals[cat].turns += d.turns\n catTotals[cat].cost += d.costUSD\n catTotals[cat].editTurns += d.editTurns\n catTotals[cat].oneShotTurns += d.oneShotTurns\n }\n for (const [model, d] of Object.entries(sess.modelBreakdown)) {\n if (!modelTotals[model]) modelTotals[model] = { calls: 0, cost: 0 }\n modelTotals[model].calls += d.calls\n modelTotals[model].cost += d.costUSD\n }\n }\n\n return {\n label,\n cost: projects.reduce((s, p) => s + p.totalCostUSD, 0),\n calls: projects.reduce((s, p) => s + p.totalApiCalls, 0),\n sessions: projects.reduce((s, p) => s + p.sessions.length, 0),\n inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens,\n categories: Object.entries(catTotals)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([cat, d]) => ({ name: CATEGORY_LABELS[cat as TaskCategory] ?? cat, ...d })),\n models: Object.entries(modelTotals)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([name, d]) => ({ name, ...d })),\n }\n}\n\nprogram\n .command('status')\n .description('Compact status output (today + week + month)')\n .option('--format <format>', 'Output format: terminal, menubar-json, json', 'terminal')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .option('--project <name>', 'Show only projects matching name (repeatable)', collect, [])\n .option('--exclude <name>', 'Exclude projects matching name (repeatable)', collect, [])\n .option('--period <period>', 'Primary period for menubar-json: today, week, 30days, month, all', 'today')\n .option('--no-optimize', 'Skip optimize findings (menubar-json only, faster)')\n .action(async (opts) => {\n await loadPricing()\n const pf = opts.provider\n const fp = (p: ProjectSummary[]) => filterProjectsByName(p, opts.project, opts.exclude)\n if (opts.format === 'menubar-json') {\n const periodInfo = getDateRange(opts.period)\n const now = new Date()\n const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const yesterdayEnd = new Date(todayStart.getTime() - 1)\n const yesterdayStr = toDateString(new Date(todayStart.getTime() - MS_PER_DAY))\n const isAllProviders = pf === 'all'\n\n // The daily cache is provider-agnostic: always backfill it from .all so subsequent\n // provider-filtered reads can derive per-provider cost+calls from DailyEntry.providers.\n // Yesterday is always recomputed: it may have been cached mid-day with partial data.\n const cache = await withDailyCacheLock(async () => {\n let c = await loadDailyCache()\n\n // Evict yesterday (and any stale future entries) so the gap fill recomputes them.\n const hadYesterday = c.days.some(d => d.date >= yesterdayStr)\n if (hadYesterday) {\n const freshDays = c.days.filter(d => d.date < yesterdayStr)\n const latestFresh = freshDays.length > 0 ? freshDays[freshDays.length - 1].date : null\n c = { ...c, days: freshDays, lastComputedDate: latestFresh }\n }\n\n const gapStart = c.lastComputedDate\n ? new Date(\n parseInt(c.lastComputedDate.slice(0, 4)),\n parseInt(c.lastComputedDate.slice(5, 7)) - 1,\n parseInt(c.lastComputedDate.slice(8, 10)) + 1\n )\n : new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY)\n\n if (gapStart.getTime() <= yesterdayEnd.getTime()) {\n const gapRange: DateRange = { start: gapStart, end: yesterdayEnd }\n const gapProjects = filterProjectsByName(await parseAllSessions(gapRange, 'all'), opts.project, opts.exclude)\n const gapDays = aggregateProjectsIntoDays(gapProjects)\n c = addNewDays(c, gapDays, yesterdayStr)\n await saveDailyCache(c)\n }\n return c\n })\n\n // CURRENT PERIOD DATA\n // - .all provider: assemble from cache + today (fast)\n // - specific provider: parse the period range with provider filter (correct, but slower)\n let currentData: PeriodData\n let scanProjects: ProjectSummary[]\n let scanRange: DateRange\n\n // Parse only today's sessions once — reused across period data, providers, and history.\n const todayRange: DateRange = { start: todayStart, end: periodInfo.range.end }\n const todayProjects = fp(await parseAllSessions(todayRange, 'all'))\n const todayDays = aggregateProjectsIntoDays(todayProjects)\n\n if (isAllProviders) {\n const rangeStartStr = toDateString(periodInfo.range.start)\n const rangeEndStr = toDateString(periodInfo.range.end)\n const historicalDays = getDaysInRange(cache, rangeStartStr, yesterdayStr)\n // Only include today from the fresh parse — historical days already come from cache.\n // Without this filter, days between rangeStart and yesterday appear in BOTH arrays.\n const todayOnly = todayDays.filter(d => d.date > yesterdayStr && d.date <= rangeEndStr)\n const allDays = [...historicalDays, ...todayOnly].sort((a, b) => a.date.localeCompare(b.date))\n currentData = buildPeriodDataFromDays(allDays, periodInfo.label)\n scanProjects = todayProjects\n scanRange = periodInfo.range\n } else {\n const projects = fp(await parseAllSessions(periodInfo.range, pf))\n currentData = buildPeriodData(periodInfo.label, projects)\n scanProjects = projects\n scanRange = periodInfo.range\n }\n\n // PROVIDERS\n // For .all: enumerate every provider with cost across the period (from cache) + installed-but-zero.\n // For specific: just this single provider with its scoped cost.\n const allProviders = await getAllProviders()\n const displayNameByName = new Map(allProviders.map(p => [p.name, p.displayName]))\n const providers: ProviderCost[] = []\n if (isAllProviders) {\n // Reuse todayDays from above (already parsed today only), combine with cache\n const rangeStartStr = toDateString(periodInfo.range.start)\n const allDaysForProviders = [\n ...getDaysInRange(cache, rangeStartStr, yesterdayStr),\n ...todayDays.filter(d => d.date > yesterdayStr),\n ]\n const providerTotals: Record<string, number> = {}\n for (const d of allDaysForProviders) {\n for (const [name, p] of Object.entries(d.providers)) {\n providerTotals[name] = (providerTotals[name] ?? 0) + p.cost\n }\n }\n for (const [name, cost] of Object.entries(providerTotals)) {\n providers.push({ name: displayNameByName.get(name) ?? name, cost })\n }\n for (const p of allProviders) {\n if (providers.some(pc => pc.name === p.displayName)) continue\n const sources = await p.discoverSessions()\n if (sources.length > 0) providers.push({ name: p.displayName, cost: 0 })\n }\n } else {\n const display = displayNameByName.get(pf) ?? pf\n providers.push({ name: display, cost: currentData.cost })\n }\n\n // DAILY HISTORY (last 365 days)\n // Cache stores per-provider cost+calls per day in DailyEntry.providers, so we can derive\n // a provider-filtered history without re-parsing. Tokens aren't broken down per provider\n // in the cache, so the filtered view shows zero tokens (heatmap/trend still works on cost).\n const historyStartStr = toDateString(new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY))\n const allCacheDays = getDaysInRange(cache, historyStartStr, yesterdayStr)\n // Reuse todayDays from above — no need to re-parse\n const fullHistory = [...allCacheDays, ...todayDays.filter(d => d.date > yesterdayStr)]\n const dailyHistory = fullHistory.map(d => {\n if (isAllProviders) {\n const topModels = Object.entries(d.models)\n .filter(([name]) => name !== '<synthetic>')\n .sort(([, a], [, b]) => b.cost - a.cost)\n .slice(0, 5)\n .map(([name, m]) => ({\n name,\n cost: m.cost,\n calls: m.calls,\n inputTokens: m.inputTokens,\n outputTokens: m.outputTokens,\n }))\n return {\n date: d.date,\n cost: d.cost,\n calls: d.calls,\n inputTokens: d.inputTokens,\n outputTokens: d.outputTokens,\n cacheReadTokens: d.cacheReadTokens,\n cacheWriteTokens: d.cacheWriteTokens,\n topModels,\n }\n }\n const prov = d.providers[pf] ?? { calls: 0, cost: 0 }\n return {\n date: d.date,\n cost: prov.cost,\n calls: prov.calls,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n topModels: [],\n }\n })\n\n const optimize = opts.optimize === false ? null : await scanAndDetect(scanProjects, scanRange)\n\n // Read exe-os agent stats if available (auto-detect exe-os presence)\n const exeOsDir = join(homedir(), '.exe-os')\n const exeOsDetected = existsSync(exeOsDir)\n let agentStats: AgentStatsPayload | null = null\n let statsFileAge: number | null = null\n try {\n const statsPath = join(exeOsDir, 'agent-stats.json')\n if (existsSync(statsPath)) {\n statsFileAge = Math.round((Date.now() - statSync(statsPath).mtimeMs) / 1000)\n const parsed = JSON.parse(readFileSync(statsPath, 'utf-8'))\n if (parsed && Array.isArray(parsed.agents) && typeof parsed.generated === 'string') {\n agentStats = parsed as AgentStatsPayload\n } else {\n process.stderr.write('[exe-watcher] agent-stats.json has unexpected schema, ignoring\\n')\n }\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err)\n process.stderr.write(`[exe-watcher] agent-stats.json found but failed to parse: ${msg}\\n`)\n }\n\n // Per-agent spend: use daemon's token data (from session_agent_map + JSONL parsing)\n // then estimate USD cost from token counts using blended pricing.\n if (agentStats) {\n agentStats = estimateAgentCosts(agentStats)\n }\n\n // Per-project spend across 24h/7d/30d periods.\n const [proj24h, proj7d, proj30d] = await Promise.all([\n parseAllSessions(getDateRange('today').range, 'all'),\n parseAllSessions(getDateRange('week').range, 'all'),\n parseAllSessions(getDateRange('30days').range, 'all'),\n ])\n const projectSpend = buildProjectSpend(proj24h, proj7d, proj30d)\n\n console.log(JSON.stringify(buildMenubarPayload(currentData, providers, optimize, dailyHistory, agentStats, projectSpend, exeOsDetected, statsFileAge)))\n return\n }\n\n if (opts.format === 'json') {\n const todayData = buildPeriodData('today', fp(await parseAllSessions(getDateRange('today').range, pf)))\n const monthData = buildPeriodData('month', fp(await parseAllSessions(getDateRange('month').range, pf)))\n const { code, rate } = getCurrency()\n const payload: {\n currency: string\n today: { cost: number; calls: number }\n month: { cost: number; calls: number }\n plan?: JsonPlanSummary\n } = {\n currency: code,\n today: { cost: Math.round(todayData.cost * rate * 100) / 100, calls: todayData.calls },\n month: { cost: Math.round(monthData.cost * rate * 100) / 100, calls: monthData.calls },\n }\n const planUsage = await getPlanUsageOrNull()\n if (planUsage) {\n payload.plan = toJsonPlanSummary(planUsage)\n }\n console.log(JSON.stringify(payload))\n return\n }\n\n const monthProjects = fp(await parseAllSessions(getDateRange('month').range, pf))\n console.log(renderStatusBar(monthProjects))\n })\n\nprogram\n .command('today')\n .description('Today\\'s usage dashboard')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .option('--format <format>', 'Output format: tui, json', 'tui')\n .option('--project <name>', 'Show only projects matching name (repeatable)', collect, [])\n .option('--exclude <name>', 'Exclude projects matching name (repeatable)', collect, [])\n .option('--refresh <seconds>', 'Auto-refresh interval in seconds (0 to disable)', parseInt, 30)\n .action(async (opts) => {\n if (opts.format === 'json') {\n await runJsonReport('today', opts.provider, opts.project, opts.exclude)\n return\n }\n await renderDashboard('today', opts.provider, opts.refresh, opts.project, opts.exclude)\n })\n\nprogram\n .command('month')\n .description('This month\\'s usage dashboard')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .option('--format <format>', 'Output format: tui, json', 'tui')\n .option('--project <name>', 'Show only projects matching name (repeatable)', collect, [])\n .option('--exclude <name>', 'Exclude projects matching name (repeatable)', collect, [])\n .option('--refresh <seconds>', 'Auto-refresh interval in seconds (0 to disable)', parseInt, 30)\n .action(async (opts) => {\n if (opts.format === 'json') {\n await runJsonReport('month', opts.provider, opts.project, opts.exclude)\n return\n }\n await renderDashboard('month', opts.provider, opts.refresh, opts.project, opts.exclude)\n })\n\nprogram\n .command('export')\n .description('Export usage data to CSV or JSON (includes 1 day, 7 days, 30 days)')\n .option('-f, --format <format>', 'Export format: csv, json', 'csv')\n .option('-o, --output <path>', 'Output file path')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .option('--project <name>', 'Show only projects matching name (repeatable)', collect, [])\n .option('--exclude <name>', 'Exclude projects matching name (repeatable)', collect, [])\n .action(async (opts) => {\n await loadPricing()\n const pf = opts.provider\n const fp = (p: ProjectSummary[]) => filterProjectsByName(p, opts.project, opts.exclude)\n const periods: PeriodExport[] = [\n { label: 'Today', projects: fp(await parseAllSessions(getDateRange('today').range, pf)) },\n { label: '7 Days', projects: fp(await parseAllSessions(getDateRange('week').range, pf)) },\n { label: '30 Days', projects: fp(await parseAllSessions(getDateRange('30days').range, pf)) },\n ]\n\n if (periods.every(p => p.projects.length === 0)) {\n console.log('\\n No usage data found.\\n')\n return\n }\n\n const defaultName = `exe-watcher-${toDateString(new Date())}`\n const outputPath = opts.output ?? `${defaultName}.${opts.format}`\n\n let savedPath: string\n try {\n if (opts.format === 'json') {\n savedPath = await exportJson(periods, outputPath)\n } else {\n savedPath = await exportCsv(periods, outputPath)\n }\n } catch (err) {\n // Protection guards in export.ts (symlink refusal, non-exe-watcher folder refusal, etc.)\n // throw with a user-readable message. Print just the message, not the stack, so the CLI\n // doesn't spray its internals at the user.\n const message = err instanceof Error ? err.message : String(err)\n console.error(`\\n Export failed: ${message}\\n`)\n process.exit(1)\n }\n\n console.log(`\\n Exported (Today + 7 Days + 30 Days) to: ${savedPath}\\n`)\n })\n\nprogram\n .command('menubar')\n .description('Install and launch the macOS menubar app (one command, no clone)')\n .option('--force', 'Reinstall even if an older copy is already in ~/Applications')\n .action(async (opts: { force?: boolean }) => {\n try {\n const result = await installMenubarApp({ force: opts.force })\n console.log(`\\n Ready. ${result.installedPath}\\n`)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`\\n Menubar install failed: ${message}\\n`)\n process.exit(1)\n }\n })\n\nprogram\n .command('currency [code]')\n .description('Set display currency (e.g. exe-watcher currency GBP)')\n .option('--symbol <symbol>', 'Override the currency symbol')\n .option('--reset', 'Reset to USD (removes currency config)')\n .action(async (code?: string, opts?: { symbol?: string; reset?: boolean }) => {\n if (opts?.reset) {\n const config = await readConfig()\n delete config.currency\n await saveConfig(config)\n console.log('\\n Currency reset to USD.\\n')\n return\n }\n\n if (!code) {\n const { code: activeCode, rate, symbol } = getCurrency()\n if (activeCode === 'USD' && rate === 1) {\n console.log('\\n Currency: USD (default)')\n console.log(` Config: ${getConfigFilePath()}\\n`)\n } else {\n console.log(`\\n Currency: ${activeCode}`)\n console.log(` Symbol: ${symbol}`)\n console.log(` Rate: 1 USD = ${rate} ${activeCode}`)\n console.log(` Config: ${getConfigFilePath()}\\n`)\n }\n return\n }\n\n const upperCode = code.toUpperCase()\n if (!isValidCurrencyCode(upperCode)) {\n console.error(`\\n \"${code}\" is not a valid ISO 4217 currency code.\\n`)\n process.exitCode = 1\n return\n }\n\n const config = await readConfig()\n config.currency = {\n code: upperCode,\n ...(opts?.symbol ? { symbol: opts.symbol } : {}),\n }\n await saveConfig(config)\n\n await loadCurrency()\n const { rate, symbol } = getCurrency()\n\n console.log(`\\n Currency set to ${upperCode}.`)\n console.log(` Symbol: ${symbol}`)\n console.log(` Rate: 1 USD = ${rate} ${upperCode}`)\n console.log(` Config saved to ${getConfigFilePath()}\\n`)\n })\n\nprogram\n .command('model-alias [from] [to]')\n .description('Map a provider model name to a canonical one for pricing (e.g. exe-watcher model-alias my-model claude-opus-4-6)')\n .option('--remove <from>', 'Remove an alias')\n .option('--list', 'List configured aliases')\n .action(async (from?: string, to?: string, opts?: { remove?: string; list?: boolean }) => {\n const config = await readConfig()\n const aliases = config.modelAliases ?? {}\n\n if (opts?.list || (!from && !opts?.remove)) {\n const entries = Object.entries(aliases)\n if (entries.length === 0) {\n console.log('\\n No model aliases configured.')\n console.log(` Config: ${getConfigFilePath()}\\n`)\n } else {\n console.log('\\n Model aliases:')\n for (const [src, dst] of entries) {\n console.log(` ${src} -> ${dst}`)\n }\n console.log(` Config: ${getConfigFilePath()}\\n`)\n }\n return\n }\n\n if (opts?.remove) {\n if (!(opts.remove in aliases)) {\n console.error(`\\n Alias not found: ${opts.remove}\\n`)\n process.exitCode = 1\n return\n }\n delete aliases[opts.remove]\n config.modelAliases = Object.keys(aliases).length > 0 ? aliases : undefined\n await saveConfig(config)\n console.log(`\\n Removed alias: ${opts.remove}\\n`)\n return\n }\n\n if (!from || !to) {\n console.error('\\n Usage: exe-watcher model-alias <from> <to>\\n')\n process.exitCode = 1\n return\n }\n\n aliases[from] = to\n config.modelAliases = aliases\n await saveConfig(config)\n console.log(`\\n Alias saved: ${from} -> ${to}`)\n console.log(` Config: ${getConfigFilePath()}\\n`)\n })\n\nprogram\n .command('plan [action] [id]')\n .description('Show or configure a subscription plan for overage tracking')\n .option('--format <format>', 'Output format: text or json', 'text')\n .option('--monthly-usd <n>', 'Monthly plan price in USD (for custom)', parseNumber)\n .option('--provider <name>', 'Provider scope: all, claude, codex, cursor', 'all')\n .option('--reset-day <n>', 'Day of month plan resets (1-28)', parseInteger, 1)\n .action(async (action?: string, id?: string, opts?: { format?: string; monthlyUsd?: number; provider?: string; resetDay?: number }) => {\n const mode = action ?? 'show'\n\n if (mode === 'show') {\n const plan = await readPlan()\n const displayPlan = !plan || plan.id === 'none'\n ? { id: 'none', monthlyUsd: 0, provider: 'all', resetDay: 1, setAt: null }\n : {\n id: plan.id,\n monthlyUsd: plan.monthlyUsd,\n provider: plan.provider,\n resetDay: clampResetDay(plan.resetDay),\n setAt: plan.setAt,\n }\n if (opts?.format === 'json') {\n console.log(JSON.stringify(displayPlan))\n return\n }\n if (!plan || plan.id === 'none') {\n console.log('\\n Plan: none')\n console.log(' API-pricing view is active.')\n console.log(` Config: ${getConfigFilePath()}\\n`)\n return\n }\n console.log(`\\n Plan: ${planDisplayName(plan.id)} (${plan.id})`)\n console.log(` Budget: $${plan.monthlyUsd}/month`)\n console.log(` Provider: ${plan.provider}`)\n console.log(` Reset day: ${clampResetDay(plan.resetDay)}`)\n console.log(` Set at: ${plan.setAt}`)\n console.log(` Config: ${getConfigFilePath()}\\n`)\n return\n }\n\n if (mode === 'reset') {\n await clearPlan()\n console.log('\\n Plan reset. API-pricing view is active.\\n')\n return\n }\n\n if (mode !== 'set') {\n console.error('\\n Usage: exe-watcher plan [set <id> | reset]\\n')\n process.exitCode = 1\n return\n }\n\n if (!id || !isPlanId(id)) {\n console.error(`\\n Plan id must be one of: claude-pro, claude-max, cursor-pro, custom, none; got \"${id ?? ''}\".\\n`)\n process.exitCode = 1\n return\n }\n\n const resetDay = opts?.resetDay ?? 1\n if (!Number.isInteger(resetDay) || resetDay < 1 || resetDay > 28) {\n console.error(`\\n --reset-day must be an integer from 1 to 28; got ${resetDay}.\\n`)\n process.exitCode = 1\n return\n }\n\n if (id === 'none') {\n await clearPlan()\n console.log('\\n Plan reset. API-pricing view is active.\\n')\n return\n }\n\n if (id === 'custom') {\n if (opts?.monthlyUsd === undefined) {\n console.error('\\n Custom plans require --monthly-usd <positive number>.\\n')\n process.exitCode = 1\n return\n }\n const monthlyUsd = opts.monthlyUsd\n if (!Number.isFinite(monthlyUsd) || monthlyUsd <= 0) {\n console.error(`\\n --monthly-usd must be a positive number; got ${opts.monthlyUsd}.\\n`)\n process.exitCode = 1\n return\n }\n const provider = opts?.provider ?? 'all'\n if (!isPlanProvider(provider)) {\n console.error(`\\n --provider must be one of: all, claude, codex, cursor; got \"${provider}\".\\n`)\n process.exitCode = 1\n return\n }\n await savePlan({\n id: 'custom',\n monthlyUsd,\n provider,\n resetDay,\n setAt: new Date().toISOString(),\n })\n console.log(`\\n Plan set to custom ($${monthlyUsd}/month, ${provider}, reset day ${resetDay}).`)\n console.log(` Config saved to ${getConfigFilePath()}\\n`)\n return\n }\n\n const preset = getPresetPlan(id)\n if (!preset) {\n console.error(`\\n Unknown preset \"${id}\".\\n`)\n process.exitCode = 1\n return\n }\n\n await savePlan({\n ...preset,\n resetDay,\n setAt: new Date().toISOString(),\n })\n console.log(`\\n Plan set to ${planDisplayName(preset.id)} ($${preset.monthlyUsd}/month).`)\n console.log(` Provider: ${preset.provider}`)\n console.log(` Reset day: ${resetDay}`)\n console.log(` Config saved to ${getConfigFilePath()}\\n`)\n })\n\nprogram\n .command('optimize')\n .description('Find token waste and get exact fixes')\n .option('-p, --period <period>', 'Analysis period: today, week, 30days, month, all', '30days')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .action(async (opts) => {\n await loadPricing()\n const { range, label } = getDateRange(opts.period)\n const projects = await parseAllSessions(range, opts.provider)\n await runOptimize(projects, label, range)\n })\n\nprogram\n .command('compare')\n .description('Compare two AI models side-by-side')\n .option('-p, --period <period>', 'Analysis period: today, week, 30days, month, all', 'all')\n .option('--provider <provider>', 'Filter by provider: all, claude, codex, cursor', 'all')\n .action(async (opts) => {\n await loadPricing()\n const { range } = getDateRange(opts.period)\n await renderCompare(range, opts.provider)\n })\n\nprogram\n .command('agent-status')\n .description('Diagnose exe-os agent data pipeline')\n .action(() => {\n const exeOsDir = join(homedir(), '.exe-os')\n const statsPath = join(exeOsDir, 'agent-stats.json')\n const pidPath = join(exeOsDir, 'exed.pid')\n\n const dirExists = existsSync(exeOsDir)\n const statsExists = dirExists && existsSync(statsPath)\n const pidExists = dirExists && existsSync(pidPath)\n\n const lines: string[] = []\n lines.push(`exe-os directory: ${dirExists ? '✓ found' : '✗ not found'} (${exeOsDir})`)\n lines.push(`daemon pid file: ${pidExists ? '✓ found' : '✗ not found'}`)\n\n if (!statsExists) {\n lines.push(`agent-stats.json: ✗ not found`)\n } else {\n try {\n const ageSeconds = Math.round((Date.now() - statSync(statsPath).mtimeMs) / 1000)\n const raw = readFileSync(statsPath, 'utf-8')\n const parsed = JSON.parse(raw)\n if (parsed && Array.isArray(parsed.agents) && typeof parsed.generated === 'string') {\n const agentCount = parsed.agents.length\n const stale = ageSeconds > 300 ? ' ⚠️ STALE' : ''\n lines.push(`agent-stats.json: ✓ valid (${agentCount} agent${agentCount !== 1 ? 's' : ''}, ${ageSeconds}s old${stale})`)\n for (const a of parsed.agents) {\n lines.push(` • ${a.id}: ${a.total} memories`)\n }\n } else {\n lines.push(`agent-stats.json: ✗ invalid schema`)\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err)\n lines.push(`agent-stats.json: ✗ parse error: ${msg}`)\n }\n }\n\n console.log(lines.join('\\n'))\n })\n\n// Default action: install menubar app on macOS when no subcommand given\nif (process.argv.length <= 2 && process.platform === 'darwin') {\n installMenubarApp().then(result => {\n console.log(`\\n Installed: ${result.installedPath}`)\n if (result.launched) console.log(' Launched.')\n }).catch(err => {\n console.error(`\\n ${err instanceof Error ? err.message : String(err)}`)\n process.exitCode = 1\n })\n} else {\n program.parse()\n}\n","import { spawn } from 'node:child_process'\nimport { createWriteStream } from 'node:fs'\nimport { cp, mkdir, mkdtemp, rename, rm, stat } from 'node:fs/promises'\nimport { homedir, platform, tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { pipeline } from 'node:stream/promises'\nimport { Readable } from 'node:stream'\n\n/// Public GitHub repo that hosts signed macOS release builds. `/releases/latest` returns the\n/// newest tagged release; we filter its assets list for our zipped .app bundle.\nconst RELEASE_API = 'https://api.github.com/repos/AskExe/exe-watcher/releases/latest'\nconst APP_BUNDLE_NAME = 'Watcher by EXE.app'\nconst ASSET_PATTERN = /^ExeWatcherMenubar-.*\\.zip$/\nconst APP_PROCESS_NAME = 'ExeWatcherMenubar'\nconst SUPPORTED_OS = 'darwin'\nconst MIN_MACOS_MAJOR = 14\n\nexport type InstallResult = { installedPath: string; launched: boolean }\n\ntype ReleaseAsset = { name: string; browser_download_url: string }\ntype ReleaseResponse = { tag_name: string; assets: ReleaseAsset[] }\n\nfunction userApplicationsDir(): string {\n return join(homedir(), 'Applications')\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path)\n return true\n } catch {\n return false\n }\n}\n\nasync function ensureSupportedPlatform(): Promise<void> {\n if (platform() !== SUPPORTED_OS) {\n throw new Error(`The menubar app is macOS only (detected: ${platform()}).`)\n }\n const major = Number((process.env.EXE_WATCHER_FORCE_MACOS_MAJOR ?? '')\n || (await sysProductVersion()).split('.')[0])\n if (!Number.isFinite(major) || major < MIN_MACOS_MAJOR) {\n throw new Error(`macOS ${MIN_MACOS_MAJOR}+ required (detected ${major}).`)\n }\n}\n\nasync function sysProductVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn('/usr/bin/sw_vers', ['-productVersion'])\n let out = ''\n proc.stdout.on('data', (chunk: Buffer) => { out += chunk.toString() })\n proc.on('error', reject)\n proc.on('close', (code) => {\n if (code !== 0) reject(new Error(`sw_vers exited with ${code}`))\n else resolve(out.trim())\n })\n })\n}\n\nasync function fetchLatestReleaseAsset(): Promise<ReleaseAsset> {\n const response = await fetch(RELEASE_API, {\n headers: {\n // Identify the installer so GitHub's abuse heuristics treat us as a known client.\n 'User-Agent': 'exe-watcher-installer',\n Accept: 'application/vnd.github+json',\n },\n })\n if (!response.ok) {\n throw new Error(`GitHub release lookup failed: HTTP ${response.status}`)\n }\n const body = await response.json() as ReleaseResponse\n const asset = body.assets.find(a => ASSET_PATTERN.test(a.name))\n if (!asset) {\n throw new Error(\n `No ${APP_BUNDLE_NAME} zip found in release ${body.tag_name}. ` +\n `Check https://github.com/AskExe/exe-watcher/releases.`\n )\n }\n return asset\n}\n\nasync function downloadToFile(url: string, destPath: string): Promise<void> {\n const response = await fetch(url, {\n headers: { 'User-Agent': 'exe-watcher-installer' },\n redirect: 'follow',\n })\n if (!response.ok || response.body === null) {\n throw new Error(`Download failed: HTTP ${response.status}`)\n }\n // fetch's ReadableStream needs to be wrapped for Node streams.\n const nodeStream = Readable.fromWeb(response.body as never)\n await pipeline(nodeStream, createWriteStream(destPath))\n}\n\nasync function runCommand(command: string, args: string[]): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, { stdio: 'inherit' })\n proc.on('error', reject)\n proc.on('close', (code) => {\n if (code === 0) resolve()\n else reject(new Error(`${command} exited with status ${code}`))\n })\n })\n}\n\nasync function isAppRunning(): Promise<boolean> {\n return new Promise((resolve) => {\n const proc = spawn('/usr/bin/pgrep', ['-f', APP_PROCESS_NAME])\n proc.on('close', (code) => resolve(code === 0))\n proc.on('error', () => resolve(false))\n })\n}\n\nasync function killRunningApp(): Promise<void> {\n await new Promise<void>((resolve) => {\n const proc = spawn('/usr/bin/pkill', ['-f', APP_PROCESS_NAME])\n proc.on('close', () => resolve())\n proc.on('error', () => resolve())\n })\n}\n\nexport async function installMenubarApp(options: { force?: boolean } = {}): Promise<InstallResult> {\n await ensureSupportedPlatform()\n\n const appsDir = userApplicationsDir()\n const targetPath = join(appsDir, APP_BUNDLE_NAME)\n const alreadyInstalled = await exists(targetPath)\n\n if (alreadyInstalled && !options.force) {\n if (!(await isAppRunning())) {\n await runCommand('/usr/bin/open', [targetPath])\n }\n return { installedPath: targetPath, launched: true }\n }\n\n console.log('Looking up the latest Exe Watcher Menubar release...')\n const asset = await fetchLatestReleaseAsset()\n\n const stagingDir = await mkdtemp(join(tmpdir(), 'exe-watcher-menubar-'))\n try {\n const archivePath = join(stagingDir, asset.name)\n console.log(`Downloading ${asset.name}...`)\n await downloadToFile(asset.browser_download_url, archivePath)\n\n console.log('Unpacking...')\n await runCommand('/usr/bin/unzip', ['-q', archivePath, '-d', stagingDir])\n\n const unpackedApp = join(stagingDir, APP_BUNDLE_NAME)\n if (!(await exists(unpackedApp))) {\n throw new Error(`Archive did not contain ${APP_BUNDLE_NAME}.`)\n }\n\n // Clear Gatekeeper's quarantine xattr. Without this, the first launch shows the\n // \"cannot verify developer\" prompt even for a signed + notarized app when the bundle\n // was delivered via curl/fetch instead of the Mac App Store.\n await runCommand('/usr/bin/xattr', ['-dr', 'com.apple.quarantine', unpackedApp]).catch(() => {})\n\n await mkdir(appsDir, { recursive: true })\n if (alreadyInstalled) {\n // Kill the running copy before replacing its bundle so `mv` can proceed cleanly and the\n // user ends up on the new version.\n await killRunningApp()\n await rm(targetPath, { recursive: true, force: true })\n }\n try {\n await rename(unpackedApp, targetPath)\n } catch (err) {\n // EXDEV: rename fails across filesystem boundaries (e.g. $TMPDIR on a\n // different APFS volume than ~/Applications). Fall back to copy + delete.\n if ((err as NodeJS.ErrnoException).code === 'EXDEV') {\n await cp(unpackedApp, targetPath, { recursive: true })\n await rm(unpackedApp, { recursive: true, force: true })\n } else {\n throw err\n }\n }\n\n console.log('Launching Exe Watcher Menubar...')\n await runCommand('/usr/bin/open', [targetPath])\n return { installedPath: targetPath, launched: true }\n } finally {\n await rm(stagingDir, { recursive: true, force: true })\n }\n}\n","import { writeFile, mkdir, readdir, stat, rm } from 'fs/promises'\nimport { dirname, join, resolve } from 'path'\n\nimport { CATEGORY_LABELS, type ProjectSummary, type TaskCategory } from './types.js'\nimport { getCurrency, convertCost } from './currency.js'\nimport { dateKey } from './day-aggregator.js'\n\nfunction escCsv(s: string): string {\n const sanitized = /^[\\t\\r=+\\-@]/.test(s) ? `'${s}` : s\n if (sanitized.includes(',') || sanitized.includes('\"') || sanitized.includes('\\n')) {\n return `\"${sanitized.replace(/\"/g, '\"\"')}\"`\n }\n return sanitized\n}\n\ntype Row = Record<string, string | number>\n\nfunction rowsToCsv(rows: Row[]): string {\n if (rows.length === 0) return ''\n const headers = Object.keys(rows[0])\n const lines = [headers.map(escCsv).join(',')]\n for (const row of rows) {\n lines.push(headers.map(h => escCsv(String(row[h] ?? ''))).join(','))\n }\n return lines.join('\\n') + '\\n'\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100\n}\n\nfunction pct(n: number, total: number): number {\n return total > 0 ? round2((n / total) * 100) : 0\n}\n\ntype DailyAgg = {\n cost: number\n calls: number\n input: number\n output: number\n cacheRead: number\n cacheWrite: number\n sessions: Set<string>\n}\n\nfunction buildDailyRows(projects: ProjectSummary[], period: string): Row[] {\n const daily: Record<string, DailyAgg> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (!turn.timestamp) continue\n const day = dateKey(turn.timestamp)\n if (!daily[day]) {\n daily[day] = { cost: 0, calls: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, sessions: new Set() }\n }\n daily[day].sessions.add(session.sessionId)\n for (const call of turn.assistantCalls) {\n daily[day].cost += call.costUSD\n daily[day].calls++\n daily[day].input += call.usage.inputTokens\n daily[day].output += call.usage.outputTokens\n daily[day].cacheRead += call.usage.cacheReadInputTokens\n daily[day].cacheWrite += call.usage.cacheCreationInputTokens\n }\n }\n }\n }\n const { code } = getCurrency()\n return Object.entries(daily).sort().map(([date, d]) => ({\n Period: period,\n Date: date,\n [`Cost (${code})`]: round2(convertCost(d.cost)),\n 'API Calls': d.calls,\n Sessions: d.sessions.size,\n 'Input Tokens': d.input,\n 'Output Tokens': d.output,\n 'Cache Read Tokens': d.cacheRead,\n 'Cache Write Tokens': d.cacheWrite,\n }))\n}\n\nfunction buildActivityRows(projects: ProjectSummary[], period: string): Row[] {\n const catTotals: Record<string, { turns: number; cost: number }> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [cat, d] of Object.entries(session.categoryBreakdown)) {\n if (!catTotals[cat]) catTotals[cat] = { turns: 0, cost: 0 }\n catTotals[cat].turns += d.turns\n catTotals[cat].cost += d.costUSD\n }\n }\n }\n const totalCost = Object.values(catTotals).reduce((s, d) => s + d.cost, 0)\n const { code } = getCurrency()\n return Object.entries(catTotals)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([cat, d]) => ({\n Period: period,\n Activity: CATEGORY_LABELS[cat as TaskCategory] ?? cat,\n [`Cost (${code})`]: round2(convertCost(d.cost)),\n 'Share (%)': pct(d.cost, totalCost),\n Turns: d.turns,\n }))\n}\n\nfunction buildModelRows(projects: ProjectSummary[], period: string): Row[] {\n const modelTotals: Record<string, { calls: number; cost: number; input: number; output: number; cacheRead: number; cacheWrite: number }> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [model, d] of Object.entries(session.modelBreakdown)) {\n if (!modelTotals[model]) modelTotals[model] = { calls: 0, cost: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }\n modelTotals[model].calls += d.calls\n modelTotals[model].cost += d.costUSD\n modelTotals[model].input += d.tokens.inputTokens\n modelTotals[model].output += d.tokens.outputTokens\n modelTotals[model].cacheRead += d.tokens.cacheReadInputTokens ?? 0\n modelTotals[model].cacheWrite += d.tokens.cacheCreationInputTokens ?? 0\n }\n }\n }\n const totalCost = Object.values(modelTotals).reduce((s, d) => s + d.cost, 0)\n const { code } = getCurrency()\n return Object.entries(modelTotals)\n .filter(([name]) => name !== '<synthetic>')\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([model, d]) => ({\n Period: period,\n Model: model,\n [`Cost (${code})`]: round2(convertCost(d.cost)),\n 'Share (%)': pct(d.cost, totalCost),\n 'API Calls': d.calls,\n 'Input Tokens': d.input,\n 'Output Tokens': d.output,\n 'Cache Read Tokens': d.cacheRead,\n 'Cache Write Tokens': d.cacheWrite,\n }))\n}\n\nfunction buildToolRows(projects: ProjectSummary[]): Row[] {\n const toolTotals: Record<string, number> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [tool, d] of Object.entries(session.toolBreakdown)) {\n toolTotals[tool] = (toolTotals[tool] ?? 0) + d.calls\n }\n }\n }\n const total = Object.values(toolTotals).reduce((s, n) => s + n, 0)\n return Object.entries(toolTotals)\n .sort(([, a], [, b]) => b - a)\n .map(([tool, calls]) => ({\n Tool: tool,\n Calls: calls,\n 'Share (%)': pct(calls, total),\n }))\n}\n\nfunction buildBashRows(projects: ProjectSummary[]): Row[] {\n const bashTotals: Record<string, number> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [cmd, d] of Object.entries(session.bashBreakdown)) {\n bashTotals[cmd] = (bashTotals[cmd] ?? 0) + d.calls\n }\n }\n }\n const total = Object.values(bashTotals).reduce((s, n) => s + n, 0)\n return Object.entries(bashTotals)\n .sort(([, a], [, b]) => b - a)\n .map(([cmd, calls]) => ({\n Command: cmd,\n Calls: calls,\n 'Share (%)': pct(calls, total),\n }))\n}\n\nfunction buildProjectRows(projects: ProjectSummary[]): Row[] {\n const { code } = getCurrency()\n const total = projects.reduce((s, p) => s + p.totalCostUSD, 0)\n return projects\n .slice()\n .sort((a, b) => b.totalCostUSD - a.totalCostUSD)\n .map(p => ({\n Project: p.projectPath,\n [`Cost (${code})`]: round2(convertCost(p.totalCostUSD)),\n [`Avg/Session (${code})`]: p.sessions.length > 0 ? round2(convertCost(p.totalCostUSD / p.sessions.length)) : '',\n 'Share (%)': pct(p.totalCostUSD, total),\n 'API Calls': p.totalApiCalls,\n Sessions: p.sessions.length,\n }))\n}\n\nfunction buildSessionRows(projects: ProjectSummary[]): Row[] {\n const { code } = getCurrency()\n const rows: Row[] = []\n for (const p of projects) {\n for (const s of p.sessions) {\n rows.push({\n Project: p.projectPath,\n 'Session ID': s.sessionId,\n 'Started At': s.firstTimestamp ?? '',\n [`Cost (${code})`]: round2(convertCost(s.totalCostUSD)),\n 'API Calls': s.apiCalls,\n Turns: s.turns.length,\n })\n }\n }\n return rows.sort((a, b) => (b[`Cost (${code})`] as number) - (a[`Cost (${code})`] as number))\n}\n\nexport type PeriodExport = {\n label: string\n projects: ProjectSummary[]\n}\n\nfunction buildSummaryRows(periods: PeriodExport[]): Row[] {\n const { code } = getCurrency()\n return periods.map(p => {\n const cost = p.projects.reduce((s, proj) => s + proj.totalCostUSD, 0)\n const calls = p.projects.reduce((s, proj) => s + proj.totalApiCalls, 0)\n const sessions = p.projects.reduce((s, proj) => s + proj.sessions.length, 0)\n const projectCount = p.projects.filter(proj => proj.totalCostUSD > 0).length\n return {\n Period: p.label,\n [`Cost (${code})`]: round2(convertCost(cost)),\n 'API Calls': calls,\n Sessions: sessions,\n Projects: projectCount,\n }\n })\n}\n\nfunction buildReadme(periods: PeriodExport[]): string {\n const { code } = getCurrency()\n const generated = new Date().toISOString()\n const lines = [\n 'Exe Watcher Usage Export',\n '====================',\n '',\n `Generated: ${generated}`,\n `Currency: ${code}`,\n `Periods: ${periods.map(p => p.label).join(', ')}`,\n '',\n 'Files',\n '-----',\n ' summary.csv One row per period. Headline totals.',\n ' daily.csv Day-by-day breakdown, Period column distinguishes the window.',\n ' activity.csv Time spent per task category (Coding, Debugging, Exploration, etc.).',\n ' models.csv Spend per model with token totals and cache usage.',\n ' projects.csv Spend per project folder (30-day window).',\n ' sessions.csv One row per session (30-day window) with session IDs and costs.',\n ' tools.csv Tool invocations and share (30-day window).',\n ' shell-commands.csv Shell commands executed via Bash tool (30-day window).',\n '',\n 'Notes',\n '-----',\n ' Every cost column is already converted to the active currency. Tokens are raw integer',\n ' counts from provider telemetry. Share (%) is relative to the period/table total.',\n '',\n ]\n return lines.join('\\n')\n}\n\n/// Sentinel file dropped into every folder we create so we can safely overwrite an older\n/// exe-watcher export without ever deleting a user's unrelated files by accident.\nconst EXPORT_MARKER_FILE = '.exe-watcher-export'\n\nasync function isExeWatcherExportFolder(path: string): Promise<boolean> {\n const markerStat = await stat(join(path, EXPORT_MARKER_FILE)).catch(() => null)\n return markerStat?.isFile() ?? false\n}\n\nasync function clearExeWatcherExportFolder(path: string): Promise<void> {\n const entries = await readdir(path)\n for (const entry of entries) {\n await rm(join(path, entry), { recursive: true, force: true })\n }\n}\n\n/// Writes a folder of one-table-per-file CSVs. The outputPath is treated as a directory. If it\n/// ends in `.csv` the extension is stripped to form the folder name. Refuses to delete a\n/// pre-existing file or a non-exe-watcher folder, so a typo like `-o ~/.ssh/id_ed25519` can't\n/// wipe a sensitive file (prior versions did `rm(path, { force: true })` unconditionally).\nexport async function exportCsv(periods: PeriodExport[], outputPath: string): Promise<string> {\n const thirtyDays = periods.find(p => p.label === '30 Days')\n const thirtyDayProjects = thirtyDays?.projects ?? periods[periods.length - 1]?.projects ?? []\n\n let folder = resolve(outputPath)\n if (folder.toLowerCase().endsWith('.csv')) {\n folder = folder.slice(0, -4)\n }\n\n const existingStat = await stat(folder).catch(() => null)\n if (existingStat?.isFile()) {\n throw new Error(`Refusing to overwrite existing file at ${folder}. Pass a directory path instead.`)\n }\n if (existingStat?.isDirectory()) {\n if (!(await isExeWatcherExportFolder(folder))) {\n throw new Error(\n `Refusing to reuse non-empty directory ${folder}: no ${EXPORT_MARKER_FILE} marker. ` +\n `Delete it manually or pick a different -o path.`\n )\n }\n await clearExeWatcherExportFolder(folder)\n }\n await mkdir(folder, { recursive: true })\n await writeFile(join(folder, EXPORT_MARKER_FILE), '', 'utf-8')\n\n const dailyRows = periods.flatMap(p => buildDailyRows(p.projects, p.label))\n const activityRows = periods.flatMap(p => buildActivityRows(p.projects, p.label))\n const modelRows = periods.flatMap(p => buildModelRows(p.projects, p.label))\n\n await writeFile(join(folder, 'README.txt'), buildReadme(periods), 'utf-8')\n await writeFile(join(folder, 'summary.csv'), rowsToCsv(buildSummaryRows(periods)), 'utf-8')\n await writeFile(join(folder, 'daily.csv'), rowsToCsv(dailyRows), 'utf-8')\n await writeFile(join(folder, 'activity.csv'), rowsToCsv(activityRows), 'utf-8')\n await writeFile(join(folder, 'models.csv'), rowsToCsv(modelRows), 'utf-8')\n await writeFile(join(folder, 'projects.csv'), rowsToCsv(buildProjectRows(thirtyDayProjects)), 'utf-8')\n await writeFile(join(folder, 'sessions.csv'), rowsToCsv(buildSessionRows(thirtyDayProjects)), 'utf-8')\n await writeFile(join(folder, 'tools.csv'), rowsToCsv(buildToolRows(thirtyDayProjects)), 'utf-8')\n await writeFile(join(folder, 'shell-commands.csv'), rowsToCsv(buildBashRows(thirtyDayProjects)), 'utf-8')\n\n return folder\n}\n\nexport async function exportJson(periods: PeriodExport[], outputPath: string): Promise<string> {\n const thirtyDays = periods.find(p => p.label === '30 Days')\n const thirtyDayProjects = thirtyDays?.projects ?? periods[periods.length - 1]?.projects ?? []\n const { code, rate, symbol } = getCurrency()\n\n const data = {\n schema: 'exe-watcher.export.v2',\n generated: new Date().toISOString(),\n currency: { code, rate, symbol },\n summary: buildSummaryRows(periods),\n periods: periods.map(p => ({\n label: p.label,\n daily: buildDailyRows(p.projects, p.label),\n activity: buildActivityRows(p.projects, p.label),\n models: buildModelRows(p.projects, p.label),\n })),\n projects: buildProjectRows(thirtyDayProjects),\n sessions: buildSessionRows(thirtyDayProjects),\n tools: buildToolRows(thirtyDayProjects),\n shellCommands: buildBashRows(thirtyDayProjects),\n }\n\n const target = resolve(outputPath.toLowerCase().endsWith('.json') ? outputPath : `${outputPath}.json`)\n await mkdir(dirname(target), { recursive: true })\n await writeFile(target, JSON.stringify(data, null, 2), 'utf-8')\n return target\n}\n","export type TokenUsage = {\n inputTokens: number\n outputTokens: number\n cacheCreationInputTokens: number\n cacheReadInputTokens: number\n cachedInputTokens: number\n reasoningTokens: number\n webSearchRequests: number\n}\n\nexport type ToolUseBlock = {\n type: 'tool_use'\n id: string\n name: string\n input: Record<string, unknown>\n}\n\nexport type ContentBlock =\n | { type: 'text'; text: string }\n | { type: 'thinking'; thinking: string }\n | ToolUseBlock\n | { type: string; [key: string]: unknown }\n\nexport type ApiUsage = {\n input_tokens: number\n output_tokens: number\n cache_creation_input_tokens?: number\n cache_read_input_tokens?: number\n server_tool_use?: {\n web_search_requests?: number\n web_fetch_requests?: number\n }\n speed?: 'standard' | 'fast'\n}\n\nexport type AssistantMessageContent = {\n model: string\n id?: string\n type: 'message'\n role: 'assistant'\n content: ContentBlock[]\n usage: ApiUsage\n stop_reason?: string\n}\n\nexport type JournalEntry = {\n type: string\n uuid?: string\n parentUuid?: string | null\n timestamp?: string\n sessionId?: string\n cwd?: string\n version?: string\n gitBranch?: string\n promptId?: string\n message?: AssistantMessageContent | { role: 'user'; content: string | ContentBlock[] }\n isSidechain?: boolean\n [key: string]: unknown\n}\n\nexport type ParsedTurn = {\n userMessage: string\n assistantCalls: ParsedApiCall[]\n timestamp: string\n sessionId: string\n}\n\nexport type ParsedApiCall = {\n provider: string\n model: string\n usage: TokenUsage\n costUSD: number\n tools: string[]\n mcpTools: string[]\n hasAgentSpawn: boolean\n hasPlanMode: boolean\n speed: 'standard' | 'fast'\n timestamp: string\n bashCommands: string[]\n deduplicationKey: string\n}\n\nexport type TaskCategory =\n | 'building'\n | 'debugging'\n | 'testing'\n | 'research'\n | 'devops'\n | 'planning'\n\nexport type ClassifiedTurn = ParsedTurn & {\n category: TaskCategory\n retries: number\n hasEdits: boolean\n}\n\nexport type SessionSummary = {\n sessionId: string\n project: string\n firstTimestamp: string\n lastTimestamp: string\n totalCostUSD: number\n totalInputTokens: number\n totalOutputTokens: number\n totalCacheReadTokens: number\n totalCacheWriteTokens: number\n apiCalls: number\n turns: ClassifiedTurn[]\n modelBreakdown: Record<string, { calls: number; costUSD: number; tokens: TokenUsage }>\n toolBreakdown: Record<string, { calls: number }>\n mcpBreakdown: Record<string, { calls: number }>\n bashBreakdown: Record<string, { calls: number }>\n categoryBreakdown: Record<TaskCategory, { turns: number; costUSD: number; retries: number; editTurns: number; oneShotTurns: number }>\n}\n\nexport type ProjectSummary = {\n project: string\n projectPath: string\n sessions: SessionSummary[]\n totalCostUSD: number\n totalApiCalls: number\n}\n\nexport type DateRange = {\n start: Date\n end: Date\n}\n\nexport const CATEGORY_LABELS: Record<TaskCategory, string> = {\n building: 'Building',\n debugging: 'Debugging',\n testing: 'Testing',\n research: 'Research',\n devops: 'DevOps',\n planning: 'Planning',\n}\n","import { readFile, mkdir, rename, unlink } from 'fs/promises'\nimport { open } from 'fs/promises'\nimport { join } from 'path'\nimport { randomBytes } from 'crypto'\n\nimport { getCacheDir } from './cache-dir.js'\nimport { readConfig } from './config.js'\n\ntype CurrencyState = {\n code: string\n rate: number\n symbol: string\n}\n\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000\nconst FRANKFURTER_URL = 'https://api.frankfurter.app/latest?from=USD&to='\n// Defensive bounds on any fetched FX rate. Outside this band the rate is either a parser bug\n// or a tampered Frankfurter response, and we refuse to multiply it into displayed costs.\nconst MIN_VALID_FX_RATE = 0.0001\nconst MAX_VALID_FX_RATE = 1_000_000\n\nfunction isValidRate(value: unknown): value is number {\n return typeof value === 'number'\n && Number.isFinite(value)\n && value >= MIN_VALID_FX_RATE\n && value <= MAX_VALID_FX_RATE\n}\n\nlet active: CurrencyState = { code: 'USD', rate: 1, symbol: '$' }\n\nconst USD: CurrencyState = { code: 'USD', rate: 1, symbol: '$' }\n\n// Intl.NumberFormat throws on invalid ISO 4217 codes, so we use it as a validator\nexport function isValidCurrencyCode(code: string): boolean {\n try {\n new Intl.NumberFormat('en', { style: 'currency', currency: code })\n return true\n } catch {\n return false\n }\n}\n\nfunction resolveSymbol(code: string): string {\n const parts = new Intl.NumberFormat('en', {\n style: 'currency',\n currency: code,\n currencyDisplay: 'symbol',\n }).formatToParts(0)\n return parts.find(p => p.type === 'currency')?.value ?? code\n}\n\nfunction getFractionDigits(code: string): number {\n return new Intl.NumberFormat('en', {\n style: 'currency',\n currency: code,\n }).resolvedOptions().maximumFractionDigits ?? 2\n}\n\nfunction getRateCachePath(): string {\n return join(getCacheDir(), 'exchange-rate.json')\n}\n\nasync function fetchRate(code: string): Promise<number> {\n const response = await fetch(`${FRANKFURTER_URL}${code}`)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n const data = await response.json() as { rates?: Record<string, unknown> }\n const rate = data.rates?.[code]\n if (!isValidRate(rate)) throw new Error(`Invalid rate returned for ${code}`)\n return rate\n}\n\nasync function loadCachedRate(code: string): Promise<number | null> {\n try {\n const raw = await readFile(getRateCachePath(), 'utf-8')\n const cached = JSON.parse(raw) as Partial<{ timestamp: number; code: string; rate: number }>\n // Validate every field -- a tampered cache file could set rate to a string, null, or\n // Infinity and break downstream math silently.\n if (typeof cached.code !== 'string' || cached.code !== code) return null\n if (typeof cached.timestamp !== 'number' || !Number.isFinite(cached.timestamp)) return null\n if (Date.now() - cached.timestamp > CACHE_TTL_MS) return null\n if (!isValidRate(cached.rate)) return null\n return cached.rate\n } catch {\n return null\n }\n}\n\nasync function cacheRate(code: string, rate: number): Promise<void> {\n await mkdir(getCacheDir(), { recursive: true })\n const finalPath = getRateCachePath()\n const tmpPath = `${finalPath}.${randomBytes(8).toString('hex')}.tmp`\n const handle = await open(tmpPath, 'w', 0o600)\n try {\n await handle.writeFile(JSON.stringify({ timestamp: Date.now(), code, rate }), { encoding: 'utf-8' })\n await handle.sync()\n } finally {\n await handle.close()\n }\n try {\n await rename(tmpPath, finalPath)\n } catch (err) {\n try { await unlink(tmpPath) } catch { /* ignore */ }\n throw err\n }\n}\n\nasync function getExchangeRate(code: string): Promise<number> {\n if (code === 'USD') return 1\n\n const cached = await loadCachedRate(code)\n if (cached) return cached\n\n try {\n const rate = await fetchRate(code)\n await cacheRate(code, rate)\n return rate\n } catch {\n return 1\n }\n}\n\nexport async function loadCurrency(): Promise<void> {\n const config = await readConfig()\n if (!config.currency) return\n\n const code = config.currency.code.toUpperCase()\n const rate = await getExchangeRate(code)\n const symbol = config.currency.symbol ?? resolveSymbol(code)\n\n active = { code, rate, symbol }\n}\n\nexport function getCurrency(): CurrencyState {\n return active\n}\n\nexport async function switchCurrency(code: string): Promise<void> {\n if (code === 'USD') {\n active = USD\n return\n }\n const rate = await getExchangeRate(code)\n const symbol = resolveSymbol(code)\n active = { code, rate, symbol }\n}\n\nexport function getCostColumnHeader(): string {\n return `Cost (${active.code})`\n}\n\nexport function convertCost(costUSD: number): number {\n const digits = getFractionDigits(active.code)\n const factor = 10 ** digits\n return Math.round(costUSD * active.rate * factor) / factor\n}\n\nexport function formatCost(costUSD: number): string {\n const { rate, symbol, code } = active\n const cost = costUSD * rate\n const digits = getFractionDigits(code)\n\n if (digits === 0) return `${symbol}${Math.round(cost)}`\n\n if (cost >= 1) return `${symbol}${cost.toFixed(2)}`\n if (cost >= 0.01) return `${symbol}${cost.toFixed(3)}`\n return `${symbol}${cost.toFixed(4)}`\n}\n","import { readFile, mkdir, rename } from 'fs/promises'\nimport { open } from 'fs/promises'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { randomBytes } from 'crypto'\n\nexport type PlanId = 'claude-pro' | 'claude-max' | 'cursor-pro' | 'custom' | 'none'\nexport type PlanProvider = 'claude' | 'codex' | 'cursor' | 'all'\n\nexport type Plan = {\n id: PlanId\n monthlyUsd: number\n provider: PlanProvider\n resetDay?: number\n setAt: string\n}\n\nexport type ExeWatcherConfig = {\n currency?: {\n code: string\n symbol?: string\n }\n plan?: Plan\n modelAliases?: Record<string, string>\n}\n\nfunction getConfigDir(): string {\n const xdgConfig = process.env['XDG_CONFIG_HOME']\n return join(xdgConfig || join(homedir(), '.config'), 'exe-watcher')\n}\n\nfunction getConfigPath(): string {\n return join(getConfigDir(), 'config.json')\n}\n\nexport async function readConfig(): Promise<ExeWatcherConfig> {\n try {\n const raw = await readFile(getConfigPath(), 'utf-8')\n return JSON.parse(raw) as ExeWatcherConfig\n } catch {\n return {}\n }\n}\n\nexport async function saveConfig(config: ExeWatcherConfig): Promise<void> {\n await mkdir(getConfigDir(), { recursive: true })\n const configPath = getConfigPath()\n const tmpPath = `${configPath}.${randomBytes(8).toString('hex')}.tmp`\n const handle = await open(tmpPath, 'w', 0o600)\n try {\n await handle.writeFile(JSON.stringify(config, null, 2) + '\\n', { encoding: 'utf-8' })\n await handle.sync()\n } finally {\n await handle.close()\n }\n await rename(tmpPath, configPath)\n}\n\nexport async function readPlan(): Promise<Plan | undefined> {\n const config = await readConfig()\n return config.plan\n}\n\nexport async function savePlan(plan: Plan): Promise<void> {\n const config = await readConfig()\n config.plan = plan\n await saveConfig(config)\n}\n\nexport async function clearPlan(): Promise<void> {\n const config = await readConfig()\n delete config.plan\n await saveConfig(config)\n}\n\nexport function getConfigFilePath(): string {\n return getConfigPath()\n}\n","import type { DailyEntry } from './daily-cache.js'\nimport type { PeriodData } from './menubar-json.js'\nimport { CATEGORY_LABELS, type ProjectSummary, type TaskCategory } from './types.js'\n\nfunction emptyEntry(date: string): DailyEntry {\n return {\n date,\n cost: 0,\n calls: 0,\n sessions: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n editTurns: 0,\n oneShotTurns: 0,\n models: {},\n categories: {},\n providers: {},\n }\n}\n\nexport function dateKey(iso: string): string {\n const d = new Date(iso)\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n\nexport function aggregateProjectsIntoDays(projects: ProjectSummary[]): DailyEntry[] {\n const byDate = new Map<string, DailyEntry>()\n const ensure = (date: string): DailyEntry => {\n let d = byDate.get(date)\n if (!d) { d = emptyEntry(date); byDate.set(date, d) }\n return d\n }\n\n for (const project of projects) {\n for (const session of project.sessions) {\n const sessionDate = dateKey(session.firstTimestamp)\n ensure(sessionDate).sessions += 1\n\n for (const turn of session.turns) {\n if (turn.assistantCalls.length === 0) continue\n const turnDate = dateKey(turn.assistantCalls[0]!.timestamp)\n const turnDay = ensure(turnDate)\n\n const editTurns = turn.hasEdits ? 1 : 0\n const oneShotTurns = turn.hasEdits && turn.retries === 0 ? 1 : 0\n const turnCost = turn.assistantCalls.reduce((s, c) => s + c.costUSD, 0)\n\n turnDay.editTurns += editTurns\n turnDay.oneShotTurns += oneShotTurns\n\n const cat = turnDay.categories[turn.category] ?? { turns: 0, cost: 0, editTurns: 0, oneShotTurns: 0 }\n cat.turns += 1\n cat.cost += turnCost\n cat.editTurns += editTurns\n cat.oneShotTurns += oneShotTurns\n turnDay.categories[turn.category] = cat\n\n for (const call of turn.assistantCalls) {\n const callDate = dateKey(call.timestamp)\n const callDay = ensure(callDate)\n\n callDay.cost += call.costUSD\n callDay.calls += 1\n callDay.inputTokens += call.usage.inputTokens\n callDay.outputTokens += call.usage.outputTokens\n callDay.cacheReadTokens += call.usage.cacheReadInputTokens\n callDay.cacheWriteTokens += call.usage.cacheCreationInputTokens\n\n const model = callDay.models[call.model] ?? {\n calls: 0, cost: 0,\n inputTokens: 0, outputTokens: 0,\n cacheReadTokens: 0, cacheWriteTokens: 0,\n }\n model.calls += 1\n model.cost += call.costUSD\n model.inputTokens += call.usage.inputTokens\n model.outputTokens += call.usage.outputTokens\n model.cacheReadTokens += call.usage.cacheReadInputTokens\n model.cacheWriteTokens += call.usage.cacheCreationInputTokens\n callDay.models[call.model] = model\n\n const provider = callDay.providers[call.provider] ?? { calls: 0, cost: 0 }\n provider.calls += 1\n provider.cost += call.costUSD\n callDay.providers[call.provider] = provider\n }\n }\n }\n }\n\n return [...byDate.values()].sort((a, b) => a.date.localeCompare(b.date))\n}\n\nexport function buildPeriodDataFromDays(days: DailyEntry[], label: string): PeriodData {\n let cost = 0, calls = 0, sessions = 0\n let inputTokens = 0, outputTokens = 0, cacheReadTokens = 0, cacheWriteTokens = 0\n const catTotals: Record<string, { turns: number; cost: number; editTurns: number; oneShotTurns: number }> = {}\n const modelTotals: Record<string, { calls: number; cost: number }> = {}\n\n for (const d of days) {\n cost += d.cost\n calls += d.calls\n sessions += d.sessions\n inputTokens += d.inputTokens\n outputTokens += d.outputTokens\n cacheReadTokens += d.cacheReadTokens\n cacheWriteTokens += d.cacheWriteTokens\n\n for (const [name, m] of Object.entries(d.models)) {\n const acc = modelTotals[name] ?? { calls: 0, cost: 0 }\n acc.calls += m.calls\n acc.cost += m.cost\n modelTotals[name] = acc\n }\n for (const [cat, c] of Object.entries(d.categories)) {\n const acc = catTotals[cat] ?? { turns: 0, cost: 0, editTurns: 0, oneShotTurns: 0 }\n acc.turns += c.turns\n acc.cost += c.cost\n acc.editTurns += c.editTurns\n acc.oneShotTurns += c.oneShotTurns\n catTotals[cat] = acc\n }\n }\n\n return {\n label,\n cost,\n calls,\n sessions,\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n categories: Object.entries(catTotals)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([cat, d]) => ({ name: CATEGORY_LABELS[cat as TaskCategory] ?? cat, ...d })),\n models: Object.entries(modelTotals)\n .sort(([, a], [, b]) => b.cost - a.cost)\n .map(([name, d]) => ({ name, ...d })),\n }\n}\n","import { readdir, stat } from 'fs/promises'\nimport { basename, join } from 'path'\nimport { readSessionLines } from './fs-utils.js'\nimport { calculateCost, getShortModelName } from './models.js'\nimport { discoverAllSessions, getProvider } from './providers/index.js'\nimport type { ParsedProviderCall } from './providers/types.js'\nimport type {\n AssistantMessageContent,\n ClassifiedTurn,\n ContentBlock,\n DateRange,\n JournalEntry,\n ParsedApiCall,\n ParsedTurn,\n ProjectSummary,\n SessionSummary,\n TokenUsage,\n ToolUseBlock,\n} from './types.js'\nimport { classifyTurn, BASH_TOOLS } from './classifier.js'\nimport { extractBashCommands } from './bash-utils.js'\n\nfunction unsanitizePath(dirName: string): string {\n return dirName.replace(/-/g, '/')\n}\n\nfunction parseJsonlLine(line: string): JournalEntry | null {\n try {\n return JSON.parse(line) as JournalEntry\n } catch {\n return null\n }\n}\n\nfunction extractToolNames(content: ContentBlock[]): string[] {\n return content\n .filter((b): b is ToolUseBlock => b.type === 'tool_use')\n .map(b => b.name)\n}\n\nfunction extractMcpTools(tools: string[]): string[] {\n return tools.filter(t => t.startsWith('mcp__'))\n}\n\nfunction extractCoreTools(tools: string[]): string[] {\n return tools.filter(t => !t.startsWith('mcp__'))\n}\n\nfunction extractBashCommandsFromContent(content: ContentBlock[]): string[] {\n return content\n .filter((b): b is ToolUseBlock => b.type === 'tool_use' && BASH_TOOLS.has((b as ToolUseBlock).name))\n .flatMap(b => {\n const command = (b.input as Record<string, unknown>)?.command\n return typeof command === 'string' ? extractBashCommands(command) : []\n })\n}\n\nfunction getUserMessageText(entry: JournalEntry): string {\n if (!entry.message || entry.message.role !== 'user') return ''\n const content = entry.message.content\n if (typeof content === 'string') return content\n if (Array.isArray(content)) {\n return content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map(b => b.text)\n .join(' ')\n }\n return ''\n}\n\nfunction getMessageId(entry: JournalEntry): string | null {\n if (entry.type !== 'assistant') return null\n const msg = entry.message as AssistantMessageContent | undefined\n return msg?.id ?? null\n}\n\nfunction parseApiCall(entry: JournalEntry): ParsedApiCall | null {\n if (entry.type !== 'assistant') return null\n const msg = entry.message as AssistantMessageContent | undefined\n if (!msg?.usage || !msg?.model) return null\n\n const usage = msg.usage\n const tokens: TokenUsage = {\n inputTokens: usage.input_tokens ?? 0,\n outputTokens: usage.output_tokens ?? 0,\n cacheCreationInputTokens: usage.cache_creation_input_tokens ?? 0,\n cacheReadInputTokens: usage.cache_read_input_tokens ?? 0,\n cachedInputTokens: 0,\n reasoningTokens: 0,\n webSearchRequests: usage.server_tool_use?.web_search_requests ?? 0,\n }\n\n const tools = extractToolNames(msg.content ?? [])\n const costUSD = calculateCost(\n msg.model,\n tokens.inputTokens,\n tokens.outputTokens,\n tokens.cacheCreationInputTokens,\n tokens.cacheReadInputTokens,\n tokens.webSearchRequests,\n usage.speed ?? 'standard',\n )\n\n const bashCmds = extractBashCommandsFromContent(msg.content ?? [])\n\n return {\n provider: 'claude',\n model: msg.model,\n usage: tokens,\n costUSD,\n tools,\n mcpTools: extractMcpTools(tools),\n hasAgentSpawn: tools.includes('Agent'),\n hasPlanMode: tools.includes('EnterPlanMode'),\n speed: usage.speed ?? 'standard',\n timestamp: entry.timestamp ?? '',\n bashCommands: bashCmds,\n deduplicationKey: msg.id ?? `claude:${entry.timestamp}`,\n }\n}\n\nfunction groupIntoTurns(entries: JournalEntry[], seenMsgIds: Set<string>): ParsedTurn[] {\n const turns: ParsedTurn[] = []\n let currentUserMessage = ''\n let currentCalls: ParsedApiCall[] = []\n let currentTimestamp = ''\n let currentSessionId = ''\n\n for (const entry of entries) {\n if (entry.type === 'user') {\n const text = getUserMessageText(entry)\n if (text.trim()) {\n if (currentCalls.length > 0) {\n turns.push({\n userMessage: currentUserMessage,\n assistantCalls: currentCalls,\n timestamp: currentTimestamp,\n sessionId: currentSessionId,\n })\n }\n currentUserMessage = text\n currentCalls = []\n currentTimestamp = entry.timestamp ?? ''\n currentSessionId = entry.sessionId ?? ''\n }\n } else if (entry.type === 'assistant') {\n const msgId = getMessageId(entry)\n if (msgId && seenMsgIds.has(msgId)) continue\n if (msgId) seenMsgIds.add(msgId)\n const call = parseApiCall(entry)\n if (call) currentCalls.push(call)\n }\n }\n\n if (currentCalls.length > 0) {\n turns.push({\n userMessage: currentUserMessage,\n assistantCalls: currentCalls,\n timestamp: currentTimestamp,\n sessionId: currentSessionId,\n })\n }\n\n return turns\n}\n\nfunction buildSessionSummary(\n sessionId: string,\n project: string,\n turns: ClassifiedTurn[],\n): SessionSummary {\n const modelBreakdown: SessionSummary['modelBreakdown'] = Object.create(null)\n const toolBreakdown: SessionSummary['toolBreakdown'] = Object.create(null)\n const mcpBreakdown: SessionSummary['mcpBreakdown'] = Object.create(null)\n const bashBreakdown: SessionSummary['bashBreakdown'] = Object.create(null)\n const categoryBreakdown: SessionSummary['categoryBreakdown'] = Object.create(null)\n\n let totalCost = 0\n let totalInput = 0\n let totalOutput = 0\n let totalCacheRead = 0\n let totalCacheWrite = 0\n let apiCalls = 0\n let firstTs = ''\n let lastTs = ''\n\n for (const turn of turns) {\n const turnCost = turn.assistantCalls.reduce((s, c) => s + c.costUSD, 0)\n\n if (!categoryBreakdown[turn.category]) {\n categoryBreakdown[turn.category] = { turns: 0, costUSD: 0, retries: 0, editTurns: 0, oneShotTurns: 0 }\n }\n categoryBreakdown[turn.category].turns++\n categoryBreakdown[turn.category].costUSD += turnCost\n if (turn.hasEdits) {\n categoryBreakdown[turn.category].editTurns++\n categoryBreakdown[turn.category].retries += turn.retries\n if (turn.retries === 0) categoryBreakdown[turn.category].oneShotTurns++\n }\n\n for (const call of turn.assistantCalls) {\n totalCost += call.costUSD\n totalInput += call.usage.inputTokens\n totalOutput += call.usage.outputTokens\n totalCacheRead += call.usage.cacheReadInputTokens\n totalCacheWrite += call.usage.cacheCreationInputTokens\n apiCalls++\n\n const modelKey = getShortModelName(call.model)\n if (!modelBreakdown[modelKey]) {\n modelBreakdown[modelKey] = {\n calls: 0,\n costUSD: 0,\n tokens: { inputTokens: 0, outputTokens: 0, cacheCreationInputTokens: 0, cacheReadInputTokens: 0, cachedInputTokens: 0, reasoningTokens: 0, webSearchRequests: 0 },\n }\n }\n modelBreakdown[modelKey].calls++\n modelBreakdown[modelKey].costUSD += call.costUSD\n modelBreakdown[modelKey].tokens.inputTokens += call.usage.inputTokens\n modelBreakdown[modelKey].tokens.outputTokens += call.usage.outputTokens\n modelBreakdown[modelKey].tokens.cacheReadInputTokens += call.usage.cacheReadInputTokens\n modelBreakdown[modelKey].tokens.cacheCreationInputTokens += call.usage.cacheCreationInputTokens\n\n for (const tool of extractCoreTools(call.tools)) {\n toolBreakdown[tool] = toolBreakdown[tool] ?? { calls: 0 }\n toolBreakdown[tool].calls++\n }\n for (const mcp of call.mcpTools) {\n const server = mcp.split('__')[1] ?? mcp\n mcpBreakdown[server] = mcpBreakdown[server] ?? { calls: 0 }\n mcpBreakdown[server].calls++\n }\n for (const cmd of call.bashCommands) {\n bashBreakdown[cmd] = bashBreakdown[cmd] ?? { calls: 0 }\n bashBreakdown[cmd].calls++\n }\n\n if (!firstTs || call.timestamp < firstTs) firstTs = call.timestamp\n if (!lastTs || call.timestamp > lastTs) lastTs = call.timestamp\n }\n }\n\n return {\n sessionId,\n project,\n firstTimestamp: firstTs || turns[0]?.timestamp || '',\n lastTimestamp: lastTs || turns[turns.length - 1]?.timestamp || '',\n totalCostUSD: totalCost,\n totalInputTokens: totalInput,\n totalOutputTokens: totalOutput,\n totalCacheReadTokens: totalCacheRead,\n totalCacheWriteTokens: totalCacheWrite,\n apiCalls,\n turns,\n modelBreakdown,\n toolBreakdown,\n mcpBreakdown,\n bashBreakdown,\n categoryBreakdown,\n }\n}\n\nasync function parseSessionFile(\n filePath: string,\n project: string,\n seenMsgIds: Set<string>,\n dateRange?: DateRange,\n): Promise<SessionSummary | null> {\n // Skip files whose mtime is older than the range start. A session file\n // can only contain entries up to its last-modified time; if that predates\n // the requested range, nothing in this file can match.\n if (dateRange) {\n try {\n const s = await stat(filePath)\n if (s.mtimeMs < dateRange.start.getTime()) return null\n } catch { /* fall through to normal read; missing stat shouldn't break parsing */ }\n }\n const entries: JournalEntry[] = []\n let hasLines = false\n\n for await (const line of readSessionLines(filePath)) {\n hasLines = true\n const entry = parseJsonlLine(line)\n if (entry) entries.push(entry)\n }\n\n if (!hasLines) return null\n\n if (entries.length === 0) return null\n\n const sessionId = basename(filePath, '.jsonl')\n let turns = groupIntoTurns(entries, seenMsgIds)\n if (dateRange) {\n // Bucket a turn by the timestamp of its first assistant call (when the cost was\n // actually incurred). Filtering entries directly produced orphan assistant calls\n // when a user message sat in one day and the response landed in another -- those\n // got pushed as turns with empty timestamps, which some code paths counted and\n // others dropped, producing inconsistent Today totals.\n turns = turns.filter(turn => {\n if (turn.assistantCalls.length === 0) return false\n const firstCallTs = turn.assistantCalls[0]!.timestamp\n if (!firstCallTs) return false\n const ts = new Date(firstCallTs)\n return ts >= dateRange.start && ts <= dateRange.end\n })\n if (turns.length === 0) return null\n }\n const classified = turns.map(classifyTurn)\n\n return buildSessionSummary(sessionId, project, classified)\n}\n\nasync function collectJsonlFiles(dirPath: string): Promise<string[]> {\n const files = await readdir(dirPath).catch(() => [])\n const jsonlFiles = files.filter(f => f.endsWith('.jsonl')).map(f => join(dirPath, f))\n\n for (const entry of files) {\n if (entry.endsWith('.jsonl')) continue\n const subagentsPath = join(dirPath, entry, 'subagents')\n const subFiles = await readdir(subagentsPath).catch(() => [])\n for (const sf of subFiles) {\n if (sf.endsWith('.jsonl')) jsonlFiles.push(join(subagentsPath, sf))\n }\n }\n\n return jsonlFiles\n}\n\nasync function scanProjectDirs(dirs: Array<{ path: string; name: string }>, seenMsgIds: Set<string>, dateRange?: DateRange): Promise<ProjectSummary[]> {\n const projectMap = new Map<string, SessionSummary[]>()\n\n for (const { path: dirPath, name: dirName } of dirs) {\n const jsonlFiles = await collectJsonlFiles(dirPath)\n\n for (const filePath of jsonlFiles) {\n const session = await parseSessionFile(filePath, dirName, seenMsgIds, dateRange)\n if (session && session.apiCalls > 0) {\n const existing = projectMap.get(dirName) ?? []\n existing.push(session)\n projectMap.set(dirName, existing)\n }\n }\n }\n\n const projects: ProjectSummary[] = []\n for (const [dirName, sessions] of projectMap) {\n projects.push({\n project: dirName,\n projectPath: unsanitizePath(dirName),\n sessions,\n totalCostUSD: sessions.reduce((s, sess) => s + sess.totalCostUSD, 0),\n totalApiCalls: sessions.reduce((s, sess) => s + sess.apiCalls, 0),\n })\n }\n\n return projects\n}\n\nfunction providerCallToTurn(call: ParsedProviderCall): ParsedTurn {\n const tools = call.tools\n const usage: TokenUsage = {\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cacheCreationInputTokens: call.cacheCreationInputTokens,\n cacheReadInputTokens: call.cacheReadInputTokens,\n cachedInputTokens: call.cachedInputTokens,\n reasoningTokens: call.reasoningTokens,\n webSearchRequests: call.webSearchRequests,\n }\n\n const apiCall: ParsedApiCall = {\n provider: call.provider,\n model: call.model,\n usage,\n costUSD: call.costUSD,\n tools,\n mcpTools: extractMcpTools(tools),\n hasAgentSpawn: tools.includes('Agent'),\n hasPlanMode: tools.includes('EnterPlanMode'),\n speed: call.speed,\n timestamp: call.timestamp,\n bashCommands: call.bashCommands,\n deduplicationKey: call.deduplicationKey,\n }\n\n return {\n userMessage: call.userMessage,\n assistantCalls: [apiCall],\n timestamp: call.timestamp,\n sessionId: call.sessionId,\n }\n}\n\nasync function parseProviderSources(\n providerName: string,\n sources: Array<{ path: string; project: string }>,\n seenKeys: Set<string>,\n dateRange?: DateRange,\n): Promise<ProjectSummary[]> {\n const provider = await getProvider(providerName)\n if (!provider) return []\n\n const sessionMap = new Map<string, { project: string; turns: ClassifiedTurn[] }>()\n\n for (const source of sources) {\n if (dateRange) {\n try {\n const s = await stat(source.path)\n if (s.mtimeMs < dateRange.start.getTime()) continue\n } catch { /* fall through; treat unknown stat as \"may contain data\" */ }\n }\n const parser = provider.createSessionParser(\n { path: source.path, project: source.project, provider: providerName },\n seenKeys,\n )\n\n for await (const call of parser.parse()) {\n if (dateRange) {\n if (!call.timestamp) continue\n const ts = new Date(call.timestamp)\n if (ts < dateRange.start || ts > dateRange.end) continue\n }\n\n const turn = providerCallToTurn(call)\n const classified = classifyTurn(turn)\n const key = `${providerName}:${call.sessionId}:${source.project}`\n\n const existing = sessionMap.get(key)\n if (existing) {\n existing.turns.push(classified)\n } else {\n sessionMap.set(key, { project: source.project, turns: [classified] })\n }\n }\n }\n\n const projectMap = new Map<string, SessionSummary[]>()\n for (const [key, { project, turns }] of sessionMap) {\n const sessionId = key.split(':')[1] ?? key\n const session = buildSessionSummary(sessionId, project, turns)\n if (session.apiCalls > 0) {\n const existing = projectMap.get(project) ?? []\n existing.push(session)\n projectMap.set(project, existing)\n }\n }\n\n const projects: ProjectSummary[] = []\n for (const [dirName, sessions] of projectMap) {\n projects.push({\n project: dirName,\n projectPath: unsanitizePath(dirName),\n sessions,\n totalCostUSD: sessions.reduce((s, sess) => s + sess.totalCostUSD, 0),\n totalApiCalls: sessions.reduce((s, sess) => s + sess.apiCalls, 0),\n })\n }\n\n return projects\n}\n\nconst CACHE_TTL_MS = 60_000\nconst MAX_CACHE_ENTRIES = 10\nconst sessionCache = new Map<string, { data: ProjectSummary[]; ts: number }>()\n\nfunction cacheKey(dateRange?: DateRange, providerFilter?: string): string {\n const s = dateRange ? `${dateRange.start.getTime()}:${dateRange.end.getTime()}` : 'none'\n return `${s}:${providerFilter ?? 'all'}`\n}\n\nfunction cachePut(key: string, data: ProjectSummary[]) {\n const now = Date.now()\n for (const [k, v] of sessionCache) {\n if (now - v.ts > CACHE_TTL_MS) sessionCache.delete(k)\n }\n if (sessionCache.size >= MAX_CACHE_ENTRIES) {\n const oldest = [...sessionCache.entries()].sort((a, b) => a[1].ts - b[1].ts)[0]\n if (oldest) sessionCache.delete(oldest[0])\n }\n sessionCache.set(key, { data, ts: now })\n}\n\nexport function filterProjectsByName(\n projects: ProjectSummary[],\n include?: string[],\n exclude?: string[],\n): ProjectSummary[] {\n let result = projects\n if (include && include.length > 0) {\n const patterns = include.map(s => s.toLowerCase())\n result = result.filter(p => {\n const name = p.project.toLowerCase()\n const path = p.projectPath.toLowerCase()\n return patterns.some(pat => name.includes(pat) || path.includes(pat))\n })\n }\n if (exclude && exclude.length > 0) {\n const patterns = exclude.map(s => s.toLowerCase())\n result = result.filter(p => {\n const name = p.project.toLowerCase()\n const path = p.projectPath.toLowerCase()\n return !patterns.some(pat => name.includes(pat) || path.includes(pat))\n })\n }\n return result\n}\n\nexport async function parseAllSessions(dateRange?: DateRange, providerFilter?: string): Promise<ProjectSummary[]> {\n const key = cacheKey(dateRange, providerFilter)\n const cached = sessionCache.get(key)\n if (cached && Date.now() - cached.ts < CACHE_TTL_MS) return cached.data\n\n const seenMsgIds = new Set<string>()\n const seenKeys = new Set<string>()\n const allSources = await discoverAllSessions(providerFilter)\n\n const claudeSources = allSources.filter(s => s.provider === 'claude')\n const nonClaudeSources = allSources.filter(s => s.provider !== 'claude')\n\n const claudeDirs = claudeSources.map(s => ({ path: s.path, name: s.project }))\n const claudeProjects = await scanProjectDirs(claudeDirs, seenMsgIds, dateRange)\n\n const providerGroups = new Map<string, Array<{ path: string; project: string }>>()\n for (const source of nonClaudeSources) {\n const existing = providerGroups.get(source.provider) ?? []\n existing.push({ path: source.path, project: source.project })\n providerGroups.set(source.provider, existing)\n }\n\n const otherProjects: ProjectSummary[] = []\n for (const [providerName, sources] of providerGroups) {\n const projects = await parseProviderSources(providerName, sources, seenKeys, dateRange)\n otherProjects.push(...projects)\n }\n\n const mergedMap = new Map<string, ProjectSummary>()\n for (const p of [...claudeProjects, ...otherProjects]) {\n const existing = mergedMap.get(p.project)\n if (existing) {\n existing.sessions.push(...p.sessions)\n existing.totalCostUSD += p.totalCostUSD\n existing.totalApiCalls += p.totalApiCalls\n } else {\n mergedMap.set(p.project, { ...p })\n }\n }\n\n const result = Array.from(mergedMap.values()).sort((a, b) => b.totalCostUSD - a.totalCostUSD)\n cachePut(key, result)\n return result\n}\n","import { readFile, stat } from 'fs/promises'\nimport { readFileSync, statSync, createReadStream, openSync, fstatSync, readSync, closeSync, constants } from 'fs'\nimport { createInterface } from 'readline'\n\n// Hard cap well below V8's 512 MB string limit even with split('\\n') doubling.\n// Stream threshold chosen as empirical breakeven between readFile+split peak\n// memory and createReadStream+readline overhead for typical session files.\nexport const MAX_SESSION_FILE_BYTES = 128 * 1024 * 1024\nexport const STREAM_THRESHOLD_BYTES = 8 * 1024 * 1024\n\nfunction verbose(): boolean {\n return process.env.EXE_WATCHER_VERBOSE === '1'\n}\n\nfunction warn(msg: string): void {\n if (verbose()) process.stderr.write(`exe-watcher: ${msg}\\n`)\n}\n\nasync function readViaStream(filePath: string): Promise<string> {\n const chunks: string[] = []\n const stream = createReadStream(filePath, { encoding: 'utf-8' })\n const rl = createInterface({ input: stream, crlfDelay: Infinity })\n for await (const line of rl) chunks.push(line)\n return chunks.join('\\n')\n}\n\nexport async function readSessionFile(filePath: string): Promise<string | null> {\n let size: number\n try {\n size = (await stat(filePath)).size\n } catch (err) {\n warn(`stat failed for ${filePath}: ${(err as NodeJS.ErrnoException).code ?? 'unknown'}`)\n return null\n }\n\n if (size > MAX_SESSION_FILE_BYTES) {\n warn(`skipped oversize file ${filePath} (${size} bytes > cap ${MAX_SESSION_FILE_BYTES})`)\n return null\n }\n\n try {\n if (size >= STREAM_THRESHOLD_BYTES) return await readViaStream(filePath)\n return await readFile(filePath, 'utf-8')\n } catch (err) {\n warn(`read failed for ${filePath}: ${(err as NodeJS.ErrnoException).code ?? 'unknown'}`)\n return null\n }\n}\n\nexport function readSessionFileSync(filePath: string): string | null {\n // Use O_NOFOLLOW to avoid TOCTOU symlink swaps between stat and read.\n // Falls back to plain readFileSync on platforms that lack O_NOFOLLOW.\n const O_NOFOLLOW = (constants as Record<string, number>)['O_NOFOLLOW'] ?? 0\n let fd: number\n try {\n fd = openSync(filePath, constants.O_RDONLY | O_NOFOLLOW)\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code ?? 'unknown'\n // ELOOP = tried to open a symlink with O_NOFOLLOW — skip it\n if (code === 'ELOOP') { warn(`skipped symlink ${filePath}`); return null }\n warn(`open failed for ${filePath}: ${code}`)\n return null\n }\n\n try {\n const size = fstatSync(fd).size\n if (size > MAX_SESSION_FILE_BYTES) {\n warn(`skipped oversize file ${filePath} (${size} bytes > cap ${MAX_SESSION_FILE_BYTES})`)\n return null\n }\n const buf = Buffer.allocUnsafe(size)\n let offset = 0\n while (offset < size) {\n const bytesRead = readSync(fd, buf, offset, size - offset, offset)\n if (bytesRead === 0) break\n offset += bytesRead\n }\n return buf.toString('utf-8', 0, offset)\n } catch (err) {\n warn(`read failed for ${filePath}: ${(err as NodeJS.ErrnoException).code ?? 'unknown'}`)\n return null\n } finally {\n closeSync(fd)\n }\n}\n\nexport async function* readSessionLines(filePath: string): AsyncGenerator<string> {\n let size: number\n try {\n size = (await stat(filePath)).size\n } catch (err) {\n warn(`stat failed for ${filePath}: ${(err as NodeJS.ErrnoException).code ?? 'unknown'}`)\n return\n }\n\n if (size > MAX_SESSION_FILE_BYTES) {\n warn(`skipped oversize file ${filePath} (${size} bytes > cap ${MAX_SESSION_FILE_BYTES})`)\n return\n }\n\n const stream = createReadStream(filePath, { encoding: 'utf-8' })\n const rl = createInterface({ input: stream, crlfDelay: Infinity })\n try {\n for await (const line of rl) yield line\n } catch (err) {\n warn(`stream read failed for ${filePath}: ${(err as NodeJS.ErrnoException).code ?? 'unknown'}`)\n } finally {\n stream.destroy()\n }\n}\n","import { readdir, stat } from 'fs/promises'\nimport { basename, join } from 'path'\nimport { homedir } from 'os'\n\nimport type { Provider, SessionSource, SessionParser } from './types.js'\n\nconst shortNames: Record<string, string> = {\n 'claude-opus-4-7': 'Opus 4.7',\n 'claude-opus-4-6': 'Opus 4.6',\n 'claude-opus-4-5': 'Opus 4.5',\n 'claude-opus-4-1': 'Opus 4.1',\n 'claude-opus-4': 'Opus 4',\n 'claude-sonnet-4-6': 'Sonnet 4.6',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'claude-haiku-4-5': 'Haiku 4.5',\n 'claude-3-5-haiku': 'Haiku 3.5',\n}\n\nfunction getClaudeDir(): string {\n return process.env['CLAUDE_CONFIG_DIR'] || join(homedir(), '.claude')\n}\n\nfunction getProjectsDir(): string {\n return join(getClaudeDir(), 'projects')\n}\n\nfunction getDesktopSessionsDir(): string {\n if (process.platform === 'darwin') return join(homedir(), 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions')\n if (process.platform === 'win32') return join(homedir(), 'AppData', 'Roaming', 'Claude', 'local-agent-mode-sessions')\n return join(homedir(), '.config', 'Claude', 'local-agent-mode-sessions')\n}\n\nasync function findDesktopProjectDirs(base: string): Promise<string[]> {\n const results: string[] = []\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > 8) return\n const entries = await readdir(dir).catch(() => [])\n for (const entry of entries) {\n if (entry === 'node_modules' || entry === '.git') continue\n const full = join(dir, entry)\n const s = await stat(full).catch(() => null)\n if (!s?.isDirectory()) continue\n if (entry === 'projects') {\n const projectDirs = await readdir(full).catch(() => [])\n for (const pd of projectDirs) {\n const pdFull = join(full, pd)\n const pdStat = await stat(pdFull).catch(() => null)\n if (pdStat?.isDirectory()) results.push(pdFull)\n }\n } else {\n await walk(full, depth + 1)\n }\n }\n }\n await walk(base, 0)\n return results\n}\n\nexport const claude: Provider = {\n name: 'claude',\n displayName: 'Claude',\n\n modelDisplayName(model: string): string {\n const canonical = model.replace(/@.*$/, '').replace(/-\\d{8}$/, '')\n for (const [key, name] of Object.entries(shortNames)) {\n if (canonical.startsWith(key)) return name\n }\n return canonical\n },\n\n toolDisplayName(rawTool: string): string {\n return rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n const sources: SessionSource[] = []\n\n const projectsDir = getProjectsDir()\n try {\n const entries = await readdir(projectsDir)\n for (const dirName of entries) {\n const dirPath = join(projectsDir, dirName)\n const dirStat = await stat(dirPath).catch(() => null)\n if (dirStat?.isDirectory()) {\n sources.push({ path: dirPath, project: dirName, provider: 'claude' })\n }\n }\n } catch {}\n\n const desktopDirs = await findDesktopProjectDirs(getDesktopSessionsDir())\n for (const dirPath of desktopDirs) {\n sources.push({ path: dirPath, project: basename(dirPath), provider: 'claude' })\n }\n\n return sources\n },\n\n createSessionParser(): SessionParser {\n return {\n async *parse() {},\n }\n },\n}\n","import { readdir, stat } from 'fs/promises'\nimport { basename, join } from 'path'\nimport { homedir } from 'os'\n\nimport { readSessionFile } from '../fs-utils.js'\nimport { calculateCost } from '../models.js'\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js'\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-5.3-codex': 'GPT-5.3 Codex',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5': 'GPT-5',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n}\n\nconst toolNameMap: Record<string, string> = {\n exec_command: 'Bash',\n read_file: 'Read',\n write_file: 'Edit',\n apply_diff: 'Edit',\n apply_patch: 'Edit',\n spawn_agent: 'Agent',\n close_agent: 'Agent',\n wait_agent: 'Agent',\n read_dir: 'Glob',\n}\n\ntype CodexEntry = {\n type: string\n timestamp?: string\n payload?: {\n type?: string\n role?: string\n cwd?: string\n model_provider?: string\n originator?: string\n session_id?: string\n model?: string\n name?: string\n content?: Array<{ type?: string; text?: string }>\n info?: {\n model?: string\n model_name?: string\n last_token_usage?: CodexTokenUsage\n total_token_usage?: CodexTokenUsage\n }\n }\n}\n\ntype CodexTokenUsage = {\n input_tokens?: number\n cached_input_tokens?: number\n output_tokens?: number\n reasoning_output_tokens?: number\n total_tokens?: number\n}\n\nfunction getCodexDir(override?: string): string {\n return override ?? process.env['CODEX_HOME'] ?? join(homedir(), '.codex')\n}\n\nfunction sanitizeProject(cwd: string): string {\n return cwd.replace(/^\\//, '').replace(/\\//g, '-')\n}\n\nasync function readFirstLine(filePath: string): Promise<CodexEntry | null> {\n const content = await readSessionFile(filePath)\n if (content === null) return null\n const line = content.split('\\n')[0]\n if (!line?.trim()) return null\n try {\n return JSON.parse(line) as CodexEntry\n } catch {\n return null\n }\n}\n\nasync function isValidCodexSession(filePath: string): Promise<{ valid: boolean; meta?: CodexEntry }> {\n const entry = await readFirstLine(filePath)\n if (!entry) return { valid: false }\n const valid = entry.type === 'session_meta' &&\n typeof entry.payload?.originator === 'string' &&\n entry.payload.originator.toLowerCase().startsWith('codex')\n return { valid, meta: valid ? entry : undefined }\n}\n\nasync function discoverSessionsInDir(codexDir: string): Promise<SessionSource[]> {\n const sessionsDir = join(codexDir, 'sessions')\n const sources: SessionSource[] = []\n\n let years: string[]\n try {\n years = await readdir(sessionsDir)\n } catch {\n return sources\n }\n\n for (const year of years) {\n if (!/^\\d{4}$/.test(year)) continue\n const yearDir = join(sessionsDir, year)\n const months = await readdir(yearDir).catch(() => [] as string[])\n\n for (const month of months) {\n if (!/^\\d{2}$/.test(month)) continue\n const monthDir = join(yearDir, month)\n const days = await readdir(monthDir).catch(() => [] as string[])\n\n for (const day of days) {\n if (!/^\\d{2}$/.test(day)) continue\n const dayDir = join(monthDir, day)\n const files = await readdir(dayDir).catch(() => [] as string[])\n\n for (const file of files) {\n if (!file.startsWith('rollout-') || !file.endsWith('.jsonl')) continue\n const filePath = join(dayDir, file)\n const s = await stat(filePath).catch(() => null)\n if (!s?.isFile()) continue\n\n const { valid, meta } = await isValidCodexSession(filePath)\n if (!valid || !meta) continue\n\n const cwd = meta.payload?.cwd ?? 'unknown'\n sources.push({ path: filePath, project: sanitizeProject(cwd), provider: 'codex' })\n }\n }\n }\n }\n\n return sources\n}\n\nfunction resolveModel(info: CodexEntry['payload'], sessionModel?: string): string {\n return info?.info?.model\n ?? info?.info?.model_name\n ?? sessionModel\n ?? 'gpt-5'\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n const content = await readSessionFile(source.path)\n if (content === null) return\n const lines = content.split('\\n').filter(l => l.trim())\n let sessionModel: string | undefined\n let sessionId = ''\n let prevCumulativeTotal = 0\n let prevInput = 0\n let prevCached = 0\n let prevOutput = 0\n let prevReasoning = 0\n let pendingTools: string[] = []\n let pendingUserMessage = ''\n\n for (const line of lines) {\n let entry: CodexEntry\n try {\n entry = JSON.parse(line) as CodexEntry\n } catch {\n continue\n }\n\n if (entry.type === 'session_meta') {\n sessionId = entry.payload?.session_id ?? basename(source.path, '.jsonl')\n sessionModel = entry.payload?.model\n continue\n }\n\n if (entry.type === 'response_item' && entry.payload?.type === 'function_call') {\n const rawName = entry.payload.name ?? ''\n pendingTools.push(toolNameMap[rawName] ?? rawName)\n continue\n }\n\n if (entry.type === 'response_item' && entry.payload?.type === 'message' && entry.payload?.role === 'user') {\n const texts = (entry.payload.content ?? [])\n .filter(c => c.type === 'input_text')\n .map(c => c.text ?? '')\n .filter(Boolean)\n if (texts.length > 0) pendingUserMessage = texts.join(' ')\n continue\n }\n\n if (entry.type === 'event_msg' && entry.payload?.type === 'token_count') {\n const info = entry.payload.info\n if (!info) continue\n\n const cumulativeTotal = info.total_token_usage?.total_tokens ?? 0\n if (cumulativeTotal > 0 && cumulativeTotal === prevCumulativeTotal) continue\n prevCumulativeTotal = cumulativeTotal\n\n const last = info.last_token_usage\n let inputTokens = 0\n let cachedInputTokens = 0\n let outputTokens = 0\n let reasoningTokens = 0\n\n if (last) {\n inputTokens = last.input_tokens ?? 0\n cachedInputTokens = last.cached_input_tokens ?? 0\n outputTokens = last.output_tokens ?? 0\n reasoningTokens = last.reasoning_output_tokens ?? 0\n } else if (cumulativeTotal > 0) {\n const total = info.total_token_usage\n if (!total) continue\n inputTokens = (total.input_tokens ?? 0) - prevInput\n cachedInputTokens = (total.cached_input_tokens ?? 0) - prevCached\n outputTokens = (total.output_tokens ?? 0) - prevOutput\n reasoningTokens = (total.reasoning_output_tokens ?? 0) - prevReasoning\n }\n\n if (!last) {\n const total = info.total_token_usage\n if (total) {\n prevInput = total.input_tokens ?? 0\n prevCached = total.cached_input_tokens ?? 0\n prevOutput = total.output_tokens ?? 0\n prevReasoning = total.reasoning_output_tokens ?? 0\n }\n }\n\n const totalTokens = inputTokens + cachedInputTokens + outputTokens + reasoningTokens\n if (totalTokens === 0) continue\n\n // OpenAI includes cached tokens inside input_tokens; Anthropic does not.\n // Normalize to Anthropic semantics: inputTokens = non-cached only.\n const uncachedInputTokens = Math.max(0, inputTokens - cachedInputTokens)\n\n const model = resolveModel(entry.payload, sessionModel)\n const timestamp = entry.timestamp ?? ''\n const dedupKey = `codex:${source.path}:${timestamp}:${cumulativeTotal}`\n\n if (seenKeys.has(dedupKey)) continue\n seenKeys.add(dedupKey)\n\n const costUSD = calculateCost(\n model,\n uncachedInputTokens,\n outputTokens + reasoningTokens,\n 0,\n cachedInputTokens,\n 0,\n )\n\n yield {\n provider: 'codex',\n model,\n inputTokens: uncachedInputTokens,\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: cachedInputTokens,\n cachedInputTokens,\n reasoningTokens,\n webSearchRequests: 0,\n costUSD,\n tools: pendingTools,\n bashCommands: [],\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n }\n\n pendingTools = []\n pendingUserMessage = ''\n }\n }\n },\n }\n}\n\nexport function createCodexProvider(codexDir?: string): Provider {\n const dir = getCodexDir(codexDir)\n\n return {\n name: 'codex',\n displayName: 'Codex',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of Object.entries(modelDisplayNames)) {\n if (model.startsWith(key)) return name\n }\n return model\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(dir)\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys)\n },\n }\n}\n\nexport const codex = createCodexProvider()\n","import { readdir, stat } from 'fs/promises'\nimport { basename, dirname, join } from 'path'\nimport { homedir } from 'os'\n\nimport { readSessionFile } from '../fs-utils.js'\nimport { calculateCost } from '../models.js'\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js'\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-4.1-nano': 'GPT-4.1 Nano',\n 'gpt-4.1-mini': 'GPT-4.1 Mini',\n 'gpt-4.1': 'GPT-4.1',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n 'gpt-5-mini': 'GPT-5 Mini',\n 'gpt-5': 'GPT-5',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'o4-mini': 'o4-mini',\n 'o3': 'o3',\n}\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read_file: 'Read',\n write_file: 'Edit',\n edit_file: 'Edit',\n create_file: 'Write',\n delete_file: 'Delete',\n search_files: 'Grep',\n find_files: 'Glob',\n list_directory: 'LS',\n web_search: 'WebSearch',\n fetch_webpage: 'WebFetch',\n github_repo: 'GitHub',\n}\n\n// Pre-sorted by key length descending so longer/more-specific keys match first\nconst modelDisplayEntries = Object.entries(modelDisplayNames).sort((a, b) => b[0].length - a[0].length)\n\n// Fields marked optional document the on-disk schema; they are not read by the parser\ntype ToolRequest = {\n name?: string\n toolCallId?: string\n type?: string\n}\n\ntype ModelChangeData = {\n newModel: string\n previousModel?: string\n}\n\ntype UserMessageData = {\n content: string\n interactionId?: string\n}\n\ntype AssistantMessageData = {\n messageId: string\n outputTokens: number\n interactionId?: string\n toolRequests?: ToolRequest[]\n}\n\ntype CopilotEvent =\n | { type: 'session.model_change'; timestamp?: string; data: ModelChangeData }\n | { type: 'user.message'; timestamp?: string; data: UserMessageData }\n | { type: 'assistant.message'; timestamp?: string; data: AssistantMessageData }\n\nfunction getCopilotSessionStateDir(override?: string): string {\n return override ?? join(homedir(), '.copilot', 'session-state')\n}\n\nfunction parseCwd(yaml: string): string | null {\n const match = yaml.match(/^cwd:\\s*(.+)$/m)\n if (!match?.[1]) return null\n const raw = match[1]\n .replace(/\\s*#.*$/, '') // strip trailing comment\n .replace(/^['\"]|['\"]$/g, '') // strip surrounding quotes\n .trim()\n return raw || null\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n const content = await readSessionFile(source.path)\n if (content === null) return\n const sessionId = basename(dirname(source.path))\n const lines = content.split('\\n').filter(l => l.trim())\n let currentModel = ''\n let pendingUserMessage = ''\n\n for (const line of lines) {\n let event: CopilotEvent\n try {\n event = JSON.parse(line) as CopilotEvent\n } catch {\n continue\n }\n\n if (event.type === 'session.model_change') {\n currentModel = event.data.newModel ?? currentModel\n continue\n }\n\n if (event.type === 'user.message') {\n pendingUserMessage = event.data.content ?? ''\n continue\n }\n\n if (event.type === 'assistant.message') {\n const { messageId, outputTokens, toolRequests = [] } = event.data\n if (outputTokens === 0) continue\n // Skip if no model has been identified yet - avoids silent misattribution\n if (!currentModel) continue\n\n const dedupKey = `copilot:${sessionId}:${messageId}`\n if (seenKeys.has(dedupKey)) continue\n seenKeys.add(dedupKey)\n\n const tools = toolRequests\n .map(t => t.name ?? '')\n .filter(Boolean)\n .map(n => toolNameMap[n] ?? n)\n\n // Copilot only logs outputTokens; inputTokens are not available in session logs.\n // Cost will be lower than actual API cost.\n const costUSD = calculateCost(currentModel, 0, outputTokens, 0, 0, 0)\n\n yield {\n provider: 'copilot',\n model: currentModel,\n inputTokens: 0,\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: 0,\n cachedInputTokens: 0,\n reasoningTokens: 0,\n webSearchRequests: 0,\n costUSD,\n tools,\n bashCommands: [],\n timestamp: event.timestamp ?? '',\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n }\n\n pendingUserMessage = ''\n }\n }\n },\n }\n}\n\nasync function discoverSessionsInDir(sessionStateDir: string): Promise<SessionSource[]> {\n const sources: SessionSource[] = []\n\n let sessionDirs: string[]\n try {\n sessionDirs = await readdir(sessionStateDir)\n } catch {\n return sources\n }\n\n for (const sessionId of sessionDirs) {\n const eventsPath = join(sessionStateDir, sessionId, 'events.jsonl')\n const s = await stat(eventsPath).catch(() => null)\n if (!s?.isFile()) continue\n\n let project = sessionId\n const yaml = await readSessionFile(join(sessionStateDir, sessionId, 'workspace.yaml'))\n if (yaml !== null) {\n const cwd = parseCwd(yaml)\n if (cwd) project = basename(cwd)\n }\n\n sources.push({ path: eventsPath, project, provider: 'copilot' })\n }\n\n return sources\n}\n\nexport function createCopilotProvider(sessionStateDir?: string): Provider {\n const dir = getCopilotSessionStateDir(sessionStateDir)\n\n return {\n name: 'copilot',\n displayName: 'Copilot',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model === key || model.startsWith(key + '-')) return name\n }\n return model\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(dir)\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys)\n },\n }\n}\n\nexport const copilot = createCopilotProvider()\n","import { readdir, stat } from 'fs/promises'\nimport { basename, join } from 'path'\nimport { homedir } from 'os'\n\nimport { readSessionFile } from '../fs-utils.js'\nimport { calculateCost } from '../models.js'\nimport { extractBashCommands } from '../bash-utils.js'\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js'\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5': 'GPT-5',\n 'gpt-4o': 'GPT-4o',\n 'gpt-4o-mini': 'GPT-4o Mini',\n}\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read: 'Read',\n edit: 'Edit',\n write: 'Write',\n glob: 'Glob',\n grep: 'Grep',\n task: 'Agent',\n dispatch_agent: 'Agent',\n fetch: 'WebFetch',\n search: 'WebSearch',\n todo: 'TodoWrite',\n patch: 'Patch',\n}\n\n// Pre-sorted by key length descending so longer/more-specific keys match first\nconst modelDisplayEntries = Object.entries(modelDisplayNames).sort((a, b) => b[0].length - a[0].length)\n\ntype PiEntry = {\n type: string\n id?: string\n timestamp?: string\n cwd?: string\n message?: {\n role?: string\n content?: Array<{ type?: string; text?: string; name?: string; arguments?: Record<string, unknown> }>\n model?: string\n responseId?: string\n usage?: {\n input: number\n output: number\n cacheRead: number\n cacheWrite: number\n }\n }\n}\n\nfunction getPiSessionsDir(override?: string): string {\n return override ?? join(homedir(), '.pi', 'agent', 'sessions')\n}\n\nfunction getOmpSessionsDir(override?: string): string {\n return override ?? join(homedir(), '.omp', 'agent', 'sessions')\n}\n\nasync function readFirstEntry(filePath: string): Promise<PiEntry | null> {\n const content = await readSessionFile(filePath)\n if (content === null) return null\n const line = content.split('\\n')[0]\n if (!line?.trim()) return null\n try {\n return JSON.parse(line) as PiEntry\n } catch {\n return null\n }\n}\n\nasync function discoverSessionsInDir(sessionsDir: string, providerName: string): Promise<SessionSource[]> {\n const sources: SessionSource[] = []\n\n let projectDirs: string[]\n try {\n projectDirs = await readdir(sessionsDir)\n } catch {\n return sources\n }\n\n for (const dirName of projectDirs) {\n const dirPath = join(sessionsDir, dirName)\n const dirStat = await stat(dirPath).catch(() => null)\n if (!dirStat?.isDirectory()) continue\n\n let files: string[]\n try {\n files = await readdir(dirPath)\n } catch {\n continue\n }\n\n for (const file of files) {\n if (!file.endsWith('.jsonl')) continue\n const filePath = join(dirPath, file)\n const fileStat = await stat(filePath).catch(() => null)\n if (!fileStat?.isFile()) continue\n\n const first = await readFirstEntry(filePath)\n if (!first || first.type !== 'session') continue\n\n const cwd = first.cwd ?? dirName\n sources.push({ path: filePath, project: basename(cwd), provider: providerName })\n }\n }\n\n return sources\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n const content = await readSessionFile(source.path)\n if (content === null) return\n const lines = content.split('\\n').filter(l => l.trim())\n let sessionId = basename(source.path, '.jsonl')\n let pendingUserMessage = ''\n\n for (const [lineIdx, line] of lines.entries()) {\n let entry: PiEntry\n try {\n entry = JSON.parse(line) as PiEntry\n } catch {\n continue\n }\n\n if (entry.type === 'session') {\n sessionId = entry.id ?? sessionId\n continue\n }\n\n if (entry.type !== 'message') continue\n\n const msg = entry.message\n if (!msg) continue\n\n if (msg.role === 'user') {\n const texts = (msg.content ?? [])\n .filter(c => c.type === 'text')\n .map(c => c.text ?? '')\n .filter(Boolean)\n if (texts.length > 0) pendingUserMessage = texts.join(' ')\n continue\n }\n\n if (msg.role !== 'assistant' || !msg.usage) continue\n\n const { input, output, cacheRead, cacheWrite } = msg.usage\n if (input === 0 && output === 0) continue\n\n const model = msg.model ?? 'gpt-5'\n const responseId = msg.responseId ?? ''\n const dedupKey = `${source.provider}:${source.path}:${responseId || entry.id || entry.timestamp || String(lineIdx)}`\n\n if (seenKeys.has(dedupKey)) continue\n seenKeys.add(dedupKey)\n\n const toolCalls = (msg.content ?? []).filter(c => c.type === 'toolCall' && c.name)\n const tools = toolCalls.map(c => toolNameMap[c.name!] ?? c.name!)\n const bashCommands = toolCalls\n .filter(c => c.name === 'bash')\n .flatMap(c => {\n const cmd = c.arguments?.['command']\n return typeof cmd === 'string' ? extractBashCommands(cmd) : []\n })\n\n const costUSD = calculateCost(model, input, output, cacheWrite, cacheRead, 0)\n const timestamp = entry.timestamp ?? ''\n\n yield {\n provider: source.provider,\n model,\n inputTokens: input,\n outputTokens: output,\n cacheCreationInputTokens: cacheWrite,\n cacheReadInputTokens: cacheRead,\n cachedInputTokens: cacheRead,\n reasoningTokens: 0,\n webSearchRequests: 0,\n costUSD,\n tools,\n bashCommands,\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n }\n\n pendingUserMessage = ''\n }\n },\n }\n}\n\nexport function createPiProvider(sessionsDir?: string): Provider {\n const dir = getPiSessionsDir(sessionsDir)\n\n return {\n name: 'pi',\n displayName: 'Pi',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model.startsWith(key)) return name\n }\n return model\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(dir, 'pi')\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys)\n },\n }\n}\n\nexport const pi = createPiProvider()\n\nexport function createOmpProvider(sessionsDir?: string): Provider {\n const dir = getOmpSessionsDir(sessionsDir)\n\n return {\n name: 'omp',\n displayName: 'OMP',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model.startsWith(key)) return name\n }\n return model\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(dir, 'omp')\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys)\n },\n }\n}\n\nexport const omp = createOmpProvider()\n","import { claude } from './claude.js'\nimport { codex } from './codex.js'\nimport { copilot } from './copilot.js'\nimport { pi, omp } from './pi.js'\nimport type { Provider, SessionSource } from './types.js'\n\nlet cursorProvider: Provider | null = null\nlet cursorLoadAttempted = false\n\nasync function loadCursor(): Promise<Provider | null> {\n if (cursorLoadAttempted) return cursorProvider\n cursorLoadAttempted = true\n try {\n const { cursor } = await import('./cursor.js')\n cursorProvider = cursor\n return cursor\n } catch {\n return null\n }\n}\n\nlet opencodeProvider: Provider | null = null\nlet opencodeLoadAttempted = false\n\nlet cursorAgentProvider: Provider | null = null\nlet cursorAgentLoadAttempted = false\n\nasync function loadOpenCode(): Promise<Provider | null> {\n if (opencodeLoadAttempted) return opencodeProvider\n opencodeLoadAttempted = true\n try {\n const { opencode } = await import('./opencode.js')\n opencodeProvider = opencode\n return opencode\n } catch {\n return null\n }\n}\n\nasync function loadCursorAgent(): Promise<Provider | null> {\n if (cursorAgentLoadAttempted) return cursorAgentProvider\n cursorAgentLoadAttempted = true\n try {\n const { cursor_agent } = await import('./cursor-agent.js')\n cursorAgentProvider = cursor_agent\n return cursor_agent\n } catch {\n return null\n }\n}\n\nconst coreProviders: Provider[] = [claude, codex, copilot, pi, omp]\n\nexport async function getAllProviders(): Promise<Provider[]> {\n const [cursor, opencode, cursorAgent] = await Promise.all([loadCursor(), loadOpenCode(), loadCursorAgent()])\n const all = [...coreProviders]\n if (cursor) all.push(cursor)\n if (opencode) all.push(opencode)\n if (cursorAgent) all.push(cursorAgent)\n return all\n}\n\nexport const providers = coreProviders\n\nexport async function discoverAllSessions(providerFilter?: string): Promise<SessionSource[]> {\n const allProviders = await getAllProviders()\n const filtered = providerFilter && providerFilter !== 'all'\n ? allProviders.filter(p => p.name === providerFilter)\n : allProviders\n const all: SessionSource[] = []\n for (const provider of filtered) {\n const sessions = await provider.discoverSessions()\n all.push(...sessions)\n }\n return all\n}\n\nexport async function getProvider(name: string): Promise<Provider | undefined> {\n if (name === 'cursor') {\n const cursor = await loadCursor()\n return cursor ?? undefined\n }\n if (name === 'opencode') {\n const oc = await loadOpenCode()\n return oc ?? undefined\n }\n if (name === 'cursor-agent') {\n const ca = await loadCursorAgent()\n return ca ?? undefined\n }\n return coreProviders.find(p => p.name === name)\n}\n","import type { ClassifiedTurn, ParsedTurn, TaskCategory } from './types.js'\n\nconst TEST_PATTERNS = /\\b(test|pytest|vitest|jest|mocha|spec|coverage|npm\\s+test|npx\\s+vitest|npx\\s+jest)\\b/i\nconst GIT_PATTERNS = /\\bgit\\s+(push|pull|commit|merge|rebase|checkout|branch|stash|log|diff|status|add|reset|cherry-pick|tag)\\b/i\nconst BUILD_PATTERNS = /\\b(npm\\s+run\\s+build|npm\\s+publish|pip\\s+install|docker|deploy|make\\s+build|npm\\s+run\\s+dev|npm\\s+start|pm2|systemctl|brew|cargo\\s+build)\\b/i\nconst INSTALL_PATTERNS = /\\b(npm\\s+install|pip\\s+install|brew\\s+install|apt\\s+install|cargo\\s+add)\\b/i\n\nconst DEBUG_KEYWORDS = /\\b(fix|bug|error|broken|failing|crash|issue|debug|traceback|exception|stack\\s*trace|not\\s+working|wrong|unexpected|status\\s+code|404|500|401|403)\\b/i\nconst FEATURE_KEYWORDS = /\\b(add|create|implement|new|build|feature|introduce|set\\s*up|scaffold|generate|make\\s+(?:a|me|the)|write\\s+(?:a|me|the))\\b/i\nconst REFACTOR_KEYWORDS = /\\b(refactor|clean\\s*up|rename|reorganize|simplify|extract|restructure|move|migrate|split)\\b/i\nconst BRAINSTORM_KEYWORDS = /\\b(brainstorm|idea|what\\s+if|explore|think\\s+about|approach|strategy|design|consider|how\\s+should|what\\s+would|opinion|suggest|recommend)\\b/i\nconst RESEARCH_KEYWORDS = /\\b(research|investigate|look\\s+into|find\\s+out|check|search|analyze|review|understand|explain|how\\s+does|what\\s+is|show\\s+me|list|compare)\\b/i\n\nconst FILE_PATTERNS = /\\.(py|js|ts|tsx|jsx|json|yaml|yml|toml|sql|sh|go|rs|java|rb|php|css|html|md|csv|xml)\\b/i\nconst SCRIPT_PATTERNS = /\\b(run\\s+\\S+\\.\\w+|execute|scrip?t|curl|api\\s+\\S+|endpoint|request\\s+url|fetch\\s+\\S+|query|database|db\\s+\\S+)\\b/i\nconst URL_PATTERN = /https?:\\/\\/\\S+/i\n\nconst EDIT_TOOLS = new Set(['Edit', 'Write', 'FileEditTool', 'FileWriteTool', 'NotebookEdit', 'cursor:edit'])\nconst READ_TOOLS = new Set(['Read', 'Grep', 'Glob', 'FileReadTool', 'GrepTool', 'GlobTool'])\nexport const BASH_TOOLS = new Set(['Bash', 'BashTool', 'PowerShellTool'])\nconst TASK_TOOLS = new Set(['TaskCreate', 'TaskUpdate', 'TaskGet', 'TaskList', 'TaskOutput', 'TaskStop', 'TodoWrite'])\nconst SEARCH_TOOLS = new Set(['WebSearch', 'WebFetch', 'ToolSearch'])\n\nfunction hasEditTools(tools: string[]): boolean {\n return tools.some(t => EDIT_TOOLS.has(t))\n}\n\nfunction hasReadTools(tools: string[]): boolean {\n return tools.some(t => READ_TOOLS.has(t))\n}\n\nfunction hasBashTool(tools: string[]): boolean {\n return tools.some(t => BASH_TOOLS.has(t))\n}\n\nfunction hasTaskTools(tools: string[]): boolean {\n return tools.some(t => TASK_TOOLS.has(t))\n}\n\nfunction hasSearchTools(tools: string[]): boolean {\n return tools.some(t => SEARCH_TOOLS.has(t))\n}\n\nfunction hasMcpTools(tools: string[]): boolean {\n return tools.some(t => t.startsWith('mcp__'))\n}\n\nfunction hasSkillTool(tools: string[]): boolean {\n return tools.some(t => t === 'Skill')\n}\n\nfunction getAllTools(turn: ParsedTurn): string[] {\n return turn.assistantCalls.flatMap(c => c.tools)\n}\n\nfunction classifyByToolPattern(turn: ParsedTurn): TaskCategory | null {\n const tools = getAllTools(turn)\n if (tools.length === 0) return null\n\n if (turn.assistantCalls.some(c => c.hasPlanMode)) return 'planning'\n if (turn.assistantCalls.some(c => c.hasAgentSpawn)) return 'planning'\n\n const hasEdits = hasEditTools(tools)\n const hasReads = hasReadTools(tools)\n const hasBash = hasBashTool(tools)\n const hasTasks = hasTaskTools(tools)\n const hasSearch = hasSearchTools(tools)\n const hasMcp = hasMcpTools(tools)\n const hasSkill = hasSkillTool(tools)\n\n if (hasBash && !hasEdits) {\n const userMsg = turn.userMessage\n if (TEST_PATTERNS.test(userMsg)) return 'testing'\n if (GIT_PATTERNS.test(userMsg)) return 'devops'\n if (BUILD_PATTERNS.test(userMsg)) return 'devops'\n if (INSTALL_PATTERNS.test(userMsg)) return 'devops'\n }\n\n if (hasEdits) return 'building'\n\n if (hasBash && hasReads) return 'research'\n if (hasBash) return 'building'\n\n if (hasSearch || hasMcp) return 'research'\n if (hasReads && !hasEdits) return 'research'\n if (hasTasks && !hasEdits) return 'planning'\n if (hasSkill) return 'building'\n\n return null\n}\n\nfunction refineByKeywords(category: TaskCategory, userMessage: string): TaskCategory {\n if (category === 'building') {\n if (DEBUG_KEYWORDS.test(userMessage)) return 'debugging'\n return 'building'\n }\n\n if (category === 'research') {\n if (DEBUG_KEYWORDS.test(userMessage)) return 'debugging'\n return 'research'\n }\n\n return category\n}\n\nfunction classifyConversation(userMessage: string): TaskCategory {\n if (BRAINSTORM_KEYWORDS.test(userMessage)) return 'research'\n if (RESEARCH_KEYWORDS.test(userMessage)) return 'research'\n if (DEBUG_KEYWORDS.test(userMessage)) return 'debugging'\n if (FEATURE_KEYWORDS.test(userMessage)) return 'building'\n if (FILE_PATTERNS.test(userMessage)) return 'building'\n if (SCRIPT_PATTERNS.test(userMessage)) return 'building'\n if (URL_PATTERN.test(userMessage)) return 'research'\n return 'research'\n}\n\nfunction countRetries(turn: ParsedTurn): number {\n let sawEditBeforeBash = false\n let sawBashAfterEdit = false\n let retries = 0\n\n for (const call of turn.assistantCalls) {\n const hasEdit = call.tools.some(t => EDIT_TOOLS.has(t))\n const hasBash = call.tools.some(t => BASH_TOOLS.has(t))\n\n if (hasEdit) {\n if (sawBashAfterEdit) retries++\n sawEditBeforeBash = true\n sawBashAfterEdit = false\n }\n if (hasBash && sawEditBeforeBash) {\n sawBashAfterEdit = true\n }\n }\n\n return retries\n}\n\nfunction turnHasEdits(turn: ParsedTurn): boolean {\n return turn.assistantCalls.some(c => c.tools.some(t => EDIT_TOOLS.has(t)))\n}\n\nexport function classifyTurn(turn: ParsedTurn): ClassifiedTurn {\n const tools = getAllTools(turn)\n\n let category: TaskCategory\n\n if (tools.length === 0) {\n category = classifyConversation(turn.userMessage)\n } else {\n const toolCategory = classifyByToolPattern(turn)\n if (toolCategory) {\n category = refineByKeywords(toolCategory, turn.userMessage)\n } else {\n category = classifyConversation(turn.userMessage)\n }\n }\n\n return { ...turn, category, retries: countRetries(turn), hasEdits: turnHasEdits(turn) }\n}\n","import chalk from 'chalk'\nimport type { ProjectSummary } from './types.js'\n\n// Re-exported from currency.ts so existing imports from './format.js' keep working.\n// The currency-aware version applies exchange rate and symbol automatically.\n// Imported locally too since renderStatusBar below uses it directly.\nimport { formatCost } from './currency.js'\nexport { formatCost }\n\nexport function formatTokens(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`\n return n.toString()\n}\n\n/// Returns YYYY-MM-DD for the given date in the process-local timezone. Cheaper than shelling\n/// out to Intl.DateTimeFormat for every turn in a loop and avoids the UTC drift that bites\n/// `Date.toISOString().slice(0,10)` whenever the user runs this between local midnight and\n/// UTC midnight.\nfunction localDateString(d: Date): string {\n const y = d.getFullYear()\n const m = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n return `${y}-${m}-${day}`\n}\n\nexport function renderStatusBar(projects: ProjectSummary[]): string {\n const now = new Date()\n const today = localDateString(now)\n const monthStart = `${today.slice(0, 7)}-01`\n\n let todayCost = 0, todayCalls = 0, monthCost = 0, monthCalls = 0\n\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (turn.assistantCalls.length === 0) continue\n // Bucket by the first assistant call's local date -- the moment the cost was\n // incurred. Bucketing by `turn.timestamp` (the user message time) drops turns\n // that straddle midnight (user asked at 23:58, response arrived at 00:30) and\n // disagrees with parseAllSessions' dateRange filter which is also on assistant\n // time.\n const bucketTs = turn.assistantCalls[0]!.timestamp\n if (!bucketTs) continue\n const day = localDateString(new Date(bucketTs))\n const turnCost = turn.assistantCalls.reduce((s, c) => s + c.costUSD, 0)\n const turnCalls = turn.assistantCalls.length\n if (day === today) { todayCost += turnCost; todayCalls += turnCalls }\n if (day >= monthStart) { monthCost += turnCost; monthCalls += turnCalls }\n }\n }\n }\n\n const lines: string[] = ['']\n lines.push(` ${chalk.bold('Today')} ${chalk.yellowBright(formatCost(todayCost))} ${chalk.dim(`${todayCalls} calls`)} ${chalk.bold('Month')} ${chalk.yellowBright(formatCost(monthCost))} ${chalk.dim(`${monthCalls} calls`)}`)\n lines.push('')\n\n return lines.join('\\n')\n}\n","/// Rollup of one time window (today / 7 days / 30 days / month / all) used as the canonical\n/// input to the menubar payload. Built inside the CLI and also consumed by the day-aggregator\n/// when hydrating per-day cache entries.\nexport type PeriodData = {\n label: string\n cost: number\n calls: number\n sessions: number\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n categories: Array<{ name: string; cost: number; turns: number; editTurns: number; oneShotTurns: number }>\n models: Array<{ name: string; cost: number; calls: number }>\n}\n\nexport type ProviderCost = {\n name: string\n cost: number\n}\nimport type { OptimizeResult } from './optimize.js'\nimport type { ProjectSummary } from './types.js'\nimport { readdirSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\n\nconst TOP_ACTIVITIES_LIMIT = 20\nconst TOP_MODELS_LIMIT = 20\nconst TOP_FINDINGS_LIMIT = 10\nconst HISTORY_DAYS_LIMIT = 365\nconst SYNTHETIC_MODEL_NAME = '<synthetic>'\n\nexport type DailyModelBreakdown = {\n name: string\n cost: number\n calls: number\n inputTokens: number\n outputTokens: number\n}\n\nexport type DailyHistoryEntry = {\n date: string\n cost: number\n calls: number\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n topModels: DailyModelBreakdown[]\n}\n\nexport type MenubarPayload = {\n generated: string\n current: {\n label: string\n cost: number\n calls: number\n sessions: number\n oneShotRate: number | null\n inputTokens: number\n outputTokens: number\n cacheHitPercent: number\n topActivities: Array<{\n name: string\n cost: number\n turns: number\n oneShotRate: number | null\n }>\n topModels: Array<{\n name: string\n cost: number\n calls: number\n }>\n providers: Record<string, number>\n }\n optimize: {\n findingCount: number\n savingsUSD: number\n topFindings: Array<{\n title: string\n impact: 'high' | 'medium' | 'low'\n savingsUSD: number\n }>\n }\n history: {\n daily: DailyHistoryEntry[]\n }\n agentStats: AgentStatsPayload | null\n exeOsDetected: boolean\n statsFileAge: number | null\n projectSpend: Array<{ name: string; cost24h: number; cost7d: number; cost30d: number; sessions: number }> | null\n}\n\ntype SpendBucket = { inputTokens?: number; outputTokens?: number; costUSD?: number; sessions?: number }\n\nexport type AgentStatsPayload = {\n generated: string\n agents: Array<{\n id: string; total: number\n growth24h?: number; growth7d: number; growth30d?: number\n spend24h?: SpendBucket; spend7d?: SpendBucket; spend30d?: SpendBucket\n costUSD?: number; cost24h?: number; cost7d?: number; cost30d?: number\n }>\n daemon: { uptime: number; pid: number }\n}\n\n/**\n * Extracts per-agent costUSD for 24h/7d/30d from the daemon's pre-computed\n * model-aware pricing in each spend bucket.\n */\nexport function estimateAgentCosts(stats: AgentStatsPayload): AgentStatsPayload {\n return {\n ...stats,\n agents: stats.agents.map(a => ({\n ...a,\n cost24h: a.spend24h?.costUSD ?? 0,\n cost7d: a.spend7d?.costUSD ?? 0,\n cost30d: a.spend30d?.costUSD ?? 0,\n costUSD: a.spend30d?.costUSD ?? 0,\n })),\n }\n}\n\n/**\n * Loads the exe-os session cache which maps Claude Code session UUIDs to agent IDs.\n * Each file in ~/.exe-os/session-cache/ is named {sessionUUID}.json and contains\n * { agentId, agentRole, startedAt }.\n */\nfunction loadSessionAgentMap(): Map<string, string> {\n const map = new Map<string, string>()\n try {\n const cacheDir = join(homedir(), '.exe-os', 'session-cache')\n const files = readdirSync(cacheDir)\n for (const file of files) {\n if (!file.endsWith('.json')) continue\n const sessionId = file.replace('.json', '')\n try {\n const raw = readFileSync(join(cacheDir, file), 'utf-8')\n const data = JSON.parse(raw) as { agentId?: string }\n if (data.agentId) {\n // Normalize: strip session suffixes like \"worker1-exe1\" → \"worker1\"\n const baseId = data.agentId.replace(/-exe\\d+$/, '')\n map.set(sessionId, baseId)\n }\n } catch { /* skip malformed files */ }\n }\n } catch { /* session cache not available */ }\n return map\n}\n\n/**\n * Derives per-agent spend from project summaries using the exe-os session cache.\n * Each session's UUID is looked up in ~/.exe-os/session-cache/ to find which\n * agent created it. Falls back to worktree path heuristic for unmapped sessions.\n */\nexport function computeAgentSpend(projects: ProjectSummary[]): Record<string, number> {\n const agentMap = loadSessionAgentMap()\n const spend: Record<string, number> = {}\n\n for (const p of projects) {\n for (const sess of p.sessions) {\n const agent = agentMap.get(sess.sessionId)\n ?? extractAgentFromProject(p.project)\n spend[agent] = (spend[agent] ?? 0) + sess.totalCostUSD\n }\n }\n return spend\n}\n\n/** Merge CLI-computed spend into daemon-supplied agent stats. */\nexport function mergeAgentSpend(stats: AgentStatsPayload | null, spend: Record<string, number>): AgentStatsPayload | null {\n if (!stats) return null\n const knownIds = new Set(stats.agents.map(a => a.id))\n const merged = stats.agents.map(a => ({ ...a, costUSD: spend[a.id] ?? 0 }))\n // Add agents that appear in spend but not in memory stats (rare edge case)\n for (const [id, costUSD] of Object.entries(spend)) {\n if (!knownIds.has(id) && id !== 'user') {\n merged.push({ id, total: 0, growth7d: 0, costUSD })\n }\n }\n return { ...stats, agents: merged }\n}\n\n/**\n * Fallback: extracts the exe-os agent name from a Claude project directory name.\n * Pattern: `-Users-alice-exe-os--worktrees-worker1` → \"worker1\"\n * Nested: `-Users-alice-exe-os--worktrees-worker2--worktrees-worker1` → \"worker1\" (innermost)\n * No worktree: `-Users-alice-exe-watcher` → \"user\"\n */\n/**\n * Builds per-project spend from parsed project summaries. Cleans up directory-style\n * names into human-readable project names (e.g. \"-Users-alice-exe-os\" → \"exe-os\").\n */\nexport function buildProjectSpend(\n projects24h: ProjectSummary[],\n projects7d: ProjectSummary[],\n projects30d: ProjectSummary[],\n): Array<{ name: string; cost24h: number; cost7d: number; cost30d: number; sessions: number }> {\n const aggregate = (projects: ProjectSummary[]) => {\n const byName: Record<string, { cost: number; sessions: number }> = {}\n for (const p of projects) {\n const name = cleanProjectName(p.project)\n if (!byName[name]) byName[name] = { cost: 0, sessions: 0 }\n byName[name].cost += p.totalCostUSD\n byName[name].sessions += p.sessions.length\n }\n return byName\n }\n const d24 = aggregate(projects24h)\n const d7 = aggregate(projects7d)\n const d30 = aggregate(projects30d)\n const allNames = new Set([...Object.keys(d24), ...Object.keys(d7), ...Object.keys(d30)])\n return Array.from(allNames)\n .map(name => ({\n name,\n cost24h: d24[name]?.cost ?? 0,\n cost7d: d7[name]?.cost ?? 0,\n cost30d: d30[name]?.cost ?? 0,\n sessions: d30[name]?.sessions ?? d7[name]?.sessions ?? d24[name]?.sessions ?? 0,\n }))\n .filter(d => d.cost30d > 0 || d.cost7d > 0 || d.cost24h > 0)\n .sort((a, b) => b.cost30d - a.cost30d)\n}\n\n/**\n * Extracts a human-readable project name from the Claude projects directory name.\n * \"-Users-alice-exe-os\" → \"exe-os\"\n * \"-Users-alice-exe-os--worktrees-worker1\" → \"exe-os\"\n * \"-Users-alice-CMO\" → \"CMO\"\n */\nfunction cleanProjectName(dirName: string): string {\n // Strip worktree suffix — attribute to the base project\n const base = dirName.replace(/--worktrees-.*$/, '')\n // Take last path segment (after the last single hyphen that follows a known pattern)\n const parts = base.split('-')\n // Find the user directory prefix and take everything after it\n // Pattern: -Users-{username}-{project...}\n const usersIdx = parts.indexOf('Users')\n if (usersIdx >= 0 && usersIdx + 2 < parts.length) {\n return parts.slice(usersIdx + 2).join('-')\n }\n return dirName\n}\n\nfunction extractAgentFromProject(dirName: string): string {\n const matches = [...dirName.matchAll(/--worktrees-([a-zA-Z][a-zA-Z0-9]*)/g)]\n if (matches.length === 0) return 'user'\n const lastMatch = matches[matches.length - 1]\n return lastMatch[1].toLowerCase()\n}\n\nfunction oneShotRateFor(editTurns: number, oneShotTurns: number): number | null {\n if (editTurns === 0) return null\n return oneShotTurns / editTurns\n}\n\nfunction aggregateOneShotRate(categories: PeriodData['categories']): number | null {\n let edits = 0\n let oneShots = 0\n for (const cat of categories) {\n edits += cat.editTurns\n oneShots += cat.oneShotTurns\n }\n if (edits === 0) return null\n return oneShots / edits\n}\n\nfunction cacheHitPercent(inputTokens: number, cacheReadTokens: number): number {\n const denom = inputTokens + cacheReadTokens\n if (denom === 0) return 0\n return (cacheReadTokens / denom) * 100\n}\n\nfunction buildTopActivities(categories: PeriodData['categories']): MenubarPayload['current']['topActivities'] {\n return categories.slice(0, TOP_ACTIVITIES_LIMIT).map(cat => ({\n name: cat.name,\n cost: cat.cost,\n turns: cat.turns,\n oneShotRate: oneShotRateFor(cat.editTurns, cat.oneShotTurns),\n }))\n}\n\nfunction buildTopModels(models: PeriodData['models']): MenubarPayload['current']['topModels'] {\n return models\n .filter(m => m.name !== SYNTHETIC_MODEL_NAME)\n .slice(0, TOP_MODELS_LIMIT)\n .map(m => ({ name: m.name, cost: m.cost, calls: m.calls }))\n}\n\nfunction buildOptimize(optimize: OptimizeResult | null): MenubarPayload['optimize'] {\n if (!optimize || optimize.findings.length === 0) {\n return { findingCount: 0, savingsUSD: 0, topFindings: [] }\n }\n const { findings, costRate } = optimize\n const totalSavingsUSD = findings.reduce((s, f) => s + f.tokensSaved * costRate, 0)\n const topFindings = findings.slice(0, TOP_FINDINGS_LIMIT).map(f => ({\n title: f.title,\n impact: f.impact,\n savingsUSD: f.tokensSaved * costRate,\n }))\n return {\n findingCount: findings.length,\n savingsUSD: totalSavingsUSD,\n topFindings,\n }\n}\n\nfunction buildProviders(providers: ProviderCost[]): Record<string, number> {\n const map: Record<string, number> = {}\n for (const p of providers) {\n if (p.cost < 0) continue\n map[p.name.toLowerCase()] = p.cost\n }\n return map\n}\n\nfunction buildHistory(daily: DailyHistoryEntry[] | undefined): MenubarPayload['history'] {\n if (!daily || daily.length === 0) return { daily: [] }\n const sorted = [...daily].sort((a, b) => a.date.localeCompare(b.date))\n const trimmed = sorted.slice(-HISTORY_DAYS_LIMIT)\n return { daily: trimmed }\n}\n\nexport function buildMenubarPayload(\n current: PeriodData,\n providers: ProviderCost[],\n optimize: OptimizeResult | null,\n dailyHistory?: DailyHistoryEntry[],\n agentStats?: AgentStatsPayload | null,\n projectSpend?: Array<{ name: string; cost24h: number; cost7d: number; cost30d: number; sessions: number }> | null,\n exeOsDetected?: boolean,\n statsFileAge?: number | null,\n): MenubarPayload {\n return {\n generated: new Date().toISOString(),\n current: {\n label: current.label,\n cost: current.cost,\n calls: current.calls,\n sessions: current.sessions,\n oneShotRate: aggregateOneShotRate(current.categories),\n inputTokens: current.inputTokens,\n outputTokens: current.outputTokens,\n cacheHitPercent: cacheHitPercent(current.inputTokens, current.cacheReadTokens),\n topActivities: buildTopActivities(current.categories),\n topModels: buildTopModels(current.models),\n providers: buildProviders(providers),\n },\n optimize: buildOptimize(optimize),\n history: buildHistory(dailyHistory),\n agentStats: agentStats ?? null,\n exeOsDetected: exeOsDetected ?? false,\n statsFileAge: statsFileAge ?? null,\n projectSpend: projectSpend ?? null,\n }\n}\n","import { randomBytes } from 'crypto'\nimport { existsSync } from 'fs'\nimport { mkdir, open, readFile, rename, unlink } from 'fs/promises'\nimport { join } from 'path'\n\nimport { getCacheDir } from './cache-dir.js'\n\nexport const DAILY_CACHE_VERSION = 3\nconst DAILY_CACHE_FILENAME = 'daily-cache.json'\n\nexport type DailyEntry = {\n date: string\n cost: number\n calls: number\n sessions: number\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n editTurns: number\n oneShotTurns: number\n models: Record<string, {\n calls: number\n cost: number\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n }>\n categories: Record<string, { turns: number; cost: number; editTurns: number; oneShotTurns: number }>\n providers: Record<string, { calls: number; cost: number }>\n}\n\nexport type DailyCache = {\n version: number\n lastComputedDate: string | null\n days: DailyEntry[]\n}\n\nfunction getCachePath(): string {\n return join(getCacheDir(), DAILY_CACHE_FILENAME)\n}\n\nfunction emptyCache(): DailyCache {\n return { version: DAILY_CACHE_VERSION, lastComputedDate: null, days: [] }\n}\n\nfunction isValidCache(parsed: unknown): parsed is DailyCache {\n if (!parsed || typeof parsed !== 'object') return false\n const c = parsed as Partial<DailyCache>\n if (c.version !== DAILY_CACHE_VERSION) return false\n if (!Array.isArray(c.days)) return false\n return true\n}\n\nexport async function loadDailyCache(): Promise<DailyCache> {\n const path = getCachePath()\n if (!existsSync(path)) return emptyCache()\n try {\n const raw = await readFile(path, 'utf-8')\n const parsed: unknown = JSON.parse(raw)\n if (!isValidCache(parsed)) return emptyCache()\n return parsed\n } catch {\n return emptyCache()\n }\n}\n\nexport async function saveDailyCache(cache: DailyCache): Promise<void> {\n const dir = getCacheDir()\n if (!existsSync(dir)) await mkdir(dir, { recursive: true })\n const finalPath = getCachePath()\n const tempPath = `${finalPath}.${randomBytes(8).toString('hex')}.tmp`\n const payload = JSON.stringify(cache)\n const handle = await open(tempPath, 'w', 0o600)\n try {\n await handle.writeFile(payload, { encoding: 'utf-8' })\n await handle.sync()\n } finally {\n await handle.close()\n }\n try {\n await rename(tempPath, finalPath)\n } catch (err) {\n try { await unlink(tempPath) } catch { /* ignore */ }\n throw err\n }\n}\n\nexport function addNewDays(cache: DailyCache, incoming: DailyEntry[], newestDate: string): DailyCache {\n const byDate = new Map(cache.days.map(d => [d.date, d]))\n for (const day of incoming) {\n byDate.set(day.date, day)\n }\n const merged = Array.from(byDate.values()).sort((a, b) => a.date.localeCompare(b.date))\n const nextLast = cache.lastComputedDate && cache.lastComputedDate > newestDate\n ? cache.lastComputedDate\n : newestDate\n return { version: DAILY_CACHE_VERSION, lastComputedDate: nextLast, days: merged }\n}\n\nexport function getDaysInRange(cache: DailyCache, start: string, end: string): DailyEntry[] {\n return cache.days.filter(d => d.date >= start && d.date <= end)\n}\n\nlet lockChain: Promise<unknown> = Promise.resolve()\n\nexport function withDailyCacheLock<T>(fn: () => Promise<T>): Promise<T> {\n const next = lockChain.then(() => fn())\n lockChain = next.catch(() => undefined)\n return next\n}\n","import { homedir } from 'os'\n\nimport React, { useState, useCallback, useEffect, useRef } from 'react'\nimport { render, Box, Text, useInput, useApp, useWindowSize } from 'ink'\nimport { CATEGORY_LABELS, type DateRange, type ProjectSummary, type TaskCategory } from './types.js'\nimport { formatCost, formatTokens } from './format.js'\nimport { parseAllSessions, filterProjectsByName } from './parser.js'\nimport { loadPricing } from './models.js'\nimport { getAllProviders } from './providers/index.js'\nimport { scanAndDetect, type WasteFinding, type WasteAction, type OptimizeResult } from './optimize.js'\nimport { estimateContextBudget, discoverProjectCwd, type ContextBudget } from './context-budget.js'\nimport { dateKey } from './day-aggregator.js'\nimport { CompareView } from './compare.js'\nimport { getPlanUsageOrNull, type PlanUsage } from './plan-usage.js'\nimport { planDisplayName } from './plans.js'\nimport { join } from 'path'\n\ntype Period = 'today' | 'week' | '30days' | 'month' | 'all'\ntype View = 'dashboard' | 'optimize' | 'compare'\n\nconst PERIODS: Period[] = ['today', 'week', '30days', 'month', 'all']\nconst PERIOD_LABELS: Record<Period, string> = {\n today: 'Today',\n week: '7 Days',\n '30days': '30 Days',\n month: 'This Month',\n all: 'All Time',\n}\n\nconst MIN_WIDE = 90\nconst ORANGE = '#F59E0B'\nconst DIM = '#555555'\nconst GOLD = '#F5D76E'\nconst PLAN_BAR_WIDTH = 10\n\nconst LANG_DISPLAY_NAMES: Record<string, string> = {\n javascript: 'JavaScript', typescript: 'TypeScript', python: 'Python',\n rust: 'Rust', go: 'Go', java: 'Java', cpp: 'C++', c: 'C', csharp: 'C#',\n ruby: 'Ruby', php: 'PHP', swift: 'Swift', kotlin: 'Kotlin',\n html: 'HTML', css: 'CSS', scss: 'SCSS', json: 'JSON', yaml: 'YAML',\n sql: 'SQL', shell: 'Shell', shellscript: 'Shell Script', bash: 'Bash',\n typescriptreact: 'TSX', javascriptreact: 'JSX',\n markdown: 'Markdown', dockerfile: 'Dockerfile', toml: 'TOML',\n}\n\nconst PANEL_COLORS = {\n overview: '#F5D76E', // Exe Gold\n daily: '#6B4C9A', // Aura purple\n project: '#F5D76E', // Exe Gold\n sessions: '#E8774A', // Warm accent\n model: '#6B4C9A', // Aura purple\n activity: '#F5D76E', // Exe Gold\n tools: '#E8774A', // Warm accent\n mcp: '#6B4C9A', // Aura purple\n bash: '#E8774A', // Warm accent\n}\n\nconst PROVIDER_COLORS: Record<string, string> = {\n claude: '#DA7E56', // Anthropic warm (matches menubar)\n codex: '#4A7D5C', // Codex green (matches menubar)\n cursor: '#3F6B8C', // Cursor blue (matches menubar)\n opencode: '#6B4C9A', // Aura purple\n pi: '#E8774A', // Warm accent\n all: '#F5D76E', // Exe Gold\n}\n\nconst CATEGORY_COLORS: Record<TaskCategory, string> = {\n building: '#5B9EF5',\n debugging: '#DC2626',\n testing: '#E05BF5',\n research: '#6B4C9A',\n devops: '#16A34A',\n planning: '#7B9EF5',\n}\n\nconst IMPACT_PANEL_COLORS: Record<string, string> = { high: '#DC2626', medium: ORANGE, low: DIM }\n\nfunction toHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map(v => Math.round(v).toString(16).padStart(2, '0')).join('')\n}\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + t * (b - a)\n}\n\nfunction gradientColor(pct: number): string {\n if (pct <= 0.33) {\n const t = pct / 0.33\n return toHex(lerp(91, 245, t), lerp(158, 200, t), lerp(245, 91, t))\n }\n if (pct <= 0.66) {\n const t = (pct - 0.33) / 0.33\n return toHex(lerp(245, 255, t), lerp(200, 140, t), lerp(91, 66, t))\n }\n const t = (pct - 0.66) / 0.34\n return toHex(lerp(255, 245, t), lerp(140, 91, t), lerp(66, 91, t))\n}\n\nfunction getDateRange(period: Period): { start: Date; end: Date } {\n const now = new Date()\n const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)\n switch (period) {\n case 'today': return { start: new Date(now.getFullYear(), now.getMonth(), now.getDate()), end }\n case 'week': return { start: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7), end }\n case '30days': return { start: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 30), end }\n case 'month': return { start: new Date(now.getFullYear(), now.getMonth(), 1), end }\n case 'all': return { start: new Date(0), end }\n }\n}\n\ntype Layout = { dashWidth: number; wide: boolean; halfWidth: number; barWidth: number }\n\nfunction getLayout(columns?: number): Layout {\n const termWidth = columns || parseInt(process.env['COLUMNS'] ?? '') || 80\n const dashWidth = Math.min(160, termWidth)\n const wide = dashWidth >= MIN_WIDE\n const halfWidth = wide ? Math.floor(dashWidth / 2) : dashWidth\n const inner = halfWidth - 4\n const barWidth = Math.max(6, Math.min(10, inner - 30))\n return { dashWidth, wide, halfWidth, barWidth }\n}\n\nfunction HBar({ value, max, width }: { value: number; max: number; width: number }) {\n if (max === 0) return <Text color={DIM}>{'░'.repeat(width)}</Text>\n const filled = Math.round((value / max) * width)\n const fillChars: React.ReactNode[] = []\n for (let i = 0; i < Math.min(filled, width); i++) {\n fillChars.push(<Text key={i} color={gradientColor(i / width)}>{'█'}</Text>)\n }\n return (\n <Text>\n {fillChars}\n <Text color=\"#333333\">{'░'.repeat(Math.max(width - filled, 0))}</Text>\n </Text>\n )\n}\n\nconst PANEL_CHROME = 4\nconst PINK = '#D4619C'\n\nfunction Panel({ title, color, children, width }: { title: string; color: string; children: React.ReactNode; width: number }) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={color} paddingX={1} width={width} overflowX=\"hidden\">\n <Text bold color={color}>{title}</Text>\n {children}\n </Box>\n )\n}\n\nconst OWL_ART = [\n ' ▄▄ ▄▄ ',\n ' █▀▀█▄▄▄▄▄█▀▀█ ',\n ' █ ● ● █ ',\n ' █ ▼ █ ',\n ' ▀▄ ╰───╯ ▄▀ ',\n ' ▀█████▀ ',\n ' ▐█████▌ ',\n ' ██ ██ ',\n ' ▀▀ ▀▀ ',\n]\n\nfunction LoadingScreen({ width, dots }: { width: number; dots: number }) {\n const dotStr = '.'.repeat(dots)\n return (\n <Box flexDirection=\"column\" width={width} alignItems=\"center\" justifyContent=\"center\" paddingY={2}>\n <Box flexDirection=\"column\" alignItems=\"center\">\n {OWL_ART.map((line, i) => (\n <Text key={i} color={i < 5 ? GOLD : PINK}>{line}</Text>\n ))}\n </Box>\n <Text> </Text>\n <Text bold color={PINK}>WATCHER</Text>\n <Text> </Text>\n <Text dimColor>Scanning sessions{dotStr.padEnd(3)}</Text>\n </Box>\n )\n}\n\nfunction fit(s: string, n: number): string {\n return s.length > n ? s.slice(0, n) : s.padEnd(n)\n}\n\nfunction renderPlanBar(percentUsed: number, width: number): string {\n if (percentUsed <= 100) {\n const capped = Math.max(0, percentUsed)\n const filled = Math.round((capped / 100) * width)\n return `${'▓'.repeat(filled)}${'░'.repeat(Math.max(0, width - filled))}`\n }\n const factor = percentUsed / 100\n const chevrons = Math.min(4, Math.max(1, Math.floor(Math.log10(factor)) + 1))\n return `${'▓'.repeat(width)}${'▶'.repeat(chevrons)}`\n}\n\nfunction Overview({ projects, label, width, planUsage }: { projects: ProjectSummary[]; label: string; width: number; planUsage?: PlanUsage }) {\n const totalCost = projects.reduce((s, p) => s + p.totalCostUSD, 0)\n const totalCalls = projects.reduce((s, p) => s + p.totalApiCalls, 0)\n const totalSessions = projects.reduce((s, p) => s + p.sessions.length, 0)\n const allSessions = projects.flatMap(p => p.sessions)\n const totalInput = allSessions.reduce((s, sess) => s + sess.totalInputTokens, 0)\n const totalOutput = allSessions.reduce((s, sess) => s + sess.totalOutputTokens, 0)\n const totalCacheRead = allSessions.reduce((s, sess) => s + sess.totalCacheReadTokens, 0)\n const totalCacheWrite = allSessions.reduce((s, sess) => s + sess.totalCacheWriteTokens, 0)\n const allInputTokens = totalInput + totalCacheRead + totalCacheWrite\n const cacheHit = allInputTokens > 0\n ? (totalCacheRead / allInputTokens) * 100 : 0\n const planLabel = planUsage ? `${planDisplayName(planUsage.plan.id)}: ${formatCost(planUsage.spentApiEquivalentUsd)} API-equivalent vs ${formatCost(planUsage.budgetUsd)} plan` : ''\n const planPct = planUsage ? `${planUsage.percentUsed.toFixed(1)}%` : ''\n const planColor = planUsage\n ? planUsage.status === 'over'\n ? '#DC2626'\n : planUsage.status === 'near'\n ? ORANGE\n : '#86EFAC'\n : DIM\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={PANEL_COLORS.overview} paddingX={1} width={width}>\n <Text wrap=\"truncate-end\">\n <Text bold color={ORANGE}>Exe Watcher</Text>\n <Text dimColor> {label}</Text>\n </Text>\n <Text wrap=\"truncate-end\">\n <Text bold color={GOLD}>{formatCost(totalCost)}</Text>\n <Text dimColor> cost </Text>\n <Text bold>{totalCalls.toLocaleString()}</Text>\n <Text dimColor> calls </Text>\n <Text bold>{String(totalSessions)}</Text>\n <Text dimColor> sessions </Text>\n <Text bold>{cacheHit.toFixed(1)}%</Text>\n <Text dimColor> cache hit</Text>\n </Text>\n <Text dimColor wrap=\"truncate-end\">\n {formatTokens(totalInput)} in {formatTokens(totalOutput)} out {formatTokens(totalCacheRead)} cached {formatTokens(totalCacheWrite)} written\n </Text>\n {planUsage && (\n <>\n <Text wrap=\"truncate-end\">\n <Text color={planColor}>{planLabel}</Text>\n <Text> </Text>\n <Text color={planColor}>{renderPlanBar(planUsage.percentUsed, PLAN_BAR_WIDTH)}</Text>\n <Text> </Text>\n <Text bold color={planColor}>{planPct}</Text>\n </Text>\n <Text dimColor wrap=\"truncate-end\">\n {planUsage.status === 'under'\n ? `Well within plan. Projected month: ${formatCost(planUsage.projectedMonthUsd)} (reset in ${planUsage.daysUntilReset} days).`\n : planUsage.status === 'near'\n ? `Approaching plan limit. Projected month: ${formatCost(planUsage.projectedMonthUsd)} (reset in ${planUsage.daysUntilReset} days).`\n : `${(planUsage.spentApiEquivalentUsd / Math.max(planUsage.budgetUsd, 1)).toFixed(1)}x your subscription value. Projected month: ${formatCost(planUsage.projectedMonthUsd)} (reset in ${planUsage.daysUntilReset} days).`}\n </Text>\n </>\n )}\n </Box>\n )\n}\n\nfunction DailyActivity({ projects, days = 14, pw, bw }: { projects: ProjectSummary[]; days?: number; pw: number; bw: number }) {\n const dailyCosts: Record<string, number> = {}\n const dailyCalls: Record<string, number> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (!turn.timestamp) continue\n const day = dateKey(turn.timestamp)\n dailyCosts[day] = (dailyCosts[day] ?? 0) + turn.assistantCalls.reduce((s, c) => s + c.costUSD, 0)\n dailyCalls[day] = (dailyCalls[day] ?? 0) + turn.assistantCalls.length\n }\n }\n }\n const sortedDays = days !== undefined ? Object.keys(dailyCosts).sort().slice(-days) : Object.keys(dailyCosts).sort()\n const maxCost = Math.max(...sortedDays.map(d => dailyCosts[d] ?? 0))\n\n return (\n <Panel title=\"Daily Activity\" color={PANEL_COLORS.daily} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(6 + bw)}{'cost'.padStart(8)}{'calls'.padStart(6)}</Text>\n {sortedDays.map(day => (\n <Text key={day} wrap=\"truncate-end\">\n <Text dimColor>{day.slice(5)} </Text>\n <HBar value={dailyCosts[day] ?? 0} max={maxCost} width={bw} />\n <Text color={GOLD}>{formatCost(dailyCosts[day] ?? 0).padStart(8)}</Text>\n <Text>{String(dailyCalls[day] ?? 0).padStart(6)}</Text>\n </Text>\n ))}\n </Panel>\n )\n}\n\nconst _homeEncoded = homedir().replace(/\\//g, '-')\n\nfunction shortProject(encoded: string): string {\n let path = encoded.replace(/^-/, '')\n if (path.startsWith(_homeEncoded.replace(/^-/, ''))) {\n path = path.slice(_homeEncoded.replace(/^-/, '').length).replace(/^-/, '')\n }\n path = path.replace(/^private-tmp-[^-]+-[^-]+-/, '').replace(/^private-tmp-/, '').replace(/^tmp-/, '')\n if (!path) return 'home'\n const parts = path.split('-').filter(Boolean)\n if (parts.length <= 3) return parts.join('/')\n return parts.slice(-3).join('/')\n}\n\nconst PROJECT_COL_AVG = 7\nconst PROJECT_COL_BASE_WIDTH = 30\nconst PROJECT_COL_WITH_OVERHEAD_WIDTH = 40\n\nfunction ProjectBreakdown({ projects, pw, bw, budgets }: { projects: ProjectSummary[]; pw: number; bw: number; budgets?: Map<string, ContextBudget> }) {\n const maxCost = Math.max(...projects.map(p => p.totalCostUSD))\n const hasBudgets = budgets && budgets.size > 0\n const nw = Math.max(8, pw - bw - (hasBudgets ? PROJECT_COL_WITH_OVERHEAD_WIDTH : PROJECT_COL_BASE_WIDTH))\n return (\n <Panel title=\"By Project\" color={PANEL_COLORS.project} width={pw}>\n <Text dimColor wrap=\"truncate-end\">\n {''.padEnd(bw + 1 + nw)}{'cost'.padStart(8)}{'avg/s'.padStart(PROJECT_COL_AVG)}{'sess'.padStart(6)}{hasBudgets ? 'overhead'.padStart(10) : ''}\n </Text>\n {projects.slice(0, 8).map((project, i) => {\n const budget = budgets?.get(project.project)\n const avgCost = project.sessions.length > 0\n ? formatCost(project.totalCostUSD / project.sessions.length)\n : '-'\n return (\n <Text key={`${project.project}-${i}`} wrap=\"truncate-end\">\n <HBar value={project.totalCostUSD} max={maxCost} width={bw} />\n <Text dimColor> {fit(shortProject(project.project), nw)}</Text>\n <Text color={GOLD}>{formatCost(project.totalCostUSD).padStart(8)}</Text>\n <Text color={GOLD}>{avgCost.padStart(PROJECT_COL_AVG)}</Text>\n <Text>{String(project.sessions.length).padStart(6)}</Text>\n {hasBudgets && <Text color=\"#7B9EF5\">{(budget ? formatTokens(budget.total) : '-').padStart(10)}</Text>}\n </Text>\n )\n })}\n </Panel>\n )\n}\n\nconst MODEL_COL_COST = 8\nconst MODEL_COL_CACHE = 7\nconst MODEL_COL_CALLS = 7\nconst MODEL_NAME_WIDTH = 14\n\nfunction ModelBreakdown({ projects, pw, bw }: { projects: ProjectSummary[]; pw: number; bw: number }) {\n const modelTotals: Record<string, { calls: number; costUSD: number; freshInput: number; cacheRead: number; cacheWrite: number }> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [model, data] of Object.entries(session.modelBreakdown)) {\n if (!modelTotals[model]) modelTotals[model] = { calls: 0, costUSD: 0, freshInput: 0, cacheRead: 0, cacheWrite: 0 }\n modelTotals[model].calls += data.calls\n modelTotals[model].costUSD += data.costUSD\n modelTotals[model].freshInput += data.tokens.inputTokens\n modelTotals[model].cacheRead += data.tokens.cacheReadInputTokens\n modelTotals[model].cacheWrite += data.tokens.cacheCreationInputTokens\n }\n }\n }\n const sorted = Object.entries(modelTotals).sort(([, a], [, b]) => b.costUSD - a.costUSD)\n const maxCost = sorted[0]?.[1]?.costUSD ?? 0\n\n return (\n <Panel title=\"By Model\" color={PANEL_COLORS.model} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(bw + 1 + MODEL_NAME_WIDTH)}{'cost'.padStart(MODEL_COL_COST)}{'cache'.padStart(MODEL_COL_CACHE)}{'calls'.padStart(MODEL_COL_CALLS)}</Text>\n {sorted.map(([model, data], i) => {\n const totalInput = data.freshInput + data.cacheRead + data.cacheWrite\n const cacheHit = totalInput > 0 ? (data.cacheRead / totalInput) * 100 : 0\n const cacheLabel = totalInput > 0 ? `${cacheHit.toFixed(1)}%` : '-'\n return (\n <Text key={`${model}-${i}`} wrap=\"truncate-end\">\n <HBar value={data.costUSD} max={maxCost} width={bw} />\n <Text> {fit(model, MODEL_NAME_WIDTH)}</Text>\n <Text color={GOLD}>{formatCost(data.costUSD).padStart(MODEL_COL_COST)}</Text>\n <Text>{cacheLabel.padStart(MODEL_COL_CACHE)}</Text>\n <Text>{String(data.calls).padStart(MODEL_COL_CALLS)}</Text>\n </Text>\n )\n })}\n </Panel>\n )\n}\n\nfunction ActivityBreakdown({ projects, pw, bw }: { projects: ProjectSummary[]; pw: number; bw: number }) {\n const categoryTotals: Record<string, { turns: number; costUSD: number; editTurns: number; oneShotTurns: number }> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [cat, data] of Object.entries(session.categoryBreakdown)) {\n if (!categoryTotals[cat]) categoryTotals[cat] = { turns: 0, costUSD: 0, editTurns: 0, oneShotTurns: 0 }\n categoryTotals[cat].turns += data.turns\n categoryTotals[cat].costUSD += data.costUSD\n categoryTotals[cat].editTurns += data.editTurns\n categoryTotals[cat].oneShotTurns += data.oneShotTurns\n }\n }\n }\n const sorted = Object.entries(categoryTotals).sort(([, a], [, b]) => b.costUSD - a.costUSD)\n const maxCost = sorted[0]?.[1]?.costUSD ?? 0\n return (\n <Panel title=\"By Activity\" color={PANEL_COLORS.activity} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(bw + 14)}{'cost'.padStart(8)}{'turns'.padStart(6)}{'1-shot'.padStart(7)}</Text>\n {sorted.map(([cat, data]) => {\n const oneShotPct = data.editTurns > 0 ? Math.round((data.oneShotTurns / data.editTurns) * 100) + '%' : '-'\n return (\n <Text key={cat} wrap=\"truncate-end\">\n <HBar value={data.costUSD} max={maxCost} width={bw} />\n <Text color={CATEGORY_COLORS[cat as TaskCategory] ?? '#666666'}> {fit(CATEGORY_LABELS[cat as TaskCategory] ?? cat, 13)}</Text>\n <Text color={GOLD}>{formatCost(data.costUSD).padStart(8)}</Text>\n <Text>{String(data.turns).padStart(6)}</Text>\n <Text color={data.editTurns === 0 ? DIM : oneShotPct === '100%' ? '#86EFAC' : ORANGE}>{String(oneShotPct).padStart(7)}</Text>\n </Text>\n )\n })}\n </Panel>\n )\n}\n\nfunction ToolBreakdown({ projects, pw, bw, title, filterPrefix }: { projects: ProjectSummary[]; pw: number; bw: number; title?: string; filterPrefix?: string }) {\n const toolTotals: Record<string, number> = {}\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const [tool, data] of Object.entries(session.toolBreakdown)) {\n if (filterPrefix) { if (!tool.startsWith(filterPrefix)) continue } else { if (tool.startsWith('lang:')) continue }\n toolTotals[tool] = (toolTotals[tool] ?? 0) + data.calls\n }\n }\n }\n const sorted = Object.entries(toolTotals).sort(([, a], [, b]) => b - a)\n const maxCalls = sorted[0]?.[1] ?? 0\n const nw = Math.max(6, pw - bw - 15)\n return (\n <Panel title={title ?? 'Core Tools'} color={PANEL_COLORS.tools} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(bw + 1 + nw)}{'calls'.padStart(7)}</Text>\n {sorted.slice(0, 10).map(([tool, calls]) => {\n const raw = filterPrefix ? tool.slice(filterPrefix.length) : tool\n const display = filterPrefix ? (LANG_DISPLAY_NAMES[raw] ?? raw) : raw\n return (\n <Text key={tool} wrap=\"truncate-end\">\n <HBar value={calls} max={maxCalls} width={bw} />\n <Text> {fit(display, nw)}</Text>\n <Text>{String(calls).padStart(7)}</Text>\n </Text>\n )\n })}\n </Panel>\n )\n}\n\nconst TOP_SESSIONS_DATE_LEN = 10\nconst TOP_SESSIONS_COST_COL = 8\nconst TOP_SESSIONS_CALLS_COL = 6\n\nfunction TopSessions({ projects, pw, bw }: { projects: ProjectSummary[]; pw: number; bw: number }) {\n const allSessions = projects.flatMap(p =>\n p.sessions.map(s => ({ ...s, projectName: p.project }))\n )\n const top = [...allSessions].sort((a, b) => b.totalCostUSD - a.totalCostUSD).slice(0, 5)\n\n if (top.length === 0) {\n return <Panel title=\"Top Sessions\" color={PANEL_COLORS.sessions} width={pw}><Text dimColor>No sessions</Text></Panel>\n }\n\n const maxCost = top[0].totalCostUSD\n const nw = Math.max(8, pw - bw - TOP_SESSIONS_COST_COL - TOP_SESSIONS_CALLS_COL - 1 - PANEL_CHROME)\n\n return (\n <Panel title=\"Top Sessions\" color={PANEL_COLORS.sessions} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(bw + 1 + nw)}{'cost'.padStart(TOP_SESSIONS_COST_COL)}{'calls'.padStart(TOP_SESSIONS_CALLS_COL)}</Text>\n {top.map((session, i) => {\n const date = session.firstTimestamp\n ? session.firstTimestamp.slice(0, TOP_SESSIONS_DATE_LEN)\n : '----------'\n const label = `${date} ${shortProject(session.projectName)}`\n return (\n <Text key={`${session.sessionId}-${i}`} wrap=\"truncate-end\">\n <HBar value={session.totalCostUSD} max={maxCost} width={bw} />\n <Text dimColor> {fit(label, nw - 1)}</Text>\n <Text color={GOLD}>{formatCost(session.totalCostUSD).padStart(TOP_SESSIONS_COST_COL)}</Text>\n <Text>{String(session.apiCalls).padStart(TOP_SESSIONS_CALLS_COL)}</Text>\n </Text>\n )\n })}\n </Panel>\n )\n}\n\nfunction McpBreakdown({ projects, pw, bw }: { projects: ProjectSummary[]; pw: number; bw: number }) {\n const mcpTotals: Record<string, number> = {}\n for (const project of projects) { for (const session of project.sessions) { for (const [server, data] of Object.entries(session.mcpBreakdown)) { mcpTotals[server] = (mcpTotals[server] ?? 0) + data.calls } } }\n const sorted = Object.entries(mcpTotals).sort(([, a], [, b]) => b - a)\n if (sorted.length === 0) return <Panel title=\"MCP Servers\" color={PANEL_COLORS.mcp} width={pw}><Text dimColor>No MCP usage</Text></Panel>\n const maxCalls = sorted[0]?.[1] ?? 0\n const nw = Math.max(6, pw - bw - 15)\n return (\n <Panel title=\"MCP Servers\" color={PANEL_COLORS.mcp} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(bw + 1 + nw)}{'calls'.padStart(6)}</Text>\n {sorted.slice(0, 8).map(([server, calls]) => (\n <Text key={server} wrap=\"truncate-end\"><HBar value={calls} max={maxCalls} width={bw} /><Text> {fit(server, nw)}</Text><Text>{String(calls).padStart(6)}</Text></Text>\n ))}\n </Panel>\n )\n}\n\nfunction BashBreakdown({ projects, pw, bw }: { projects: ProjectSummary[]; pw: number; bw: number }) {\n const bashTotals: Record<string, number> = {}\n for (const project of projects) { for (const session of project.sessions) { for (const [cmd, data] of Object.entries(session.bashBreakdown)) { bashTotals[cmd] = (bashTotals[cmd] ?? 0) + data.calls } } }\n const sorted = Object.entries(bashTotals).sort(([, a], [, b]) => b - a)\n if (sorted.length === 0) return <Panel title=\"Shell Commands\" color={PANEL_COLORS.bash} width={pw}><Text dimColor>No shell commands</Text></Panel>\n const maxCalls = sorted[0]?.[1] ?? 0\n const nw = Math.max(6, pw - bw - 15)\n return (\n <Panel title=\"Shell Commands\" color={PANEL_COLORS.bash} width={pw}>\n <Text dimColor wrap=\"truncate-end\">{''.padEnd(bw + 1 + nw)}{'calls'.padStart(7)}</Text>\n {sorted.slice(0, 10).map(([cmd, calls]) => (\n <Text key={cmd} wrap=\"truncate-end\"><HBar value={calls} max={maxCalls} width={bw} /><Text> {fit(cmd, nw)}</Text><Text>{String(calls).padStart(7)}</Text></Text>\n ))}\n </Panel>\n )\n}\n\nconst PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n all: 'All',\n claude: 'Claude',\n codex: 'Codex',\n cursor: 'Cursor',\n opencode: 'OpenCode',\n pi: 'Pi',\n}\nfunction getProviderDisplayName(name: string): string { return PROVIDER_DISPLAY_NAMES[name] ?? name }\n\nfunction PeriodTabs({ active, providerName, showProvider }: { active: Period; providerName?: string; showProvider?: boolean }) {\n return (\n <Box justifyContent=\"space-between\" paddingX={1}>\n <Box gap={1}>\n {PERIODS.map(p => (\n <Text key={p} bold={active === p} color={active === p ? ORANGE : DIM}>\n {active === p ? `[ ${PERIOD_LABELS[p]} ]` : ` ${PERIOD_LABELS[p]} `}\n </Text>\n ))}\n </Box>\n {showProvider && providerName && (\n <Box><Text color={DIM}>| </Text><Text color={ORANGE} bold>[p]</Text><Text bold color={PROVIDER_COLORS[providerName] ?? ORANGE}> {getProviderDisplayName(providerName)}</Text></Box>\n )}\n </Box>\n )\n}\n\nfunction FindingAction({ action }: { action: WasteAction }) {\n const lines = action.type === 'file-content' ? action.content.split('\\n') : action.type === 'command' ? action.text.split('\\n') : [action.text]\n return (<><Text dimColor>{action.label}</Text>{lines.map((line, i) => <Text key={i} color=\"#6B4C9A\"> {line}</Text>)}</>)\n}\n\nfunction FindingPanel({ index, finding, costRate, width }: { index: number; finding: WasteFinding; costRate: number; width: number }) {\n const costSaved = finding.tokensSaved * costRate\n const color = IMPACT_PANEL_COLORS[finding.impact] ?? DIM\n const label = finding.impact.charAt(0).toUpperCase() + finding.impact.slice(1)\n const trendBadge = finding.trend === 'improving' ? ' improving \\u2193' : ''\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={color} paddingX={1} width={width}>\n <Text wrap=\"truncate-end\">\n <Text bold>{index}. {finding.title}</Text>\n <Text> </Text>\n <Text color={color}>{label}</Text>\n {trendBadge && <Text color=\"#16A34A\">{trendBadge}</Text>}\n </Text>\n <Text dimColor wrap=\"wrap\">{finding.explanation}</Text>\n <Text color={GOLD}>Savings: ~{formatTokens(finding.tokensSaved)} tokens (~{formatCost(costSaved)})</Text>\n <Text> </Text>\n <FindingAction action={finding.fix} />\n </Box>\n )\n}\n\nconst GRADE_COLORS: Record<string, string> = { A: '#16A34A', B: '#16A34A', C: GOLD, D: ORANGE, F: '#DC2626' }\n\nfunction OptimizeView({ findings, costRate, projects, label, width, healthScore, healthGrade }: { findings: WasteFinding[]; costRate: number; projects: ProjectSummary[]; label: string; width: number; healthScore: number; healthGrade: string }) {\n const periodCost = projects.reduce((s, p) => s + p.totalCostUSD, 0)\n const totalTokens = findings.reduce((s, f) => s + f.tokensSaved, 0)\n const totalCost = totalTokens * costRate\n const pctRaw = periodCost > 0 ? (totalCost / periodCost) * 100 : 0\n const pct = pctRaw >= 1 ? pctRaw.toFixed(0) : pctRaw.toFixed(1)\n const gradeColor = GRADE_COLORS[healthGrade] ?? DIM\n return (\n <Box flexDirection=\"column\" width={width}>\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1} width={width}>\n <Text wrap=\"truncate-end\">\n <Text bold color={ORANGE}>Exe Watcher Optimize</Text>\n <Text dimColor> {label} Setup: </Text>\n <Text bold color={gradeColor}>{healthGrade}</Text>\n <Text dimColor> ({healthScore}/100)</Text>\n </Text>\n <Text color=\"#16A34A\" wrap=\"truncate-end\">Savings: ~{formatTokens(totalTokens)} tokens (~{formatCost(totalCost)}, ~{pct}% of spend)</Text>\n </Box>\n {findings.map((f, i) => <FindingPanel key={i} index={i + 1} finding={f} costRate={costRate} width={width} />)}\n <Box paddingX={1} width={width}><Text dimColor>Token estimates are approximate.</Text></Box>\n </Box>\n )\n}\n\nfunction StatusBar({ width, showProvider, view, findingCount, optimizeAvailable, compareAvailable }: { width: number; showProvider?: boolean; view?: View; findingCount?: number; optimizeAvailable?: boolean; compareAvailable?: boolean }) {\n const isOptimize = view === 'optimize'\n return (\n <Box borderStyle=\"round\" borderColor={DIM} width={width} justifyContent=\"center\" paddingX={1}>\n <Text>\n {isOptimize\n ? <><Text color={ORANGE} bold>b</Text><Text dimColor> back </Text></>\n : <><Text color={ORANGE} bold>{'<'}</Text><Text color={ORANGE}>{'>'}</Text><Text dimColor> switch </Text></>}\n <Text color={ORANGE} bold>q</Text><Text dimColor> quit </Text>\n <Text color={ORANGE} bold>1</Text><Text dimColor> today </Text>\n <Text color={ORANGE} bold>2</Text><Text dimColor> week </Text>\n <Text color={ORANGE} bold>3</Text><Text dimColor> 30 days </Text>\n <Text color={ORANGE} bold>4</Text><Text dimColor> month </Text>\n <Text color={ORANGE} bold>5</Text><Text dimColor> all time</Text>\n {!isOptimize && optimizeAvailable && findingCount != null && findingCount > 0 && (\n <><Text dimColor> </Text><Text color={ORANGE} bold>o</Text><Text dimColor> optimize</Text><Text color=\"#DC2626\"> ({findingCount})</Text></>\n )}\n {!isOptimize && compareAvailable && (\n <><Text dimColor> </Text><Text color={ORANGE} bold>c</Text><Text dimColor> compare</Text></>\n )}\n {showProvider && (<><Text dimColor> </Text><Text color={ORANGE} bold>p</Text><Text dimColor> provider</Text></>)}\n </Text>\n </Box>\n )\n}\n\nfunction Row({ wide, width, children }: { wide: boolean; width: number; children: React.ReactNode }) {\n if (wide) return <Box width={width}>{children}</Box>\n return <>{children}</>\n}\n\nfunction DashboardContent({ projects, period, columns, activeProvider, budgets, planUsage }: { projects: ProjectSummary[]; period: Period; columns?: number; activeProvider?: string; budgets?: Map<string, ContextBudget>; planUsage?: PlanUsage }) {\n const { dashWidth, wide, halfWidth, barWidth } = getLayout(columns)\n const isCursor = activeProvider === 'cursor'\n if (projects.length === 0) return <Panel title=\"Exe Watcher\" color={ORANGE} width={dashWidth}><Text dimColor>No usage data found for {PERIOD_LABELS[period]}.</Text></Panel>\n const pw = wide ? halfWidth : dashWidth\n const days = period === 'all' ? undefined : (period === 'month' || period === '30days' ? 31 : 14)\n return (\n <Box flexDirection=\"column\" width={dashWidth}>\n <Overview projects={projects} label={PERIOD_LABELS[period]} width={dashWidth} planUsage={planUsage} />\n <Row wide={wide} width={dashWidth}><DailyActivity projects={projects} days={days} pw={pw} bw={barWidth} /><ProjectBreakdown projects={projects} pw={pw} bw={barWidth} budgets={budgets} /></Row>\n <TopSessions projects={projects} pw={dashWidth} bw={barWidth} />\n <Row wide={wide} width={dashWidth}><ActivityBreakdown projects={projects} pw={pw} bw={barWidth} /><ModelBreakdown projects={projects} pw={pw} bw={barWidth} /></Row>\n {isCursor ? (\n <ToolBreakdown projects={projects} pw={dashWidth} bw={barWidth} title=\"Languages\" filterPrefix=\"lang:\" />\n ) : (\n <><Row wide={wide} width={dashWidth}><ToolBreakdown projects={projects} pw={pw} bw={barWidth} /><BashBreakdown projects={projects} pw={pw} bw={barWidth} /></Row><McpBreakdown projects={projects} pw={dashWidth} bw={barWidth} /></>\n )}\n </Box>\n )\n}\n\nfunction InteractiveDashboard({ initialPeriod, initialProvider, refreshSeconds, projectFilter, excludeFilter }: {\n initialPeriod: Period\n initialProvider: string\n refreshSeconds?: number\n projectFilter?: string[]\n excludeFilter?: string[]\n}) {\n const { exit } = useApp()\n const [period, setPeriod] = useState<Period>(initialPeriod)\n const [projects, setProjects] = useState<ProjectSummary[]>([])\n const [initialLoading, setInitialLoading] = useState(true)\n const [loading, setLoading] = useState(false)\n const [activeProvider, setActiveProvider] = useState(initialProvider)\n const [detectedProviders, setDetectedProviders] = useState<string[]>([])\n const [view, setView] = useState<View>('dashboard')\n const [optimizeResult, setOptimizeResult] = useState<OptimizeResult | null>(null)\n const [projectBudgets, setProjectBudgets] = useState<Map<string, ContextBudget>>(new Map())\n const [planUsage, setPlanUsage] = useState<PlanUsage | undefined>(undefined)\n const [loadingDots, setLoadingDots] = useState(1)\n const { columns } = useWindowSize()\n const { dashWidth } = getLayout(columns)\n const multipleProviders = detectedProviders.length > 1\n const optimizeAvailable = activeProvider === 'all' || activeProvider === 'claude'\n const modelCount = new Set(\n projects.flatMap(p => p.sessions.flatMap(s => Object.keys(s.modelBreakdown)))\n ).size\n const compareAvailable = modelCount >= 2\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const reloadGenerationRef = useRef(0)\n const findingCount = optimizeResult?.findings.length ?? 0\n\n // Animate loading dots\n useEffect(() => {\n if (!initialLoading) return\n const id = setInterval(() => setLoadingDots(d => (d % 3) + 1), 400)\n return () => clearInterval(id)\n }, [initialLoading])\n\n // Initial data load — runs once on mount\n useEffect(() => {\n let cancelled = false\n async function boot() {\n await loadPricing()\n if (cancelled) return\n const range = getDateRange(initialPeriod)\n const data = await parseAllSessions(range, initialProvider)\n if (cancelled) return\n const filtered = filterProjectsByName(data, projectFilter, excludeFilter)\n setProjects(filtered)\n const usage = await getPlanUsageOrNull()\n if (cancelled) return\n setPlanUsage(usage ?? undefined)\n setInitialLoading(false)\n }\n boot()\n return () => { cancelled = true }\n }, [])\n\n useEffect(() => {\n let cancelled = false\n async function detect() {\n const found: string[] = []\n for (const p of await getAllProviders()) { const s = await p.discoverSessions(); if (s.length > 0) found.push(p.name) }\n if (!cancelled) setDetectedProviders(found)\n }\n detect()\n return () => { cancelled = true }\n }, [])\n\n useEffect(() => {\n let cancelled = false\n async function loadBudgets() {\n const claudeDir = join(homedir(), '.claude', 'projects')\n const budgets = new Map<string, ContextBudget>()\n for (const project of projects.slice(0, 8)) {\n if (cancelled) return\n const cwd = await discoverProjectCwd(join(claudeDir, project.project))\n if (!cwd) continue\n budgets.set(project.project, await estimateContextBudget(cwd))\n }\n if (!cancelled) setProjectBudgets(budgets)\n }\n loadBudgets()\n return () => { cancelled = true }\n }, [projects])\n\n useEffect(() => {\n if (!optimizeAvailable) { setOptimizeResult(null); return }\n let cancelled = false\n async function scan() {\n if (projects.length === 0) { setOptimizeResult(null); return }\n const result = await scanAndDetect(projects, getDateRange(period))\n if (!cancelled) setOptimizeResult(result)\n }\n scan()\n return () => { cancelled = true }\n }, [projects, period, optimizeAvailable])\n\n const reloadData = useCallback(async (p: Period, prov: string) => {\n const generation = ++reloadGenerationRef.current\n setLoading(true)\n setOptimizeResult(null)\n try {\n const range = getDateRange(p)\n const data = await parseAllSessions(range, prov)\n if (reloadGenerationRef.current !== generation) return\n\n const filteredProjects = filterProjectsByName(data, projectFilter, excludeFilter)\n if (reloadGenerationRef.current !== generation) return\n\n setProjects(filteredProjects)\n const usage = await getPlanUsageOrNull()\n if (reloadGenerationRef.current !== generation) return\n setPlanUsage(usage ?? undefined)\n } catch (error) {\n console.error(error)\n } finally {\n if (reloadGenerationRef.current === generation) {\n setLoading(false)\n }\n }\n }, [projectFilter, excludeFilter])\n\n useEffect(() => {\n if (!refreshSeconds || refreshSeconds <= 0) return\n const id = setInterval(() => { reloadData(period, activeProvider) }, refreshSeconds * 1000)\n return () => clearInterval(id)\n }, [refreshSeconds, period, activeProvider, reloadData])\n\n const switchPeriod = useCallback((np: Period) => {\n if (np === period) return\n setPeriod(np)\n if (debounceRef.current) clearTimeout(debounceRef.current)\n debounceRef.current = setTimeout(() => { reloadData(np, activeProvider) }, 600)\n }, [period, activeProvider, reloadData])\n\n const switchPeriodImmediate = useCallback(async (np: Period) => {\n if (np === period) return\n setPeriod(np)\n if (debounceRef.current) clearTimeout(debounceRef.current)\n await reloadData(np, activeProvider)\n }, [period, activeProvider, reloadData])\n\n useInput((input, key) => {\n if (input === 'q') { exit(); return }\n if (input === 'o' && findingCount > 0 && view === 'dashboard' && optimizeAvailable) { setView('optimize'); return }\n if ((input === 'b' || key.escape) && view === 'optimize') { setView('dashboard'); return }\n if (input === 'c' && compareAvailable && view === 'dashboard') { setView('compare'); return }\n if (input === 'p' && multipleProviders && view !== 'compare') {\n const opts = ['all', ...detectedProviders]; const next = opts[(opts.indexOf(activeProvider) + 1) % opts.length]\n setActiveProvider(next); setView('dashboard')\n if (debounceRef.current) clearTimeout(debounceRef.current)\n reloadData(period, next); return\n }\n const idx = PERIODS.indexOf(period)\n if (key.leftArrow) switchPeriod(PERIODS[(idx - 1 + PERIODS.length) % PERIODS.length]!)\n else if (key.rightArrow || key.tab) switchPeriod(PERIODS[(idx + 1) % PERIODS.length]!)\n else if (input === '1') switchPeriodImmediate('today')\n else if (input === '2') switchPeriodImmediate('week')\n else if (input === '3') switchPeriodImmediate('30days')\n else if (input === '4') switchPeriodImmediate('month')\n else if (input === '5') switchPeriodImmediate('all')\n })\n\n if (initialLoading) {\n return <LoadingScreen width={dashWidth} dots={loadingDots} />\n }\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" width={dashWidth}>\n <PeriodTabs active={period} providerName={activeProvider} showProvider={view !== 'compare' && multipleProviders} />\n {view === 'compare'\n ? <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1}>\n <Text bold color={ORANGE}>Model Comparison</Text>\n <Text> </Text>\n <Text dimColor>Loading {PERIOD_LABELS[period]} model data...</Text>\n </Box>\n </Box>\n : <Panel title=\"Watcher\" color={ORANGE} width={dashWidth}><Text dimColor>Loading {PERIOD_LABELS[period]}...</Text></Panel>}\n {view !== 'compare' && <StatusBar width={dashWidth} showProvider={multipleProviders} view={view} findingCount={0} optimizeAvailable={false} compareAvailable={false} />}\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\" width={dashWidth}>\n <PeriodTabs active={period} providerName={activeProvider} showProvider={multipleProviders && view !== 'compare'} />\n {view === 'compare'\n ? <CompareView projects={projects} onBack={() => setView('dashboard')} />\n : view === 'optimize' && optimizeResult\n ? <OptimizeView findings={optimizeResult.findings} costRate={optimizeResult.costRate} projects={projects} label={PERIOD_LABELS[period]} width={dashWidth} healthScore={optimizeResult.healthScore} healthGrade={optimizeResult.healthGrade} />\n : <DashboardContent projects={projects} period={period} columns={columns} activeProvider={activeProvider} budgets={projectBudgets} planUsage={planUsage} />}\n {view !== 'compare' && <StatusBar width={dashWidth} showProvider={multipleProviders} view={view} findingCount={findingCount} optimizeAvailable={optimizeAvailable} compareAvailable={compareAvailable} />}\n </Box>\n )\n}\n\nfunction StaticDashboard({ projects, period, activeProvider, planUsage }: { projects: ProjectSummary[]; period: Period; activeProvider?: string; planUsage?: PlanUsage }) {\n const { columns } = useWindowSize()\n const { dashWidth } = getLayout(columns)\n return (\n <Box flexDirection=\"column\" width={dashWidth}>\n <PeriodTabs active={period} />\n <DashboardContent projects={projects} period={period} columns={columns} activeProvider={activeProvider} planUsage={planUsage} />\n </Box>\n )\n}\n\nexport async function renderDashboard(period: Period = 'week', provider: string = 'all', refreshSeconds?: number, projectFilter?: string[], excludeFilter?: string[], customRange?: DateRange | null): Promise<void> {\n const isTTY = process.stdin.isTTY && process.stdout.isTTY\n if (isTTY) {\n // Render immediately — the component loads data asynchronously and shows\n // an owl loading screen while scanning sessions.\n const { waitUntilExit } = render(\n <InteractiveDashboard initialPeriod={period} initialProvider={provider} refreshSeconds={refreshSeconds} projectFilter={projectFilter} excludeFilter={excludeFilter} />\n )\n await waitUntilExit()\n } else {\n // Non-TTY (piped) — must load synchronously before rendering once.\n await loadPricing()\n const range = customRange ?? getDateRange(period)\n const filteredProjects = filterProjectsByName(await parseAllSessions(range, provider), projectFilter, excludeFilter)\n const planUsage = await getPlanUsageOrNull()\n const { unmount } = render(<StaticDashboard projects={filteredProjects} period={period} activeProvider={provider} planUsage={planUsage ?? undefined} />, { patchConsole: false })\n unmount()\n }\n}\n","import chalk from 'chalk'\nimport { readdir, stat } from 'fs/promises'\nimport { existsSync, statSync } from 'fs'\nimport { basename, join } from 'path'\nimport { homedir } from 'os'\n\nimport { readSessionLines, readSessionFileSync } from './fs-utils.js'\nimport { discoverAllSessions } from './providers/index.js'\nimport type { DateRange, ProjectSummary } from './types.js'\nimport { formatCost } from './currency.js'\nimport { formatTokens } from './format.js'\n\n// ============================================================================\n// Display constants\n// ============================================================================\n\nconst ORANGE = '#F59E0B'\nconst DIM = '#666666'\nconst GOLD = '#F5D76E'\nconst CYAN = '#6B4C9A'\nconst GREEN = '#16A34A'\nconst RED = '#DC2626'\n\n// ============================================================================\n// Token estimation constants\n// ============================================================================\n\nconst AVG_TOKENS_PER_READ = 600\nconst TOKENS_PER_MCP_TOOL = 400\nconst TOOLS_PER_MCP_SERVER = 5\nconst TOKENS_PER_AGENT_DEF = 80\nconst TOKENS_PER_SKILL_DEF = 80\nconst TOKENS_PER_COMMAND_DEF = 60\nconst CLAUDEMD_TOKENS_PER_LINE = 13\nconst BASH_TOKENS_PER_CHAR = 0.25\n\n// ============================================================================\n// Detector thresholds\n// ============================================================================\n\nconst CLAUDEMD_HEALTHY_LINES = 200\nconst CLAUDEMD_HIGH_THRESHOLD_LINES = 400\nconst MIN_JUNK_READS_TO_FLAG = 3\nconst JUNK_READS_HIGH_THRESHOLD = 20\nconst JUNK_READS_MEDIUM_THRESHOLD = 5\nconst MIN_DUPLICATE_READS_TO_FLAG = 5\nconst DUPLICATE_READS_HIGH_THRESHOLD = 30\nconst DUPLICATE_READS_MEDIUM_THRESHOLD = 10\nconst MIN_EDITS_FOR_RATIO = 10\nconst HEALTHY_READ_EDIT_RATIO = 4\nconst LOW_RATIO_HIGH_THRESHOLD = 2\nconst LOW_RATIO_MEDIUM_THRESHOLD = 3\nconst MIN_API_CALLS_FOR_CACHE = 10\nconst CACHE_EXCESS_HIGH_THRESHOLD = 15000\nconst UNUSED_MCP_HIGH_THRESHOLD = 3\nconst GHOST_AGENTS_HIGH_THRESHOLD = 5\nconst GHOST_AGENTS_MEDIUM_THRESHOLD = 2\nconst GHOST_SKILLS_HIGH_THRESHOLD = 10\nconst GHOST_SKILLS_MEDIUM_THRESHOLD = 5\nconst GHOST_COMMANDS_MEDIUM_THRESHOLD = 10\nconst MCP_NEW_CONFIG_GRACE_MS = 24 * 60 * 60 * 1000\nconst BASH_DEFAULT_LIMIT = 30000\nconst BASH_RECOMMENDED_LIMIT = 15000\n\n// ============================================================================\n// Scoring constants\n// ============================================================================\n\nconst HEALTH_WEIGHT_HIGH = 15\nconst HEALTH_WEIGHT_MEDIUM = 7\nconst HEALTH_WEIGHT_LOW = 3\nconst HEALTH_MAX_PENALTY = 80\nconst GRADE_A_MIN = 90\nconst GRADE_B_MIN = 75\nconst GRADE_C_MIN = 55\nconst GRADE_D_MIN = 30\nconst URGENCY_IMPACT_WEIGHT = 0.7\nconst URGENCY_TOKEN_WEIGHT = 0.3\nconst URGENCY_TOKEN_NORMALIZE = 500_000\n\n// ============================================================================\n// File system constants\n// ============================================================================\n\nconst MAX_IMPORT_DEPTH = 5\nconst IMPORT_PATTERN = /^@(\\.\\.?\\/[^\\s]+|\\/[^\\s]+)/gm\nconst COMMAND_PATTERN = /<command-name>([^<]+)<\\/command-name>|(?:^|\\s)\\/([a-zA-Z][\\w-]*)/gm\n\nconst JUNK_DIRS = [\n 'node_modules', '.git', 'dist', 'build', '__pycache__', '.next',\n '.nuxt', '.output', 'coverage', '.cache', '.tsbuildinfo',\n '.venv', 'venv', '.svn', '.hg',\n]\nconst JUNK_PATTERN = new RegExp(`/(?:${JUNK_DIRS.join('|')})/`)\n\nconst SHELL_PROFILES = ['.zshrc', '.bashrc', '.bash_profile', '.profile']\n\nconst TOP_ITEMS_PREVIEW = 3\nconst GHOST_NAMES_PREVIEW = 5\nconst GHOST_CLEANUP_COMMANDS_LIMIT = 10\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type Impact = 'high' | 'medium' | 'low'\nexport type HealthGrade = 'A' | 'B' | 'C' | 'D' | 'F'\n\nexport type WasteAction =\n | { type: 'paste'; label: string; text: string }\n | { type: 'command'; label: string; text: string }\n | { type: 'file-content'; label: string; path: string; content: string }\n\nexport type Trend = 'active' | 'improving'\n\nexport type WasteFinding = {\n title: string\n explanation: string\n impact: Impact\n tokensSaved: number\n fix: WasteAction\n trend?: Trend\n}\n\nexport type OptimizeResult = {\n findings: WasteFinding[]\n costRate: number\n healthScore: number\n healthGrade: HealthGrade\n}\n\nexport type ToolCall = {\n name: string\n input: Record<string, unknown>\n sessionId: string\n project: string\n recent?: boolean\n}\n\nexport type ApiCallMeta = {\n cacheCreationTokens: number\n version: string\n recent?: boolean\n}\n\ntype ScanData = {\n toolCalls: ToolCall[]\n projectCwds: Set<string>\n apiCalls: ApiCallMeta[]\n userMessages: string[]\n}\n\n// ============================================================================\n// JSONL scanner\n// ============================================================================\n\nconst FILE_READ_CONCURRENCY = 16\nconst RESULT_CACHE_TTL_MS = 60_000\nconst RECENT_WINDOW_HOURS = 48\nconst RECENT_WINDOW_MS = RECENT_WINDOW_HOURS * 60 * 60 * 1000\nconst DEFAULT_TREND_PERIOD_DAYS = 30\nconst DEFAULT_TREND_PERIOD_MS = DEFAULT_TREND_PERIOD_DAYS * 24 * 60 * 60 * 1000\nconst IMPROVING_THRESHOLD = 0.5\n\nasync function collectJsonlFiles(dirPath: string): Promise<string[]> {\n const files = await readdir(dirPath).catch(() => [])\n const result = files.filter(f => f.endsWith('.jsonl')).map(f => join(dirPath, f))\n for (const entry of files) {\n if (entry.endsWith('.jsonl')) continue\n const subPath = join(dirPath, entry, 'subagents')\n const subFiles = await readdir(subPath).catch(() => [])\n for (const sf of subFiles) {\n if (sf.endsWith('.jsonl')) result.push(join(subPath, sf))\n }\n }\n return result\n}\n\nasync function isFileStaleForRange(filePath: string, range: DateRange | undefined): Promise<boolean> {\n if (!range) return false\n try {\n const s = await stat(filePath)\n return s.mtimeMs < range.start.getTime()\n } catch { return false }\n}\n\nasync function runWithConcurrency<T>(\n items: T[],\n limit: number,\n worker: (item: T) => Promise<void>,\n): Promise<void> {\n let idx = 0\n async function next(): Promise<void> {\n while (idx < items.length) {\n const current = idx++\n await worker(items[current])\n }\n }\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => next()))\n}\n\ntype ScanFileResult = {\n calls: ToolCall[]\n cwds: string[]\n apiCalls: ApiCallMeta[]\n userMessages: string[]\n}\n\nfunction inRange(timestamp: string | undefined, range: DateRange | undefined): boolean {\n if (!range) return true\n if (!timestamp) return false\n const ts = new Date(timestamp)\n return ts >= range.start && ts <= range.end\n}\n\nfunction isRecent(timestamp: string | undefined, cutoff: number): boolean {\n if (!timestamp) return false\n return new Date(timestamp).getTime() >= cutoff\n}\n\nexport async function scanJsonlFile(\n filePath: string,\n project: string,\n dateRange: DateRange | undefined,\n recentCutoffMs = Date.now() - RECENT_WINDOW_MS,\n): Promise<ScanFileResult> {\n const calls: ToolCall[] = []\n const cwds: string[] = []\n const apiCalls: ApiCallMeta[] = []\n const userMessages: string[] = []\n const sessionId = basename(filePath, '.jsonl')\n let lastVersion = ''\n\n for await (const line of readSessionLines(filePath)) {\n if (!line.trim()) continue\n let entry: Record<string, unknown>\n try { entry = JSON.parse(line) } catch { continue }\n\n if (entry.version && typeof entry.version === 'string') lastVersion = entry.version\n\n const ts = typeof entry.timestamp === 'string' ? entry.timestamp : undefined\n const withinRange = inRange(ts, dateRange)\n const recent = isRecent(ts, recentCutoffMs)\n\n if (entry.cwd && typeof entry.cwd === 'string' && withinRange) cwds.push(entry.cwd)\n\n if (entry.type === 'user') {\n if (!withinRange) continue\n const msg = entry.message as Record<string, unknown> | undefined\n const msgContent = msg?.content\n if (typeof msgContent === 'string') {\n userMessages.push(msgContent)\n } else if (Array.isArray(msgContent)) {\n for (const block of msgContent) {\n if (block && typeof block === 'object' && block.type === 'text' && typeof block.text === 'string') {\n userMessages.push(block.text)\n }\n }\n }\n continue\n }\n\n if (entry.type !== 'assistant') continue\n if (!withinRange) continue\n\n const msg = entry.message as Record<string, unknown> | undefined\n const usage = msg?.usage as Record<string, unknown> | undefined\n if (usage) {\n const cacheCreate = (usage.cache_creation_input_tokens as number) ?? 0\n if (cacheCreate > 0) apiCalls.push({ cacheCreationTokens: cacheCreate, version: lastVersion, recent })\n }\n\n const blocks = msg?.content\n if (!Array.isArray(blocks)) continue\n\n for (const block of blocks) {\n if (block.type !== 'tool_use') continue\n calls.push({\n name: block.name as string,\n input: (block.input as Record<string, unknown>) ?? {},\n sessionId,\n project,\n recent,\n })\n }\n }\n\n return { calls, cwds, apiCalls, userMessages }\n}\n\nasync function scanSessions(dateRange?: DateRange): Promise<ScanData> {\n const sources = await discoverAllSessions('claude')\n const allCalls: ToolCall[] = []\n const allCwds = new Set<string>()\n const allApiCalls: ApiCallMeta[] = []\n const allUserMessages: string[] = []\n\n const tasks: Array<{ file: string; project: string }> = []\n for (const source of sources) {\n const files = await collectJsonlFiles(source.path)\n for (const file of files) {\n if (await isFileStaleForRange(file, dateRange)) continue\n tasks.push({ file, project: source.project })\n }\n }\n\n await runWithConcurrency(tasks, FILE_READ_CONCURRENCY, async ({ file, project }) => {\n const { calls, cwds, apiCalls, userMessages } = await scanJsonlFile(file, project, dateRange)\n allCalls.push(...calls)\n for (const cwd of cwds) allCwds.add(cwd)\n allApiCalls.push(...apiCalls)\n allUserMessages.push(...userMessages)\n })\n\n return { toolCalls: allCalls, projectCwds: allCwds, apiCalls: allApiCalls, userMessages: allUserMessages }\n}\n\n// ============================================================================\n// Shared helpers\n// ============================================================================\n\nfunction readJsonFile(path: string): Record<string, unknown> | null {\n const raw = readSessionFileSync(path)\n if (raw === null) return null\n try { return JSON.parse(raw) } catch { return null }\n}\n\nfunction shortHomePath(absPath: string): string {\n const home = homedir()\n return absPath.startsWith(home) ? '~' + absPath.slice(home.length) : absPath\n}\n\nfunction isReadTool(name: string): boolean {\n return name === 'Read' || name === 'FileReadTool'\n}\n\ntype McpConfigEntry = { normalized: string; original: string; mtime: number }\n\nexport function loadMcpConfigs(projectCwds: Iterable<string>): Map<string, McpConfigEntry> {\n const servers = new Map<string, McpConfigEntry>()\n const configPaths = [\n join(homedir(), '.claude', 'settings.json'),\n join(homedir(), '.claude', 'settings.local.json'),\n ]\n for (const cwd of projectCwds) {\n configPaths.push(join(cwd, '.mcp.json'))\n configPaths.push(join(cwd, '.claude', 'settings.json'))\n configPaths.push(join(cwd, '.claude', 'settings.local.json'))\n }\n\n for (const p of configPaths) {\n if (!existsSync(p)) continue\n const config = readJsonFile(p)\n if (!config) continue\n let mtime = 0\n try { mtime = statSync(p).mtimeMs } catch {}\n const serversObj = (config.mcpServers ?? {}) as Record<string, unknown>\n for (const name of Object.keys(serversObj)) {\n const normalized = name.replace(/:/g, '_')\n const existing = servers.get(normalized)\n if (!existing || existing.mtime < mtime) {\n servers.set(normalized, { normalized, original: name, mtime })\n }\n }\n }\n return servers\n}\n\n// ============================================================================\n// Detectors\n// ============================================================================\n\nexport function detectJunkReads(calls: ToolCall[], dateRange?: DateRange): WasteFinding | null {\n const dirCounts = new Map<string, number>()\n let totalJunkReads = 0\n let recentJunkReads = 0\n\n for (const call of calls) {\n if (!isReadTool(call.name)) continue\n const filePath = call.input.file_path as string | undefined\n if (!filePath || !JUNK_PATTERN.test(filePath)) continue\n totalJunkReads++\n if (call.recent) recentJunkReads++\n for (const dir of JUNK_DIRS) {\n if (filePath.includes(`/${dir}/`)) {\n dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1)\n break\n }\n }\n }\n\n if (totalJunkReads < MIN_JUNK_READS_TO_FLAG) return null\n\n const hasRecentActivity = calls.some(c => c.recent)\n const trend = sessionTrend(recentJunkReads, totalJunkReads, dateRange, hasRecentActivity)\n if (trend === 'resolved') return null\n\n const sorted = [...dirCounts.entries()].sort((a, b) => b[1] - a[1])\n const dirList = sorted.slice(0, TOP_ITEMS_PREVIEW).map(([d, n]) => `${d}/ (${n}x)`).join(', ')\n const tokensSaved = totalJunkReads * AVG_TOKENS_PER_READ\n\n const detected = sorted.map(([d]) => d)\n const commonDefaults = ['node_modules', '.git', 'dist', '__pycache__']\n const extras = commonDefaults.filter(d => !dirCounts.has(d)).slice(0, Math.max(0, 6 - detected.length))\n const dirsToAvoid = [...detected, ...extras].join(', ')\n\n return {\n title: 'Claude is reading build/dependency folders',\n explanation: `Claude read into ${dirList} (${totalJunkReads} reads). These are generated or dependency directories, not your code. Tell Claude in CLAUDE.md to avoid them.`,\n impact: totalJunkReads > JUNK_READS_HIGH_THRESHOLD ? 'high' : totalJunkReads > JUNK_READS_MEDIUM_THRESHOLD ? 'medium' : 'low',\n tokensSaved,\n fix: {\n type: 'paste',\n label: 'Append to your project CLAUDE.md:',\n text: `Do not read or search files under these directories unless I explicitly ask: ${dirsToAvoid}.`,\n },\n trend,\n }\n}\n\nexport function detectDuplicateReads(calls: ToolCall[], dateRange?: DateRange): WasteFinding | null {\n const sessionFiles = new Map<string, Map<string, { count: number; recent: number }>>()\n\n for (const call of calls) {\n if (!isReadTool(call.name)) continue\n const filePath = call.input.file_path as string | undefined\n if (!filePath || JUNK_PATTERN.test(filePath)) continue\n const key = `${call.project}:${call.sessionId}`\n if (!sessionFiles.has(key)) sessionFiles.set(key, new Map())\n const fm = sessionFiles.get(key)!\n const entry = fm.get(filePath) ?? { count: 0, recent: 0 }\n entry.count++\n if (call.recent) entry.recent++\n fm.set(filePath, entry)\n }\n\n let totalDuplicates = 0\n let recentDuplicates = 0\n const fileDupes = new Map<string, number>()\n\n for (const fm of sessionFiles.values()) {\n for (const [file, entry] of fm) {\n if (entry.count <= 1) continue\n const extra = entry.count - 1\n totalDuplicates += extra\n if (entry.recent > 1) recentDuplicates += entry.recent - 1\n const name = basename(file)\n fileDupes.set(name, (fileDupes.get(name) ?? 0) + extra)\n }\n }\n\n if (totalDuplicates < MIN_DUPLICATE_READS_TO_FLAG) return null\n\n const hasRecentActivity = calls.some(c => c.recent)\n const trend = sessionTrend(recentDuplicates, totalDuplicates, dateRange, hasRecentActivity)\n if (trend === 'resolved') return null\n\n const worst = [...fileDupes.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, TOP_ITEMS_PREVIEW)\n .map(([name, n]) => `${name} (${n + 1}x)`)\n .join(', ')\n\n const tokensSaved = totalDuplicates * AVG_TOKENS_PER_READ\n\n return {\n title: 'Claude is re-reading the same files',\n explanation: `${totalDuplicates} redundant re-reads across sessions. Top repeats: ${worst}. Each re-read loads the same content into context again.`,\n impact: totalDuplicates > DUPLICATE_READS_HIGH_THRESHOLD ? 'high' : totalDuplicates > DUPLICATE_READS_MEDIUM_THRESHOLD ? 'medium' : 'low',\n tokensSaved,\n fix: {\n type: 'paste',\n label: 'Point Claude at exact locations in your prompt, for example:',\n text: 'In <file> lines <start>-<end>, look at the <function> function.',\n },\n trend,\n }\n}\n\nexport function detectUnusedMcp(\n calls: ToolCall[],\n projects: ProjectSummary[],\n projectCwds: Set<string>,\n): WasteFinding | null {\n const configured = loadMcpConfigs(projectCwds)\n if (configured.size === 0) return null\n\n const calledServers = new Set<string>()\n for (const call of calls) {\n if (!call.name.startsWith('mcp__')) continue\n const seg = call.name.split('__')[1]\n if (seg) calledServers.add(seg)\n }\n for (const p of projects) {\n for (const s of p.sessions) {\n for (const server of Object.keys(s.mcpBreakdown)) calledServers.add(server)\n }\n }\n\n const now = Date.now()\n const unused: string[] = []\n for (const entry of configured.values()) {\n if (calledServers.has(entry.normalized)) continue\n if (entry.mtime > 0 && now - entry.mtime < MCP_NEW_CONFIG_GRACE_MS) continue\n unused.push(entry.original)\n }\n\n if (unused.length === 0) return null\n\n const totalSessions = projects.reduce((s, p) => s + p.sessions.length, 0)\n const schemaTokensPerSession = unused.length * TOOLS_PER_MCP_SERVER * TOKENS_PER_MCP_TOOL\n const tokensSaved = schemaTokensPerSession * Math.max(totalSessions, 1)\n\n return {\n title: `${unused.length} MCP server${unused.length > 1 ? 's' : ''} configured but never used`,\n explanation: `Never called in this period: ${unused.join(', ')}. Each server loads ~${TOOLS_PER_MCP_SERVER * TOKENS_PER_MCP_TOOL} tokens of tool schema into every session.`,\n impact: unused.length >= UNUSED_MCP_HIGH_THRESHOLD ? 'high' : 'medium',\n tokensSaved,\n fix: {\n type: 'command',\n label: `Remove unused server${unused.length > 1 ? 's' : ''}:`,\n text: unused.map(s => `claude mcp remove ${s}`).join('\\n'),\n },\n }\n}\n\nfunction expandImports(filePath: string, seen: Set<string>, depth: number): { totalLines: number; importedFiles: number } {\n if (depth > MAX_IMPORT_DEPTH || seen.has(filePath)) return { totalLines: 0, importedFiles: 0 }\n seen.add(filePath)\n const content = readSessionFileSync(filePath)\n if (content === null) return { totalLines: 0, importedFiles: 0 }\n\n let totalLines = content.split('\\n').length\n let importedFiles = 0\n const dir = join(filePath, '..')\n\n IMPORT_PATTERN.lastIndex = 0\n for (const match of content.matchAll(IMPORT_PATTERN)) {\n const rawPath = match[1]\n if (!rawPath) continue\n const resolved = rawPath.startsWith('/') ? rawPath : join(dir, rawPath)\n if (!existsSync(resolved)) continue\n const nested = expandImports(resolved, seen, depth + 1)\n totalLines += nested.totalLines\n importedFiles += 1 + nested.importedFiles\n }\n\n return { totalLines, importedFiles }\n}\n\nexport function detectBloatedClaudeMd(projectCwds: Set<string>): WasteFinding | null {\n const bloated: { path: string; expandedLines: number; imports: number }[] = []\n\n for (const cwd of projectCwds) {\n for (const name of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n const fullPath = join(cwd, name)\n if (!existsSync(fullPath)) continue\n const { totalLines, importedFiles } = expandImports(fullPath, new Set(), 0)\n if (totalLines > CLAUDEMD_HEALTHY_LINES) {\n bloated.push({ path: `${shortHomePath(cwd)}/${name}`, expandedLines: totalLines, imports: importedFiles })\n }\n }\n }\n\n if (bloated.length === 0) return null\n\n const sorted = bloated.sort((a, b) => b.expandedLines - a.expandedLines)\n const worst = sorted[0]\n const totalExtraLines = sorted.reduce((s, b) => s + (b.expandedLines - CLAUDEMD_HEALTHY_LINES), 0)\n const tokensSaved = totalExtraLines * CLAUDEMD_TOKENS_PER_LINE\n\n const list = sorted.slice(0, TOP_ITEMS_PREVIEW).map(b => {\n const importNote = b.imports > 0 ? ` with ${b.imports} @-import${b.imports > 1 ? 's' : ''}` : ''\n return `${b.path} (${b.expandedLines} lines${importNote})`\n }).join(', ')\n\n return {\n title: `Your CLAUDE.md is too long`,\n explanation: `${list}. CLAUDE.md plus all @-imported files load into every API call. Trimming below ${CLAUDEMD_HEALTHY_LINES} lines saves ~${formatTokens(tokensSaved)} tokens per call.`,\n impact: worst.expandedLines > CLAUDEMD_HIGH_THRESHOLD_LINES ? 'high' : 'medium',\n tokensSaved,\n fix: {\n type: 'paste',\n label: 'Ask Claude to trim it:',\n text: `Review CLAUDE.md and all @-imported files. Cut total expanded content to under ${CLAUDEMD_HEALTHY_LINES} lines. Remove anything Claude can figure out from the code itself. Keep only rules, gotchas, and non-obvious conventions.`,\n },\n }\n}\n\nconst READ_TOOL_NAMES = new Set(['Read', 'Grep', 'Glob', 'FileReadTool', 'GrepTool', 'GlobTool'])\nconst EDIT_TOOL_NAMES = new Set(['Edit', 'Write', 'FileEditTool', 'FileWriteTool', 'NotebookEdit'])\n\nexport function detectLowReadEditRatio(calls: ToolCall[]): WasteFinding | null {\n let reads = 0\n let edits = 0\n let recentEdits = 0\n let recentReads = 0\n for (const call of calls) {\n if (READ_TOOL_NAMES.has(call.name)) {\n reads++\n if (call.recent) recentReads++\n } else if (EDIT_TOOL_NAMES.has(call.name)) {\n edits++\n if (call.recent) recentEdits++\n }\n }\n\n if (edits < MIN_EDITS_FOR_RATIO) return null\n const ratio = reads / edits\n if (ratio >= HEALTHY_READ_EDIT_RATIO) return null\n\n const impact: Impact = ratio < LOW_RATIO_HIGH_THRESHOLD ? 'high' : ratio < LOW_RATIO_MEDIUM_THRESHOLD ? 'medium' : 'low'\n const extraReadsNeeded = Math.max(Math.round(edits * HEALTHY_READ_EDIT_RATIO) - reads, 0)\n const tokensSaved = extraReadsNeeded * AVG_TOKENS_PER_READ\n\n let trend: Trend | 'resolved' = 'active'\n if (recentEdits >= MIN_EDITS_FOR_RATIO) {\n const recentRatio = recentReads / recentEdits\n if (recentRatio >= HEALTHY_READ_EDIT_RATIO) trend = 'resolved'\n else if (recentRatio > ratio * (1 / IMPROVING_THRESHOLD)) trend = 'improving'\n }\n if (trend === 'resolved') return null\n\n return {\n title: 'Claude edits more than it reads',\n explanation: `Claude made ${reads} reads and ${edits} edits (ratio ${ratio.toFixed(1)}:1). A healthy ratio is ${HEALTHY_READ_EDIT_RATIO}+ reads per edit. Editing without reading leads to retries and wasted tokens.`,\n impact,\n tokensSaved,\n fix: {\n type: 'paste',\n label: 'Add to your CLAUDE.md:',\n text: 'Before editing any file, read it first. Before modifying a function, grep for all callers. Research before you edit.',\n },\n trend,\n }\n}\n\nconst DEFAULT_CACHE_BASELINE_TOKENS = 50_000\nconst CACHE_BASELINE_QUANTILE = 0.25\nconst CACHE_BLOAT_MULTIPLIER = 1.4\nconst CACHE_VERSION_MIN_SAMPLES = 5\nconst CACHE_VERSION_DIFF_THRESHOLD = 10_000\n\nfunction computeBudgetAwareCacheBaseline(projects: ProjectSummary[]): number {\n const sessions = projects.flatMap(p => p.sessions)\n if (sessions.length === 0) return DEFAULT_CACHE_BASELINE_TOKENS\n const cacheWrites = sessions.map(s => s.totalCacheWriteTokens).filter(n => n > 0)\n if (cacheWrites.length < MIN_API_CALLS_FOR_CACHE) return DEFAULT_CACHE_BASELINE_TOKENS\n const sorted = cacheWrites.sort((a, b) => a - b)\n return sorted[Math.floor(sorted.length * CACHE_BASELINE_QUANTILE)] || DEFAULT_CACHE_BASELINE_TOKENS\n}\n\nexport function detectCacheBloat(apiCalls: ApiCallMeta[], projects: ProjectSummary[], dateRange?: DateRange): WasteFinding | null {\n if (apiCalls.length < MIN_API_CALLS_FOR_CACHE) return null\n\n const sorted = apiCalls.map(c => c.cacheCreationTokens).sort((a, b) => a - b)\n const median = sorted[Math.floor(sorted.length / 2)]\n const baseline = computeBudgetAwareCacheBaseline(projects)\n const bloatThreshold = baseline * CACHE_BLOAT_MULTIPLIER\n\n if (median < bloatThreshold) return null\n\n const recentCalls = apiCalls.filter(c => c.recent)\n const totalBloated = apiCalls.filter(c => c.cacheCreationTokens > bloatThreshold).length\n const recentBloated = recentCalls.filter(c => c.cacheCreationTokens > bloatThreshold).length\n const trend = sessionTrend(recentBloated, totalBloated, dateRange, recentCalls.length > 0)\n if (trend === 'resolved') return null\n\n const versionCounts = new Map<string, { total: number; count: number }>()\n for (const call of apiCalls) {\n if (!call.version) continue\n const entry = versionCounts.get(call.version) ?? { total: 0, count: 0 }\n entry.total += call.cacheCreationTokens\n entry.count++\n versionCounts.set(call.version, entry)\n }\n const versionAvgs = [...versionCounts.entries()]\n .filter(([, d]) => d.count >= CACHE_VERSION_MIN_SAMPLES)\n .map(([v, d]) => ({ version: v, avg: Math.round(d.total / d.count) }))\n .sort((a, b) => b.avg - a.avg)\n\n const excess = median - baseline\n const tokensSaved = excess * apiCalls.length\n\n let versionNote = ''\n if (versionAvgs.length >= 2) {\n const [high, ...rest] = versionAvgs\n const low = rest[rest.length - 1]\n if (high.avg - low.avg > CACHE_VERSION_DIFF_THRESHOLD) {\n versionNote = ` Version ${high.version} averages ${formatTokens(high.avg)} vs ${low.version} at ${formatTokens(low.avg)}.`\n }\n }\n\n return {\n title: 'Session warmup is unusually large',\n explanation: `Median cache_creation per call is ${formatTokens(median)} tokens, about ${formatTokens(excess)} above your baseline of ${formatTokens(baseline)}.${versionNote}`,\n impact: excess > CACHE_EXCESS_HIGH_THRESHOLD ? 'high' : 'medium',\n tokensSaved,\n fix: {\n type: 'paste',\n label: 'Check for recent Claude Code updates or heavy MCP/skill additions. As a workaround (not officially supported):',\n text: 'export ANTHROPIC_CUSTOM_HEADERS=\\'User-Agent: claude-cli/2.1.98 (external, sdk-cli)\\'',\n },\n trend,\n }\n}\n\nasync function listMarkdownFiles(dir: string): Promise<string[]> {\n if (!existsSync(dir)) return []\n try {\n const entries = await readdir(dir)\n return entries.filter(e => e.endsWith('.md')).map(e => e.replace(/\\.md$/, ''))\n } catch { return [] }\n}\n\nasync function listSkillDirs(dir: string): Promise<string[]> {\n if (!existsSync(dir)) return []\n try {\n const entries = await readdir(dir)\n const names: string[] = []\n for (const entry of entries) {\n if (existsSync(join(dir, entry, 'SKILL.md'))) names.push(entry)\n }\n return names\n } catch { return [] }\n}\n\nexport async function detectGhostAgents(calls: ToolCall[]): Promise<WasteFinding | null> {\n const defined = await listMarkdownFiles(join(homedir(), '.claude', 'agents'))\n if (defined.length === 0) return null\n\n const invoked = new Set<string>()\n for (const call of calls) {\n if (call.name !== 'Agent' && call.name !== 'Task') continue\n const subType = call.input.subagent_type as string | undefined\n if (subType) invoked.add(subType)\n }\n\n const ghosts = defined.filter(name => !invoked.has(name))\n if (ghosts.length === 0) return null\n\n const tokensSaved = ghosts.length * TOKENS_PER_AGENT_DEF\n const list = ghosts.slice(0, GHOST_NAMES_PREVIEW).join(', ') + (ghosts.length > GHOST_NAMES_PREVIEW ? `, +${ghosts.length - GHOST_NAMES_PREVIEW} more` : '')\n\n return {\n title: `${ghosts.length} custom agent${ghosts.length > 1 ? 's' : ''} you never use`,\n explanation: `Defined in ~/.claude/agents/ but never invoked in this period: ${list}. Each adds ~${TOKENS_PER_AGENT_DEF} tokens to the Task tool schema on every session.`,\n impact: ghosts.length >= GHOST_AGENTS_HIGH_THRESHOLD ? 'high' : ghosts.length >= GHOST_AGENTS_MEDIUM_THRESHOLD ? 'medium' : 'low',\n tokensSaved,\n fix: {\n type: 'command',\n label: `Archive unused agent${ghosts.length > 1 ? 's' : ''}:`,\n text: ghosts.slice(0, GHOST_CLEANUP_COMMANDS_LIMIT).map(name => `mv ~/.claude/agents/${name}.md ~/.claude/agents/.archived/`).join('\\n'),\n },\n }\n}\n\nexport async function detectGhostSkills(calls: ToolCall[]): Promise<WasteFinding | null> {\n const defined = await listSkillDirs(join(homedir(), '.claude', 'skills'))\n if (defined.length === 0) return null\n\n const invoked = new Set<string>()\n for (const call of calls) {\n if (call.name !== 'Skill') continue\n const skillName = (call.input.skill as string) || (call.input.name as string)\n if (skillName) invoked.add(skillName)\n }\n\n const ghosts = defined.filter(name => !invoked.has(name))\n if (ghosts.length === 0) return null\n\n const tokensSaved = ghosts.length * TOKENS_PER_SKILL_DEF\n const list = ghosts.slice(0, GHOST_NAMES_PREVIEW).join(', ') + (ghosts.length > GHOST_NAMES_PREVIEW ? `, +${ghosts.length - GHOST_NAMES_PREVIEW} more` : '')\n\n return {\n title: `${ghosts.length} skill${ghosts.length > 1 ? 's' : ''} you never use`,\n explanation: `In ~/.claude/skills/ but not invoked this period: ${list}. Each adds ~${TOKENS_PER_SKILL_DEF} tokens of metadata to every session.`,\n impact: ghosts.length >= GHOST_SKILLS_HIGH_THRESHOLD ? 'high' : ghosts.length >= GHOST_SKILLS_MEDIUM_THRESHOLD ? 'medium' : 'low',\n tokensSaved,\n fix: {\n type: 'command',\n label: `Archive unused skill${ghosts.length > 1 ? 's' : ''}:`,\n text: ghosts.slice(0, GHOST_CLEANUP_COMMANDS_LIMIT).map(name => `mv ~/.claude/skills/${name} ~/.claude/skills/.archived/`).join('\\n'),\n },\n }\n}\n\nexport async function detectGhostCommands(userMessages: string[]): Promise<WasteFinding | null> {\n const defined = await listMarkdownFiles(join(homedir(), '.claude', 'commands'))\n if (defined.length === 0) return null\n\n const invoked = new Set<string>()\n for (const msg of userMessages) {\n COMMAND_PATTERN.lastIndex = 0\n for (const m of msg.matchAll(COMMAND_PATTERN)) {\n const name = (m[1] || m[2] || '').trim()\n if (name) invoked.add(name)\n }\n }\n\n const ghosts = defined.filter(name => !invoked.has(name))\n if (ghosts.length === 0) return null\n\n const tokensSaved = ghosts.length * TOKENS_PER_COMMAND_DEF\n const list = ghosts.slice(0, GHOST_NAMES_PREVIEW).join(', ') + (ghosts.length > GHOST_NAMES_PREVIEW ? `, +${ghosts.length - GHOST_NAMES_PREVIEW} more` : '')\n\n return {\n title: `${ghosts.length} slash command${ghosts.length > 1 ? 's' : ''} you never use`,\n explanation: `In ~/.claude/commands/ but not referenced this period: ${list}. Each adds ~${TOKENS_PER_COMMAND_DEF} tokens of definition per session.`,\n impact: ghosts.length >= GHOST_COMMANDS_MEDIUM_THRESHOLD ? 'medium' : 'low',\n tokensSaved,\n fix: {\n type: 'command',\n label: `Archive unused command${ghosts.length > 1 ? 's' : ''}:`,\n text: ghosts.slice(0, GHOST_CLEANUP_COMMANDS_LIMIT).map(name => `mv ~/.claude/commands/${name}.md ~/.claude/commands/.archived/`).join('\\n'),\n },\n }\n}\n\nfunction readShellProfileLimit(): number | null {\n for (const profile of SHELL_PROFILES) {\n const path = join(homedir(), profile)\n if (!existsSync(path)) continue\n const content = readSessionFileSync(path)\n if (content === null) continue\n const match = content.match(/^\\s*export\\s+BASH_MAX_OUTPUT_LENGTH\\s*=\\s*['\"]?(\\d+)['\"]?/m)\n if (match) return parseInt(match[1], 10)\n }\n return null\n}\n\nexport function detectBashBloat(): WasteFinding | null {\n const profileLimit = readShellProfileLimit()\n const envLimit = process.env['BASH_MAX_OUTPUT_LENGTH']\n const configured = profileLimit ?? (envLimit ? parseInt(envLimit, 10) : null)\n\n if (configured !== null && configured <= BASH_RECOMMENDED_LIMIT) return null\n\n const limit = configured ?? BASH_DEFAULT_LIMIT\n const extraChars = limit - BASH_RECOMMENDED_LIMIT\n const tokensSaved = Math.round(extraChars * BASH_TOKENS_PER_CHAR)\n\n return {\n title: 'Shrink bash output limit',\n explanation: `Your bash output cap is ${(limit / 1000).toFixed(0)}K chars (${configured ? 'configured' : 'default'}). Most output fits in ${(BASH_RECOMMENDED_LIMIT / 1000).toFixed(0)}K. The extra ~${formatTokens(tokensSaved)} tokens per bash call is trailing noise.`,\n impact: 'medium',\n tokensSaved,\n fix: {\n type: 'paste',\n label: 'Add to ~/.zshrc or ~/.bashrc:',\n text: `export BASH_MAX_OUTPUT_LENGTH=${BASH_RECOMMENDED_LIMIT}`,\n },\n }\n}\n\n// ============================================================================\n// Scoring\n// ============================================================================\n\nconst HEALTH_WEIGHTS: Record<Impact, number> = {\n high: HEALTH_WEIGHT_HIGH,\n medium: HEALTH_WEIGHT_MEDIUM,\n low: HEALTH_WEIGHT_LOW,\n}\n\nexport function computeHealth(findings: WasteFinding[]): { score: number; grade: HealthGrade } {\n if (findings.length === 0) return { score: 100, grade: 'A' }\n let penalty = 0\n for (const f of findings) penalty += HEALTH_WEIGHTS[f.impact] ?? 0\n const score = Math.max(0, 100 - Math.min(HEALTH_MAX_PENALTY, penalty))\n const grade: HealthGrade =\n score >= GRADE_A_MIN ? 'A' :\n score >= GRADE_B_MIN ? 'B' :\n score >= GRADE_C_MIN ? 'C' :\n score >= GRADE_D_MIN ? 'D' : 'F'\n return { score, grade }\n}\n\nconst URGENCY_WEIGHTS: Record<Impact, number> = { high: 1, medium: 0.5, low: 0.2 }\n\nfunction urgencyScore(f: WasteFinding): number {\n const normalizedTokens = Math.min(1, f.tokensSaved / URGENCY_TOKEN_NORMALIZE)\n return URGENCY_WEIGHTS[f.impact] * URGENCY_IMPACT_WEIGHT + normalizedTokens * URGENCY_TOKEN_WEIGHT\n}\n\ntype TrendInputs = {\n recentCount: number\n recentWindowMs: number\n baselineCount: number\n baselineWindowMs: number\n hasRecentActivity: boolean\n}\n\nexport function computeTrend(inputs: TrendInputs): Trend | 'resolved' {\n const { recentCount, recentWindowMs, baselineCount, baselineWindowMs, hasRecentActivity } = inputs\n if (baselineCount === 0) return 'active'\n if (recentCount === 0 && hasRecentActivity) return 'resolved'\n if (!hasRecentActivity) return 'active'\n const baselineRate = baselineCount / baselineWindowMs\n const recentRate = recentCount / Math.max(recentWindowMs, 1)\n if (recentRate < baselineRate * IMPROVING_THRESHOLD) return 'improving'\n return 'active'\n}\n\nfunction sessionTrend(\n recentItemCount: number,\n totalItemCount: number,\n dateRange: DateRange | undefined,\n hasRecentActivity: boolean,\n): Trend | 'resolved' {\n const now = Date.now()\n const baselineCount = totalItemCount - recentItemCount\n const periodStart = dateRange ? dateRange.start.getTime() : now - DEFAULT_TREND_PERIOD_MS\n const recentStart = now - RECENT_WINDOW_MS\n const baselineWindowMs = Math.max(recentStart - periodStart, 1)\n return computeTrend({\n recentCount: recentItemCount,\n recentWindowMs: RECENT_WINDOW_MS,\n baselineCount,\n baselineWindowMs,\n hasRecentActivity,\n })\n}\n\n// ============================================================================\n// Cost estimation\n// ============================================================================\n\nconst INPUT_COST_RATIO = 0.7\nconst DEFAULT_COST_PER_TOKEN = 0\n\nfunction computeInputCostRate(projects: ProjectSummary[]): number {\n const sessions = projects.flatMap(p => p.sessions)\n const totalCost = sessions.reduce((s, sess) => s + sess.totalCostUSD, 0)\n const totalTokens = sessions.reduce((s, sess) =>\n s + sess.totalInputTokens + sess.totalCacheReadTokens + sess.totalCacheWriteTokens, 0)\n if (totalTokens === 0 || totalCost === 0) return DEFAULT_COST_PER_TOKEN\n return (totalCost * INPUT_COST_RATIO) / totalTokens\n}\n\n// ============================================================================\n// Main entry points\n// ============================================================================\n\ntype CacheEntry = { data: OptimizeResult; ts: number }\nconst resultCache = new Map<string, CacheEntry>()\n\nfunction cacheKey(projects: ProjectSummary[], dateRange: DateRange | undefined): string {\n const dr = dateRange ? `${dateRange.start.getTime()}-${dateRange.end.getTime()}` : 'all'\n const fingerprint = projects.length + ':' + projects.reduce((s, p) => s + p.totalApiCalls, 0)\n return `${dr}:${fingerprint}`\n}\n\nexport async function scanAndDetect(\n projects: ProjectSummary[],\n dateRange?: DateRange,\n): Promise<OptimizeResult> {\n if (projects.length === 0) {\n return { findings: [], costRate: 0, healthScore: 100, healthGrade: 'A' }\n }\n\n const key = cacheKey(projects, dateRange)\n const cached = resultCache.get(key)\n if (cached && Date.now() - cached.ts < RESULT_CACHE_TTL_MS) return cached.data\n\n const costRate = computeInputCostRate(projects)\n const { toolCalls, projectCwds, apiCalls, userMessages } = await scanSessions(dateRange)\n\n const findings: WasteFinding[] = []\n const syncDetectors: Array<() => WasteFinding | null> = [\n () => detectCacheBloat(apiCalls, projects, dateRange),\n () => detectLowReadEditRatio(toolCalls),\n () => detectJunkReads(toolCalls, dateRange),\n () => detectDuplicateReads(toolCalls, dateRange),\n () => detectUnusedMcp(toolCalls, projects, projectCwds),\n () => detectBloatedClaudeMd(projectCwds),\n () => detectBashBloat(),\n ]\n for (const detect of syncDetectors) {\n const finding = detect()\n if (finding) findings.push(finding)\n }\n\n const ghostResults = await Promise.all([\n detectGhostAgents(toolCalls),\n detectGhostSkills(toolCalls),\n detectGhostCommands(userMessages),\n ])\n for (const f of ghostResults) if (f) findings.push(f)\n\n findings.sort((a, b) => urgencyScore(b) - urgencyScore(a))\n const { score, grade } = computeHealth(findings)\n const result: OptimizeResult = { findings, costRate, healthScore: score, healthGrade: grade }\n resultCache.set(key, { data: result, ts: Date.now() })\n return result\n}\n\n// ============================================================================\n// CLI rendering\n// ============================================================================\n\nconst PANEL_WIDTH = 62\nconst SEP = '\\u2500'\nconst IMPACT_COLORS: Record<Impact, string> = { high: RED, medium: ORANGE, low: DIM }\nconst GRADE_COLORS: Record<HealthGrade, string> = { A: GREEN, B: GREEN, C: GOLD, D: ORANGE, F: RED }\n\nfunction wrap(text: string, width: number, indent: string): string {\n const words = text.split(' ')\n const lines: string[] = []\n let current = ''\n for (const word of words) {\n if (current && current.length + word.length + 1 > width) {\n lines.push(indent + current)\n current = word\n } else {\n current = current ? current + ' ' + word : word\n }\n }\n if (current) lines.push(indent + current)\n return lines.join('\\n')\n}\n\nfunction renderFinding(n: number, f: WasteFinding, costRate: number): string[] {\n const lines: string[] = []\n const costSaved = f.tokensSaved * costRate\n const impactLabel = f.impact.charAt(0).toUpperCase() + f.impact.slice(1)\n const trendBadge = f.trend === 'improving' ? ' improving \\u2193 ' : ''\n const savings = `~${formatTokens(f.tokensSaved)} tokens (~${formatCost(costSaved)})`\n const titlePad = PANEL_WIDTH - f.title.length - impactLabel.length - trendBadge.length - 8\n const pad = titlePad > 0 ? ' ' + SEP.repeat(titlePad) + ' ' : ' '\n\n lines.push(chalk.hex(DIM)(` ${SEP}${SEP}${SEP} `) +\n chalk.bold(`${n}. ${f.title}`) +\n chalk.hex(DIM)(pad) +\n chalk.hex(IMPACT_COLORS[f.impact])(impactLabel) +\n (trendBadge ? chalk.hex(GREEN)(trendBadge) : '') +\n chalk.hex(DIM)(` ${SEP}${SEP}${SEP}`))\n lines.push('')\n lines.push(wrap(f.explanation, PANEL_WIDTH - 4, ' '))\n lines.push('')\n lines.push(chalk.hex(GOLD)(` Potential savings: ${savings}`))\n lines.push('')\n\n const a = f.fix\n if (a.type === 'file-content') {\n lines.push(chalk.hex(DIM)(` ${a.label}`))\n for (const line of a.content.split('\\n')) lines.push(chalk.hex(CYAN)(` ${line}`))\n } else if (a.type === 'command') {\n lines.push(chalk.hex(DIM)(` ${a.label}`))\n for (const line of a.text.split('\\n')) lines.push(chalk.hex(CYAN)(` ${line}`))\n } else {\n lines.push(chalk.hex(DIM)(` ${a.label}`))\n lines.push(chalk.hex(CYAN)(` ${a.text}`))\n }\n lines.push('')\n return lines\n}\n\nfunction renderOptimize(\n findings: WasteFinding[],\n costRate: number,\n periodLabel: string,\n periodCost: number,\n sessionCount: number,\n callCount: number,\n healthScore: number,\n healthGrade: HealthGrade,\n): string {\n const lines: string[] = []\n lines.push('')\n lines.push(` ${chalk.bold.hex(ORANGE)('Exe Watcher config health')}${chalk.dim(' ' + periodLabel)}`)\n lines.push(chalk.hex(DIM)(' ' + SEP.repeat(PANEL_WIDTH)))\n\n const issueSuffix = findings.length > 0 ? `, ${findings.length} issue${findings.length > 1 ? 's' : ''}` : ''\n lines.push(' ' + [\n `${sessionCount} sessions`,\n `${callCount.toLocaleString()} calls`,\n chalk.hex(GOLD)(formatCost(periodCost)),\n `Health: ${chalk.bold.hex(GRADE_COLORS[healthGrade])(healthGrade)}${chalk.dim(` (${healthScore}/100${issueSuffix})`)}`,\n ].join(chalk.hex(DIM)(' ')))\n lines.push('')\n\n if (findings.length === 0) {\n lines.push(chalk.hex(GREEN)(' Nothing to fix. Your setup is lean.'))\n lines.push('')\n lines.push(chalk.dim(' Exe Watcher optimize scans your Claude Code sessions and config for'))\n lines.push(chalk.dim(' token waste: junk directory reads, duplicate file reads, unused'))\n lines.push(chalk.dim(' agents/skills/MCP servers, bloated CLAUDE.md, and more.'))\n lines.push('')\n return lines.join('\\n')\n }\n\n const totalTokens = findings.reduce((s, f) => s + f.tokensSaved, 0)\n const totalCost = totalTokens * costRate\n const pctRaw = periodCost > 0 ? (totalCost / periodCost) * 100 : 0\n const pct = pctRaw >= 1 ? pctRaw.toFixed(0) : pctRaw.toFixed(1)\n\n const costText = costRate > 0 ? ` (~${formatCost(totalCost)}, ~${pct}% of spend)` : ''\n lines.push(chalk.hex(GREEN)(` Potential savings: ~${formatTokens(totalTokens)} tokens${costText}`))\n lines.push('')\n\n for (let i = 0; i < findings.length; i++) {\n lines.push(...renderFinding(i + 1, findings[i], costRate))\n }\n\n lines.push(chalk.hex(DIM)(' ' + SEP.repeat(PANEL_WIDTH)))\n lines.push(chalk.dim(' Estimates only.'))\n lines.push('')\n return lines.join('\\n')\n}\n\nexport async function runOptimize(\n projects: ProjectSummary[],\n periodLabel: string,\n dateRange?: DateRange,\n): Promise<void> {\n if (projects.length === 0) {\n console.log(chalk.dim('\\n No usage data found for this period.\\n'))\n return\n }\n\n process.stderr.write(chalk.dim(' Analyzing your sessions...\\n'))\n\n const { findings, costRate, healthScore, healthGrade } = await scanAndDetect(projects, dateRange)\n const sessions = projects.flatMap(p => p.sessions)\n const periodCost = projects.reduce((s, p) => s + p.totalCostUSD, 0)\n const callCount = projects.reduce((s, p) => s + p.totalApiCalls, 0)\n\n const output = renderOptimize(findings, costRate, periodLabel, periodCost, sessions.length, callCount, healthScore, healthGrade)\n console.log(output)\n}\n","import { readdir } from 'fs/promises'\nimport { existsSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\n\nimport { readSessionFile } from './fs-utils.js'\n\nconst CHARS_PER_TOKEN = 4\nconst SYSTEM_BASE_TOKENS = 10400\nconst TOOL_TOKENS_OVERHEAD = 400\nconst SKILL_FRONTMATTER_TOKENS = 80\n\nexport type ContextBudget = {\n systemBase: number\n mcpTools: { count: number; tokens: number }\n skills: { count: number; tokens: number }\n memory: { count: number; tokens: number; files: Array<{ name: string; tokens: number }> }\n total: number\n modelContext: number\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN)\n}\n\nasync function readConfigFile(path: string): Promise<Record<string, unknown> | null> {\n if (!existsSync(path)) return null\n const raw = await readSessionFile(path)\n if (raw === null) return null\n try { return JSON.parse(raw) } catch { return null }\n}\n\nasync function countMcpTools(projectPath?: string): Promise<number> {\n const home = homedir()\n const configPaths = [\n join(home, '.claude', 'settings.json'),\n join(home, '.claude', 'settings.local.json'),\n ]\n if (projectPath) {\n configPaths.push(join(projectPath, '.mcp.json'))\n configPaths.push(join(projectPath, '.claude', 'settings.json'))\n configPaths.push(join(projectPath, '.claude', 'settings.local.json'))\n }\n\n const servers = new Set<string>()\n let toolCount = 0\n\n for (const p of configPaths) {\n const config = await readConfigFile(p)\n if (!config) continue\n const mcpServers = (config.mcpServers ?? {}) as Record<string, unknown>\n for (const name of Object.keys(mcpServers)) {\n if (servers.has(name)) continue\n servers.add(name)\n toolCount += 5\n }\n }\n\n return toolCount\n}\n\nasync function countSkills(projectPath?: string): Promise<number> {\n const dirs = [join(homedir(), '.claude', 'skills')]\n if (projectPath) dirs.push(join(projectPath, '.claude', 'skills'))\n\n let count = 0\n for (const dir of dirs) {\n if (!existsSync(dir)) continue\n try {\n const entries = await readdir(dir)\n for (const entry of entries) {\n const skillFile = join(dir, entry, 'SKILL.md')\n if (existsSync(skillFile)) count++\n }\n } catch { continue }\n }\n\n return count\n}\n\nasync function scanMemoryFiles(projectPath?: string): Promise<Array<{ name: string; tokens: number }>> {\n const home = homedir()\n const files: Array<{ name: string; tokens: number }> = []\n const paths: Array<{ path: string; name: string }> = [\n { path: join(home, '.claude', 'CLAUDE.md'), name: '~/.claude/CLAUDE.md' },\n ]\n\n if (projectPath) {\n paths.push({ path: join(projectPath, 'CLAUDE.md'), name: 'CLAUDE.md' })\n paths.push({ path: join(projectPath, '.claude', 'CLAUDE.md'), name: '.claude/CLAUDE.md' })\n paths.push({ path: join(projectPath, 'CLAUDE.local.md'), name: 'CLAUDE.local.md' })\n }\n\n for (const { path, name } of paths) {\n if (!existsSync(path)) continue\n const content = await readSessionFile(path)\n if (content === null) continue\n files.push({ name, tokens: estimateTokens(content) })\n }\n\n return files\n}\n\nexport async function estimateContextBudget(projectPath?: string, modelContext = 1_000_000): Promise<ContextBudget> {\n const mcpToolCount = await countMcpTools(projectPath)\n const skillCount = await countSkills(projectPath)\n const memoryFiles = await scanMemoryFiles(projectPath)\n\n const mcpTokens = mcpToolCount * TOOL_TOKENS_OVERHEAD\n const skillTokens = skillCount * SKILL_FRONTMATTER_TOKENS\n const memoryTokens = memoryFiles.reduce((s, f) => s + f.tokens, 0)\n const total = SYSTEM_BASE_TOKENS + mcpTokens + skillTokens + memoryTokens\n\n return {\n systemBase: SYSTEM_BASE_TOKENS,\n mcpTools: { count: mcpToolCount, tokens: mcpTokens },\n skills: { count: skillCount, tokens: skillTokens },\n memory: { count: memoryFiles.length, tokens: memoryTokens, files: memoryFiles },\n total,\n modelContext,\n }\n}\n\nexport async function estimateBudgetsByProject(projectPaths: Map<string, string>): Promise<Map<string, ContextBudget>> {\n const results = new Map<string, ContextBudget>()\n for (const [project, cwd] of projectPaths) {\n const budget = await estimateContextBudget(cwd)\n results.set(project, budget)\n }\n return results\n}\n\nexport async function discoverProjectCwd(sessionDir: string): Promise<string | null> {\n let files: string[]\n try {\n files = (await readdir(sessionDir)).filter(f => f.endsWith('.jsonl'))\n } catch { return null }\n if (files.length === 0) return null\n const content = await readSessionFile(join(sessionDir, files[0]))\n if (content === null) return null\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue\n try {\n const entry = JSON.parse(line)\n if (entry.cwd && typeof entry.cwd === 'string') return entry.cwd\n } catch { continue }\n }\n return null\n}\n","import React, { useState, useEffect, useRef } from 'react'\nimport { render, Box, Text, useInput, useApp, useStdout } from 'ink'\n\nimport type { ModelStats, ComparisonRow, CategoryComparison, WorkingStyleRow } from './compare-stats.js'\nimport { aggregateModelStats, computeComparison, computeCategoryComparison, computeWorkingStyle, scanSelfCorrections } from './compare-stats.js'\nimport { formatCost } from './format.js'\nimport { parseAllSessions } from './parser.js'\nimport { getAllProviders } from './providers/index.js'\nimport type { ProjectSummary, DateRange } from './types.js'\n\nconst ORANGE = '#F59E0B'\nconst GREEN = '#16A34A'\nconst DIM = '#888888'\nconst GOLD = '#F5D76E'\nconst BAR_A = '#6B4C9A'\nconst BAR_B = '#F5D76E'\nconst LOW_DATA_THRESHOLD = 20\nconst LABEL_WIDTH = 20\nconst VALUE_WIDTH = 14\nconst MODEL_NAME_COL = 24\nconst BAR_MAX_WIDTH = 30\nconst MIN_WIDE = 90\nconst PANEL_CHROME = 4\nconst MS_PER_DAY = 24 * 60 * 60 * 1000\nconst FULL_BLOCK = '\\u2588'\n\nfunction formatValue(value: number | null, fmt: ComparisonRow['formatFn']): string {\n if (value === null) return '-'\n switch (fmt) {\n case 'cost': return formatCost(value)\n case 'number': return Math.round(value).toLocaleString()\n case 'percent': return `${value.toFixed(1)}%`\n case 'decimal': return value.toFixed(2)\n }\n}\n\nfunction shortName(model: string): string {\n return model.replace(/^claude-/, '').replace(/-\\d{8}$/, '')\n}\n\nfunction daysOfData(first: string, last: string): number {\n if (!first || !last) return 0\n const ms = new Date(last).getTime() - new Date(first).getTime()\n return Math.max(1, Math.ceil(ms / MS_PER_DAY))\n}\n\nfunction barWidth(rate: number): number {\n return Math.round((rate / 100) * BAR_MAX_WIDTH)\n}\n\ntype ModelSelectorProps = {\n models: ModelStats[]\n onSelect: (a: ModelStats, b: ModelStats) => void\n onBack: () => void\n}\n\nfunction ModelSelector({ models, onSelect, onBack }: ModelSelectorProps) {\n const { exit } = useApp()\n const [cursor, setCursor] = useState(0)\n const [selected, setSelected] = useState<Set<number>>(new Set())\n\n useInput((input, key) => {\n if (input === 'q') { exit(); return }\n if (key.escape) { onBack(); return }\n\n if (key.upArrow) {\n setCursor(c => (c - 1 + models.length) % models.length)\n return\n }\n if (key.downArrow) {\n setCursor(c => (c + 1) % models.length)\n return\n }\n\n if (input === ' ') {\n setSelected(prev => {\n const next = new Set(prev)\n if (next.has(cursor)) {\n next.delete(cursor)\n } else if (next.size < 2) {\n next.add(cursor)\n }\n return next\n })\n return\n }\n\n if (key.return && selected.size === 2) {\n const indices = [...selected].sort((a, b) => a - b)\n onSelect(models[indices[0]!]!, models[indices[1]!]!)\n }\n })\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1}>\n <Text bold color={ORANGE}>Model Comparison</Text>\n <Text> </Text>\n <Text color={DIM}>Select two models to compare:</Text>\n <Text> </Text>\n {models.map((m, i) => {\n const isCursor = i === cursor\n const isSelected = selected.has(i)\n const lowData = m.calls < LOW_DATA_THRESHOLD\n const prefix = isCursor ? '> ' : ' '\n return (\n <Text key={m.model}>\n <Text color={isCursor ? ORANGE : undefined}>{prefix}</Text>\n <Text bold={isSelected} color={isSelected ? GREEN : undefined}>\n {shortName(m.model).padEnd(MODEL_NAME_COL)}\n </Text>\n <Text>{m.calls.toLocaleString().padStart(8)} calls</Text>\n <Text color={GOLD}>{formatCost(m.cost).padStart(10)}</Text>\n {isSelected && <Text color={GREEN}> [selected]</Text>}\n {lowData && <Text color={DIM}> low data</Text>}\n </Text>\n )\n })}\n </Box>\n <Text> </Text>\n <Text>\n <Text color={ORANGE} bold>[space]</Text><Text dimColor> select </Text>\n <Text color={ORANGE} bold>[enter]</Text><Text dimColor> compare </Text>\n <Text color={ORANGE} bold>{'<>'}</Text><Text dimColor> switch period </Text>\n <Text color={ORANGE} bold>[esc]</Text><Text dimColor> back </Text>\n <Text color={ORANGE} bold>[q]</Text><Text dimColor> quit</Text>\n </Text>\n </Box>\n )\n}\n\ntype ComparisonResultsProps = {\n modelA: ModelStats\n modelB: ModelStats\n rows: ComparisonRow[]\n categories: CategoryComparison[]\n workingStyle: WorkingStyleRow[]\n onBack: () => void\n}\n\nfunction MetricPanel({ title, rows, nameA, nameB, pw }: { title: string; rows: ComparisonRow[]; nameA: string; nameB: string; pw: number }) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1} width={pw}>\n <Text bold color={ORANGE}>{title}</Text>\n <Text>\n <Text>{''.padEnd(LABEL_WIDTH)}</Text>\n <Text bold>{nameA.padStart(VALUE_WIDTH)}</Text>\n <Text bold>{nameB.padStart(VALUE_WIDTH)}</Text>\n </Text>\n {rows.map(row => {\n const fmtA = formatValue(row.valueA, row.formatFn)\n const fmtB = formatValue(row.valueB, row.formatFn)\n return (\n <Text key={row.label}>\n <Text color={DIM}>{row.label.padEnd(LABEL_WIDTH)}</Text>\n <Text color={row.winner === 'a' ? GREEN : undefined}>{fmtA.padStart(VALUE_WIDTH)}</Text>\n <Text color={row.winner === 'b' ? GREEN : undefined}>{fmtB.padStart(VALUE_WIDTH)}</Text>\n </Text>\n )\n })}\n </Box>\n )\n}\n\nfunction ContextPanel({ title, rows, nameA, nameB, pw, lowDataWarning }: { title: string; rows: { label: string; valueA: string; valueB: string }[]; nameA: string; nameB: string; pw: number; lowDataWarning?: string }) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1} width={pw}>\n <Text bold color={ORANGE}>{title}</Text>\n <Text>\n <Text>{''.padEnd(LABEL_WIDTH)}</Text>\n <Text bold>{nameA.padStart(VALUE_WIDTH)}</Text>\n <Text bold>{nameB.padStart(VALUE_WIDTH)}</Text>\n </Text>\n {rows.map(row => (\n <Text key={row.label}>\n <Text color={DIM}>{row.label.padEnd(LABEL_WIDTH)}</Text>\n <Text color={DIM}>{row.valueA.padStart(VALUE_WIDTH)}</Text>\n <Text color={DIM}>{row.valueB.padStart(VALUE_WIDTH)}</Text>\n </Text>\n ))}\n {lowDataWarning && <Text color={GOLD}>{lowDataWarning}</Text>}\n </Box>\n )\n}\n\nfunction ComparisonResults({ modelA, modelB, rows, categories, workingStyle, onBack }: ComparisonResultsProps) {\n const { exit } = useApp()\n const { stdout } = useStdout()\n const termWidth = stdout?.columns || 80\n const dashWidth = Math.min(160, termWidth)\n const wide = dashWidth >= MIN_WIDE\n const halfWidth = wide ? Math.floor(dashWidth / 2) : dashWidth\n\n const nameA = shortName(modelA.model)\n const nameB = shortName(modelB.model)\n const lowDataA = modelA.calls < LOW_DATA_THRESHOLD\n const lowDataB = modelB.calls < LOW_DATA_THRESHOLD\n\n useInput((input, key) => {\n if (input === 'q') { exit(); return }\n if (key.escape) { onBack(); return }\n })\n\n const sectionOrder: string[] = []\n const sectionRows = new Map<string, ComparisonRow[]>()\n for (const row of rows) {\n if (!sectionRows.has(row.section)) {\n sectionOrder.push(row.section)\n sectionRows.set(row.section, [])\n }\n sectionRows.get(row.section)!.push(row)\n }\n\n const fmtTokens = (n: number) => {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`\n return String(n)\n }\n\n const contextRows: { label: string; valueA: string; valueB: string }[] = [\n { label: 'Calls', valueA: modelA.calls.toLocaleString(), valueB: modelB.calls.toLocaleString() },\n { label: 'Total cost', valueA: formatCost(modelA.cost), valueB: formatCost(modelB.cost) },\n { label: 'Input tokens', valueA: fmtTokens(modelA.inputTokens), valueB: fmtTokens(modelB.inputTokens) },\n { label: 'Output tokens', valueA: fmtTokens(modelA.outputTokens), valueB: fmtTokens(modelB.outputTokens) },\n { label: 'Days of data', valueA: String(daysOfData(modelA.firstSeen, modelA.lastSeen)), valueB: String(daysOfData(modelB.firstSeen, modelB.lastSeen)) },\n { label: 'Edit turns', valueA: modelA.editTurns.toLocaleString(), valueB: modelB.editTurns.toLocaleString() },\n { label: 'Self-corrections', valueA: modelA.selfCorrections.toLocaleString(), valueB: modelB.selfCorrections.toLocaleString() },\n ]\n\n const lowDataWarning = (lowDataA || lowDataB)\n ? `Note: ${[lowDataA && shortName(modelA.model), lowDataB && shortName(modelB.model)].filter(Boolean).join(' and ')} ha${lowDataA && lowDataB ? 've' : 's'} fewer than ${LOW_DATA_THRESHOLD} calls`\n : undefined\n\n const pw = wide ? halfWidth : dashWidth\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1} width={dashWidth}>\n <Text>\n <Text bold color={ORANGE}>{nameA}</Text>\n <Text dimColor> vs </Text>\n <Text bold color={ORANGE}>{nameB}</Text>\n </Text>\n </Box>\n\n <Box width={dashWidth}>\n <MetricPanel title={sectionOrder[0] ?? 'Performance'} rows={sectionRows.get(sectionOrder[0] ?? '') ?? []} nameA={nameA} nameB={nameB} pw={pw} />\n <MetricPanel title={sectionOrder[1] ?? 'Efficiency'} rows={sectionRows.get(sectionOrder[1] ?? '') ?? []} nameA={nameA} nameB={nameB} pw={pw} />\n </Box>\n\n {categories.length > 0 && (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1} width={dashWidth}>\n <Text bold color={ORANGE}>Category Head-to-Head</Text>\n <Text color={DIM}>one-shot rate per category</Text>\n <Text>\n <Text>{' '}</Text>\n <Text color={BAR_A}>{FULL_BLOCK + FULL_BLOCK}</Text>\n <Text> {nameA} </Text>\n <Text color={BAR_B}>{FULL_BLOCK + FULL_BLOCK}</Text>\n <Text> {nameB}</Text>\n </Text>\n {categories.map(cat => {\n const bwA = cat.oneShotRateA !== null ? barWidth(cat.oneShotRateA) : 0\n const bwB = cat.oneShotRateB !== null ? barWidth(cat.oneShotRateB) : 0\n const rateA = cat.oneShotRateA !== null ? `${cat.oneShotRateA.toFixed(1)}%` : '-'\n const rateB = cat.oneShotRateB !== null ? `${cat.oneShotRateB.toFixed(1)}%` : '-'\n const turnsA = cat.editTurnsA > 0 ? `(${cat.editTurnsA})` : ''\n const turnsB = cat.editTurnsB > 0 ? `(${cat.editTurnsB})` : ''\n\n return (\n <React.Fragment key={cat.category}>\n <Text> </Text>\n <Text color={DIM}>{' '}{cat.category}</Text>\n <Text>\n <Text>{' '}</Text>\n <Text color={cat.winner === 'a' ? BAR_A : DIM}>{FULL_BLOCK.repeat(Math.max(bwA, 1))}</Text>\n <Text>{' '.repeat(Math.max(0, BAR_MAX_WIDTH - bwA))} </Text>\n <Text color={cat.winner === 'a' ? GREEN : undefined}>{rateA.padStart(6)}</Text>\n <Text color={DIM}> {turnsA}</Text>\n </Text>\n <Text>\n <Text>{' '}</Text>\n <Text color={cat.winner === 'b' ? BAR_B : DIM}>{FULL_BLOCK.repeat(Math.max(bwB, 1))}</Text>\n <Text>{' '.repeat(Math.max(0, BAR_MAX_WIDTH - bwB))} </Text>\n <Text color={cat.winner === 'b' ? GREEN : undefined}>{rateB.padStart(6)}</Text>\n <Text color={DIM}> {turnsB}</Text>\n </Text>\n </React.Fragment>\n )\n })}\n </Box>\n )}\n\n <Box width={dashWidth}>\n {workingStyle.length > 0 && (\n <ContextPanel title=\"Working Style\" rows={workingStyle.map(r => ({ label: r.label, valueA: formatValue(r.valueA, r.formatFn), valueB: formatValue(r.valueB, r.formatFn) }))} nameA={nameA} nameB={nameB} pw={pw} />\n )}\n <ContextPanel title=\"Context\" rows={contextRows} nameA={nameA} nameB={nameB} pw={pw} lowDataWarning={lowDataWarning} />\n </Box>\n\n <Text>\n <Text color={ORANGE} bold>{'<>'}</Text><Text dimColor> switch period </Text>\n <Text color={ORANGE} bold>[esc]</Text><Text dimColor> back </Text>\n <Text color={ORANGE} bold>[q]</Text><Text dimColor> quit</Text>\n </Text>\n </Box>\n )\n}\n\ntype CompareViewProps = {\n projects: ProjectSummary[]\n onBack: () => void\n}\n\nexport function CompareView({ projects, onBack }: CompareViewProps) {\n const { exit } = useApp()\n const [phase, setPhase] = useState<'select' | 'loading' | 'results'>('select')\n const [models, setModels] = useState<ModelStats[]>(() => aggregateModelStats(projects))\n const [pickedNames, setPickedNames] = useState<[string, string] | null>(null)\n const [selectedA, setSelectedA] = useState<ModelStats | null>(null)\n const [selectedB, setSelectedB] = useState<ModelStats | null>(null)\n const [rows, setRows] = useState<ComparisonRow[]>([])\n const [categories, setCategories] = useState<CategoryComparison[]>([])\n const [style, setStyle] = useState<WorkingStyleRow[]>([])\n const [loadTrigger, setLoadTrigger] = useState(0)\n const projectsRef = useRef(projects)\n projectsRef.current = projects\n\n useEffect(() => {\n const newModels = aggregateModelStats(projects)\n setModels(newModels)\n\n if (pickedNames) {\n const hasA = newModels.some(m => m.model === pickedNames[0])\n const hasB = newModels.some(m => m.model === pickedNames[1])\n if (hasA && hasB) {\n setLoadTrigger(t => t + 1)\n } else {\n setPickedNames(null)\n setPhase('select')\n }\n }\n }, [projects])\n\n useEffect(() => {\n if (loadTrigger === 0 || !pickedNames) return\n let cancelled = false\n setPhase('loading')\n\n const currentModels = aggregateModelStats(projectsRef.current)\n const a = currentModels.find(m => m.model === pickedNames[0])\n const b = currentModels.find(m => m.model === pickedNames[1])\n if (!a || !b) { setPhase('select'); return }\n\n async function run() {\n const providers = await getAllProviders()\n const dirs: string[] = []\n for (const p of providers) {\n const sessions = await p.discoverSessions()\n for (const s of sessions) dirs.push(s.path)\n }\n const corrections = await scanSelfCorrections(dirs)\n if (cancelled) return\n\n const currentProjects = projectsRef.current\n const aCopy = { ...a!, selfCorrections: corrections.get(a!.model) ?? 0 }\n const bCopy = { ...b!, selfCorrections: corrections.get(b!.model) ?? 0 }\n setSelectedA(aCopy)\n setSelectedB(bCopy)\n setRows(computeComparison(aCopy, bCopy))\n setCategories(computeCategoryComparison(currentProjects, a!.model, b!.model))\n setStyle(computeWorkingStyle(currentProjects, a!.model, b!.model))\n setPhase('results')\n }\n\n run()\n return () => { cancelled = true }\n }, [loadTrigger])\n\n useInput((input, key) => {\n if (phase !== 'select') return\n if (models.length < 2) {\n if (input === 'q') { exit(); return }\n if (key.escape) { onBack(); return }\n }\n })\n\n if (models.length < 2) {\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1}>\n <Text bold color={ORANGE}>Model Comparison</Text>\n <Text> </Text>\n <Text color={DIM}>Need at least 2 models to compare. Found {models.length}.</Text>\n </Box>\n <Text> </Text>\n <Text>\n <Text color={ORANGE} bold>[esc]</Text><Text dimColor> back </Text>\n <Text color={ORANGE} bold>[q]</Text><Text dimColor> quit</Text>\n </Text>\n </Box>\n )\n }\n\n const handleSelect = (a: ModelStats, b: ModelStats) => {\n setPickedNames([a.model, b.model])\n setLoadTrigger(t => t + 1)\n }\n\n if (phase === 'loading') {\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={ORANGE} paddingX={1}>\n <Text bold color={ORANGE}>Model Comparison</Text>\n <Text> </Text>\n <Text color={DIM}>Scanning self-corrections...</Text>\n </Box>\n </Box>\n )\n }\n\n if (phase === 'results' && selectedA && selectedB) {\n return (\n <ComparisonResults\n modelA={selectedA}\n modelB={selectedB}\n rows={rows}\n categories={categories}\n workingStyle={style}\n onBack={() => setPhase('select')}\n />\n )\n }\n\n return (\n <ModelSelector\n models={models}\n onSelect={handleSelect}\n onBack={onBack}\n />\n )\n}\n\nexport async function renderCompare(range: DateRange, provider: string): Promise<void> {\n const isTTY = process.stdin.isTTY && process.stdout.isTTY\n if (!isTTY) {\n process.stdout.write('Model comparison requires an interactive terminal.\\n')\n return\n }\n\n const projects = await parseAllSessions(range, provider)\n const { waitUntilExit } = render(\n <CompareView projects={projects} onBack={() => process.exit(0)} />\n )\n await waitUntilExit()\n}\n","import { readdir, readFile } from 'fs/promises'\nimport { join } from 'path'\n\nimport type { ProjectSummary } from './types.js'\n\nconst PLANNING_TOOLS = new Set(['TaskCreate', 'TaskUpdate', 'TodoWrite', 'EnterPlanMode', 'ExitPlanMode'])\n\nexport type ModelStats = {\n model: string\n calls: number\n cost: number\n outputTokens: number\n inputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n totalTurns: number\n editTurns: number\n oneShotTurns: number\n retries: number\n selfCorrections: number\n editCost: number\n firstSeen: string\n lastSeen: string\n}\n\nexport function aggregateModelStats(projects: ProjectSummary[]): ModelStats[] {\n const byModel = new Map<string, ModelStats>()\n\n const ensure = (model: string): ModelStats => {\n let s = byModel.get(model)\n if (!s) {\n s = { model, calls: 0, cost: 0, outputTokens: 0, inputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, totalTurns: 0, editTurns: 0, oneShotTurns: 0, retries: 0, selfCorrections: 0, editCost: 0, firstSeen: '', lastSeen: '' }\n byModel.set(model, s)\n }\n return s\n }\n\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (turn.assistantCalls.length === 0) continue\n const primaryModel = turn.assistantCalls[0]!.model\n if (primaryModel === '<synthetic>') continue\n\n const ms = ensure(primaryModel)\n ms.totalTurns++\n if (turn.hasEdits) {\n ms.editTurns++\n if (turn.retries === 0) ms.oneShotTurns++\n for (const c of turn.assistantCalls) {\n if (c.model !== '<synthetic>') ms.editCost += c.costUSD\n }\n }\n ms.retries += turn.retries\n\n for (const call of turn.assistantCalls) {\n if (call.model === '<synthetic>') continue\n const cs = call.model === primaryModel ? ms : ensure(call.model)\n cs.calls++\n cs.cost += call.costUSD\n cs.outputTokens += call.usage.outputTokens\n cs.inputTokens += call.usage.inputTokens\n cs.cacheReadTokens += call.usage.cacheReadInputTokens\n cs.cacheWriteTokens += call.usage.cacheCreationInputTokens\n\n if (!cs.firstSeen || call.timestamp < cs.firstSeen) cs.firstSeen = call.timestamp\n if (!cs.lastSeen || call.timestamp > cs.lastSeen) cs.lastSeen = call.timestamp\n }\n }\n }\n }\n\n return [...byModel.values()].sort((a, b) => b.cost - a.cost)\n}\n\nexport type ComparisonRow = {\n section: string\n label: string\n valueA: number | null\n valueB: number | null\n formatFn: 'cost' | 'number' | 'percent' | 'decimal'\n winner: 'a' | 'b' | 'tie' | 'none'\n}\n\nexport type CategoryComparison = {\n category: string\n turnsA: number\n editTurnsA: number\n oneShotRateA: number | null\n turnsB: number\n editTurnsB: number\n oneShotRateB: number | null\n winner: 'a' | 'b' | 'tie' | 'none'\n}\n\nexport type WorkingStyleRow = {\n label: string\n valueA: number | null\n valueB: number | null\n formatFn: ComparisonRow['formatFn']\n}\n\ntype MetricDef = {\n section: string\n label: string\n formatFn: ComparisonRow['formatFn']\n higherIsBetter: boolean\n compute: (s: ModelStats) => number | null\n}\n\nconst METRICS: MetricDef[] = [\n {\n section: 'Performance',\n label: 'One-shot rate',\n formatFn: 'percent',\n higherIsBetter: true,\n compute: s => s.editTurns > 0 ? (s.oneShotTurns / s.editTurns) * 100 : null,\n },\n {\n section: 'Performance',\n label: 'Retry rate',\n formatFn: 'decimal',\n higherIsBetter: false,\n compute: s => s.editTurns > 0 ? s.retries / s.editTurns : null,\n },\n {\n section: 'Performance',\n label: 'Self-correction',\n formatFn: 'percent',\n higherIsBetter: false,\n compute: s => s.totalTurns > 0 ? (s.selfCorrections / s.totalTurns) * 100 : null,\n },\n {\n section: 'Efficiency',\n label: 'Cost / call',\n formatFn: 'cost',\n higherIsBetter: false,\n compute: s => s.calls > 0 ? s.cost / s.calls : null,\n },\n {\n section: 'Efficiency',\n label: 'Cost / edit',\n formatFn: 'cost',\n higherIsBetter: false,\n compute: s => s.editTurns > 0 ? s.editCost / s.editTurns : null,\n },\n {\n section: 'Efficiency',\n label: 'Output tok / call',\n formatFn: 'number',\n higherIsBetter: false,\n compute: s => s.calls > 0 ? Math.round(s.outputTokens / s.calls) : null,\n },\n {\n section: 'Efficiency',\n label: 'Cache hit rate',\n formatFn: 'percent',\n higherIsBetter: true,\n compute: s => {\n const total = s.inputTokens + s.cacheReadTokens + s.cacheWriteTokens\n return total > 0 ? (s.cacheReadTokens / total) * 100 : null\n },\n },\n]\n\nfunction pickWinner(valueA: number | null, valueB: number | null, higherIsBetter: boolean): ComparisonRow['winner'] {\n if (valueA === null || valueB === null) return 'none'\n if (valueA === valueB) return 'tie'\n if (higherIsBetter) return valueA > valueB ? 'a' : 'b'\n return valueA < valueB ? 'a' : 'b'\n}\n\nexport function computeComparison(a: ModelStats, b: ModelStats): ComparisonRow[] {\n return METRICS.map(m => {\n const valueA = m.compute(a)\n const valueB = m.compute(b)\n return {\n section: m.section,\n label: m.label,\n valueA,\n valueB,\n formatFn: m.formatFn,\n winner: pickWinner(valueA, valueB, m.higherIsBetter),\n }\n })\n}\n\nexport function computeCategoryComparison(projects: ProjectSummary[], modelA: string, modelB: string): CategoryComparison[] {\n type Accum = { turns: number; editTurns: number; oneShotTurns: number }\n const mapA = new Map<string, Accum>()\n const mapB = new Map<string, Accum>()\n\n const ensure = (map: Map<string, Accum>, cat: string): Accum => {\n let a = map.get(cat)\n if (!a) { a = { turns: 0, editTurns: 0, oneShotTurns: 0 }; map.set(cat, a) }\n return a\n }\n\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (turn.assistantCalls.length === 0) continue\n const primary = turn.assistantCalls[0]!.model\n if (primary !== modelA && primary !== modelB) continue\n\n const acc = ensure(primary === modelA ? mapA : mapB, turn.category)\n acc.turns++\n if (turn.hasEdits) {\n acc.editTurns++\n if (turn.retries === 0) acc.oneShotTurns++\n }\n }\n }\n }\n\n const allCats = new Set([...mapA.keys(), ...mapB.keys()])\n const result: CategoryComparison[] = []\n\n for (const category of allCats) {\n const a = mapA.get(category)\n const b = mapB.get(category)\n if ((!a || a.editTurns === 0) && (!b || b.editTurns === 0)) continue\n\n const rateA = a && a.editTurns > 0 ? (a.oneShotTurns / a.editTurns) * 100 : null\n const rateB = b && b.editTurns > 0 ? (b.oneShotTurns / b.editTurns) * 100 : null\n\n result.push({\n category,\n turnsA: a?.turns ?? 0,\n editTurnsA: a?.editTurns ?? 0,\n oneShotRateA: rateA,\n turnsB: b?.turns ?? 0,\n editTurnsB: b?.editTurns ?? 0,\n oneShotRateB: rateB,\n winner: pickWinner(rateA, rateB, true),\n })\n }\n\n return result.sort((a, b) => (b.turnsA + b.turnsB) - (a.turnsA + a.turnsB))\n}\n\nexport function computeWorkingStyle(projects: ProjectSummary[], modelA: string, modelB: string): WorkingStyleRow[] {\n type StyleAccum = { totalTurns: number; agentSpawns: number; planModeUses: number; totalToolCalls: number; fastModeCalls: number }\n const sA: StyleAccum = { totalTurns: 0, agentSpawns: 0, planModeUses: 0, totalToolCalls: 0, fastModeCalls: 0 }\n const sB: StyleAccum = { totalTurns: 0, agentSpawns: 0, planModeUses: 0, totalToolCalls: 0, fastModeCalls: 0 }\n\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (turn.assistantCalls.length === 0) continue\n const primary = turn.assistantCalls[0]!.model\n if (primary !== modelA && primary !== modelB) continue\n\n const s = primary === modelA ? sA : sB\n s.totalTurns++\n const turnTools = turn.assistantCalls.flatMap(c => c.tools)\n if (turnTools.some(t => PLANNING_TOOLS.has(t)) || turn.assistantCalls.some(c => c.hasPlanMode)) {\n s.planModeUses++\n }\n for (const call of turn.assistantCalls) {\n s.totalToolCalls += call.tools.length\n if (call.hasAgentSpawn) s.agentSpawns++\n if (call.speed === 'fast') s.fastModeCalls++\n }\n }\n }\n }\n\n const pct = (num: number, den: number) => den > 0 ? (num / den) * 100 : null\n const avg = (num: number, den: number) => den > 0 ? num / den : null\n\n return [\n { label: 'Delegation rate', valueA: pct(sA.agentSpawns, sA.totalTurns), valueB: pct(sB.agentSpawns, sB.totalTurns), formatFn: 'percent' as const },\n { label: 'Planning rate', valueA: pct(sA.planModeUses, sA.totalTurns), valueB: pct(sB.planModeUses, sB.totalTurns), formatFn: 'percent' as const },\n { label: 'Avg tools / turn', valueA: avg(sA.totalToolCalls, sA.totalTurns), valueB: avg(sB.totalToolCalls, sB.totalTurns), formatFn: 'decimal' as const },\n { label: 'Fast mode usage', valueA: pct(sA.fastModeCalls, sA.totalTurns), valueB: pct(sB.fastModeCalls, sB.totalTurns), formatFn: 'percent' as const },\n ]\n}\n\nconst SELF_CORRECTION_PATTERNS = [\n /\\bmy mistake\\b/i,\n /\\bmy bad\\b/i,\n /\\bmy apolog/i,\n /\\bI apologize\\b/i,\n /\\bI was wrong\\b/i,\n /\\bI was incorrect\\b/i,\n /\\bI made (a |an )?(error|mistake)\\b/i,\n /\\bI incorrectly\\b/i,\n /\\bI mistakenly\\b/i,\n /\\bthat was (incorrect|wrong|an error)\\b/i,\n /\\blet me correct that\\b/i,\n /\\bI need to correct\\b/i,\n /\\byou're right[.,]? I/i,\n /\\bsorry about that\\b/i,\n]\n\nfunction extractText(content: unknown): string {\n if (typeof content === 'string') return content\n if (!Array.isArray(content)) return ''\n return content\n .filter((b): b is { type: string; text: string } => b !== null && typeof b === 'object' && b.type === 'text' && typeof b.text === 'string')\n .map(b => b.text)\n .join(' ')\n}\n\nfunction isCompactFile(name: string): boolean {\n return name.includes('compact')\n}\n\nasync function collectJsonlFiles(sessionDir: string): Promise<string[]> {\n const entries = await readdir(sessionDir, { withFileTypes: true })\n const files: string[] = []\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.jsonl') && !isCompactFile(entry.name)) {\n files.push(join(sessionDir, entry.name))\n } else if (entry.isDirectory() && entry.name === 'subagents') {\n const subEntries = await readdir(join(sessionDir, entry.name), { withFileTypes: true })\n for (const sub of subEntries) {\n if (sub.isFile() && sub.name.endsWith('.jsonl') && !isCompactFile(sub.name)) {\n files.push(join(sessionDir, entry.name, sub.name))\n }\n }\n }\n }\n return files\n}\n\nexport async function scanSelfCorrections(projectDirs: string[]): Promise<Map<string, number>> {\n const counts = new Map<string, number>()\n const seen = new Set<string>()\n\n for (const dir of projectDirs) {\n let entries\n try {\n entries = await readdir(dir, { withFileTypes: true })\n } catch {\n continue\n }\n\n const allFiles: string[] = []\n\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.jsonl') && !isCompactFile(entry.name)) {\n allFiles.push(join(dir, entry.name))\n } else if (entry.isDirectory()) {\n try {\n const sessionFiles = await collectJsonlFiles(join(dir, entry.name))\n allFiles.push(...sessionFiles)\n } catch {\n continue\n }\n }\n }\n\n for (const file of allFiles) {\n let raw: string\n try {\n raw = await readFile(file, 'utf8')\n } catch {\n continue\n }\n\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed)\n } catch {\n continue\n }\n\n const rec = parsed as Record<string, unknown>\n if (!rec || typeof rec !== 'object' || rec['type'] !== 'assistant') continue\n\n const ts = rec['timestamp']\n const msg = rec['message']\n if (msg === null || typeof msg !== 'object') continue\n\n const msgRec = msg as Record<string, unknown>\n const model = msgRec['model']\n if (typeof model !== 'string' || model === '<synthetic>') continue\n\n const dedupeKey = `${model}:${ts}`\n if (seen.has(dedupeKey)) continue\n seen.add(dedupeKey)\n\n const text = extractText(msgRec['content'])\n if (SELF_CORRECTION_PATTERNS.some(p => p.test(text))) {\n counts.set(model, (counts.get(model) ?? 0) + 1)\n }\n }\n }\n }\n\n return counts\n}\n","import { readPlan, type Plan } from './config.js'\nimport { parseAllSessions } from './parser.js'\nimport type { DateRange, ProjectSummary } from './types.js'\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000\nconst PLAN_NEAR_THRESHOLD_PCT = 80\n\nexport type PlanStatus = 'under' | 'near' | 'over'\n\nexport type PlanUsage = {\n plan: Plan\n periodStart: Date\n periodEnd: Date\n spentApiEquivalentUsd: number\n budgetUsd: number\n percentUsed: number\n status: PlanStatus\n projectedMonthUsd: number\n daysUntilReset: number\n}\n\nexport function clampResetDay(resetDay: number | undefined): number {\n if (!Number.isInteger(resetDay)) return 1\n return Math.min(28, Math.max(1, resetDay ?? 1))\n}\n\nexport function computePeriodFromResetDay(resetDay: number | undefined, today: Date): { periodStart: Date; periodEnd: Date } {\n const day = clampResetDay(resetDay)\n const year = today.getFullYear()\n const month = today.getMonth()\n\n if (today.getDate() >= day) {\n return {\n periodStart: new Date(year, month, day, 0, 0, 0, 0),\n periodEnd: new Date(year, month + 1, day, 0, 0, 0, 0),\n }\n }\n\n return {\n periodStart: new Date(year, month - 1, day, 0, 0, 0, 0),\n periodEnd: new Date(year, month, day, 0, 0, 0, 0),\n }\n}\n\nfunction median(values: number[]): number {\n if (values.length === 0) return 0\n const sorted = [...values].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n if (sorted.length % 2 === 0) {\n return (sorted[mid - 1] + sorted[mid]) / 2\n }\n return sorted[mid]!\n}\n\nfunction toLocalDateKey(d: Date): string {\n const year = d.getFullYear()\n const month = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\nfunction toDayIndex(d: Date): number {\n return Math.floor(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / MS_PER_DAY)\n}\n\nfunction diffCalendarDays(from: Date, to: Date): number {\n return toDayIndex(to) - toDayIndex(from)\n}\n\nexport function projectMonthEnd(\n projects: ProjectSummary[],\n periodStart: Date,\n periodEnd: Date,\n today: Date,\n spent: number,\n): number {\n const dayCosts = new Map<string, number>()\n\n for (const project of projects) {\n for (const session of project.sessions) {\n for (const turn of session.turns) {\n if (!turn.timestamp) continue\n const ts = new Date(turn.timestamp)\n if (Number.isNaN(ts.getTime())) continue\n if (ts < periodStart || ts > today) continue\n const dayKey = toLocalDateKey(ts)\n const turnCost = turn.assistantCalls.reduce((sum, call) => sum + call.costUSD, 0)\n dayCosts.set(dayKey, (dayCosts.get(dayKey) ?? 0) + turnCost)\n }\n }\n }\n\n const elapsedDays = Math.max(1, diffCalendarDays(periodStart, today) + 1)\n const elapsedDailyCosts: number[] = []\n for (let i = 0; i < elapsedDays; i++) {\n const date = new Date(periodStart.getFullYear(), periodStart.getMonth(), periodStart.getDate() + i)\n elapsedDailyCosts.push(dayCosts.get(toLocalDateKey(date)) ?? 0)\n }\n\n const trailingWindow = elapsedDailyCosts.slice(-7)\n const medianDailyCost = median(trailingWindow)\n const daysRemaining = Math.max(0, diffCalendarDays(today, periodEnd) - 1)\n\n return spent + medianDailyCost * daysRemaining\n}\n\nexport function getPlanUsageFromProjects(plan: Plan, projects: ProjectSummary[], today = new Date()): PlanUsage {\n const { periodStart, periodEnd } = computePeriodFromResetDay(plan.resetDay, today)\n const spent = projects.reduce((sum, p) => sum + p.totalCostUSD, 0)\n const budgetUsd = plan.monthlyUsd\n const percentUsed = budgetUsd > 0 ? (spent / budgetUsd) * 100 : 0\n const status: PlanStatus = percentUsed > 100 ? 'over' : percentUsed >= PLAN_NEAR_THRESHOLD_PCT ? 'near' : 'under'\n const projectedMonthUsd = projectMonthEnd(projects, periodStart, periodEnd, today, spent)\n const daysUntilReset = Math.max(0, diffCalendarDays(today, periodEnd))\n\n return {\n plan,\n periodStart,\n periodEnd,\n spentApiEquivalentUsd: spent,\n budgetUsd,\n percentUsed,\n status,\n projectedMonthUsd,\n daysUntilReset,\n }\n}\n\nexport async function getPlanUsage(plan: Plan, today = new Date()): Promise<PlanUsage> {\n const { periodStart } = computePeriodFromResetDay(plan.resetDay, today)\n const range: DateRange = {\n start: periodStart,\n end: today,\n }\n const provider = plan.provider === 'all' ? 'all' : plan.provider\n const projects = await parseAllSessions(range, provider)\n return getPlanUsageFromProjects(plan, projects, today)\n}\n\nexport async function getPlanUsageOrNull(today = new Date()): Promise<PlanUsage | null> {\n const plan = await readPlan()\n if (!isActivePlan(plan)) return null\n return getPlanUsage(plan, today)\n}\n\nexport function isActivePlan(plan: Plan | undefined): plan is Plan {\n return plan !== undefined && plan.id !== 'none' && Number.isFinite(plan.monthlyUsd) && plan.monthlyUsd > 0\n}\n","import type { Plan, PlanId, PlanProvider } from './config.js'\n\nexport const PLAN_PROVIDERS: PlanProvider[] = ['all', 'claude', 'codex', 'cursor']\nexport const PLAN_IDS: PlanId[] = ['claude-pro', 'claude-max', 'cursor-pro', 'custom', 'none']\n\nexport const PRESET_PLANS: Record<'claude-pro' | 'claude-max' | 'cursor-pro', Omit<Plan, 'setAt'>> = {\n 'claude-pro': {\n id: 'claude-pro',\n monthlyUsd: 20,\n provider: 'claude',\n resetDay: 1,\n },\n 'claude-max': {\n id: 'claude-max',\n monthlyUsd: 200,\n provider: 'claude',\n resetDay: 1,\n },\n 'cursor-pro': {\n id: 'cursor-pro',\n monthlyUsd: 20,\n provider: 'cursor',\n resetDay: 1,\n },\n}\n\nexport function isPlanProvider(value: string): value is PlanProvider {\n return PLAN_PROVIDERS.includes(value as PlanProvider)\n}\n\nexport function isPlanId(value: string): value is PlanId {\n return PLAN_IDS.includes(value as PlanId)\n}\n\nexport function getPresetPlan(id: string): Omit<Plan, 'setAt'> | null {\n if (id in PRESET_PLANS) {\n return PRESET_PLANS[id as keyof typeof PRESET_PLANS]\n }\n return null\n}\n\nexport function planDisplayName(id: PlanId): string {\n switch (id) {\n case 'claude-pro':\n return 'Claude Pro'\n case 'claude-max':\n return 'Claude Max'\n case 'cursor-pro':\n return 'Cursor Pro'\n case 'custom':\n return 'Custom'\n case 'none':\n return 'None'\n }\n}\n","import type { DateRange } from './types.js'\n\nconst ISO_DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/\n\nconst END_OF_DAY_HOURS = 23\nconst END_OF_DAY_MINUTES = 59\nconst END_OF_DAY_SECONDS = 59\nconst END_OF_DAY_MS = 999\n\nfunction parseLocalDate(s: string): Date {\n if (!ISO_DATE_RE.test(s)) {\n throw new Error(`Invalid date format \"${s}\": expected YYYY-MM-DD`)\n }\n const [y, m, d] = s.split('-').map(Number) as [number, number, number]\n return new Date(y, m - 1, d)\n}\n\nexport function parseDateRangeFlags(from: string | undefined, to: string | undefined): DateRange | null {\n if (from === undefined && to === undefined) return null\n\n const now = new Date()\n const start = from !== undefined ? parseLocalDate(from) : new Date(0)\n\n const endDate = to !== undefined ? parseLocalDate(to) : new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const end = new Date(\n endDate.getFullYear(),\n endDate.getMonth(),\n endDate.getDate(),\n END_OF_DAY_HOURS,\n END_OF_DAY_MINUTES,\n END_OF_DAY_SECONDS,\n END_OF_DAY_MS,\n )\n\n if (start > end) {\n throw new Error(`--from must not be after --to (got ${from} > ${to})`)\n }\n return { start, end }\n}\n"],"mappings":"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","names":["join","homedir","readFile","mkdir","rename","unlink","open","join","randomBytes","CACHE_TTL_MS","shortNames","basename","cursor","readFile","mkdir","stat","rename","open","join","randomBytes","getCachePath","join","homedir","resolveModel","createParser","modelDisplayNames","readdir","join","homedir","validateSchema","createParser","toolNameMap","existsSync","readdir","readFile","stat","join","basename","homedir","getProjectsDir","ms","resolveModel","cursor","active","createParser","modelDisplayNames","existsSync","readFileSync","statSync","join","homedir","resolve","mkdir","stat","rm","join","readFile","mkdir","rename","open","join","randomBytes","mkdir","rename","join","homedir","join","readFile","mkdir","randomBytes","open","rename","stat","join","rm","mkdir","readdir","stat","basename","join","readFile","stat","readdir","stat","join","homedir","readdir","stat","basename","join","homedir","join","homedir","readdir","stat","basename","readdir","stat","basename","dirname","join","homedir","modelDisplayNames","toolNameMap","join","homedir","createParser","basename","dirname","discoverSessionsInDir","readdir","stat","readdir","stat","basename","join","homedir","modelDisplayNames","toolNameMap","modelDisplayEntries","join","homedir","discoverSessionsInDir","readdir","stat","basename","createParser","cursor","opencode","cursor_agent","cursor","stat","basename","readdir","join","CACHE_TTL_MS","randomBytes","existsSync","mkdir","open","readFile","rename","unlink","join","getCachePath","homedir","useState","useEffect","useRef","render","Box","Text","useInput","useApp","chalk","readdir","stat","existsSync","statSync","basename","join","homedir","collectJsonlFiles","readdir","join","stat","basename","msg","homedir","existsSync","statSync","median","cacheKey","chalk","pct","readdir","existsSync","join","homedir","CHARS_PER_TOKEN","estimateTokens","existsSync","homedir","join","readdir","readdir","join","readdir","readFile","join","pct","collectJsonlFiles","ORANGE","GREEN","DIM","GOLD","cursor","ORANGE","DIM","GREEN","GOLD","MS_PER_DAY","join","jsx","jsxs","MIN_WIDE","ORANGE","DIM","GOLD","pct","t","barWidth","Text","Box","homedir","active","GRADE_COLORS","useApp","useState","useRef","useEffect","useInput","render","createRequire","require","createRequire","MS_PER_DAY","getDateRange","cacheHitPercent","join","homedir","existsSync","statSync","readFileSync","config","rate","symbol"]}