ccusage 13.0.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -2
- package/README.md +92 -28
- package/dist/calculate-cost.d.ts +2 -2
- package/dist/calculate-cost.js +1 -1
- package/dist/{data-loader-BrxITdVN.d.ts → data-loader-C1n0ww95.d.ts} +10 -3
- package/dist/{data-loader-B8gFJPfi.js → data-loader-C8KM6jhg.js} +111 -40
- package/dist/data-loader.d.ts +3 -3
- package/dist/data-loader.js +5 -5
- package/dist/{debug-CL2Shx1n.js → debug-BJaJWLMi.js} +3 -3
- package/dist/debug.js +5 -5
- package/dist/index.js +150 -32
- package/dist/{logger-B4PJ298G.js → logger-fRKbFGRA.js} +1 -1
- package/dist/logger.js +1 -1
- package/dist/{mcp-Bw62xMEM.js → mcp-Beq_0A1e.js} +4 -4
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +5 -5
- package/dist/{pricing-fetcher-A6FC8DhM.d.ts → pricing-fetcher-CXnYw4TA.d.ts} +1 -1
- package/dist/{pricing-fetcher-Cx71zrV9.js → pricing-fetcher-Dup-4216.js} +13 -3
- package/dist/pricing-fetcher.d.ts +1 -1
- package/dist/pricing-fetcher.js +3 -3
- package/package.json +1 -1
- /package/dist/{types.internal-CX7kpidj.js → _types-Cr2YEzKm.js} +0 -0
package/LICENSE
CHANGED
|
@@ -2,8 +2,6 @@ MIT License
|
|
|
2
2
|
|
|
3
3
|
Copyright (c) 2025 ryoppippi
|
|
4
4
|
|
|
5
|
-
Logo and brand assets created by nyatinte are also licensed under MIT License.
|
|
6
|
-
|
|
7
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
9
7
|
in the Software without restriction, including without limitation the rights
|
package/README.md
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
# ccusage
|
|
2
|
-
|
|
3
1
|
<div align="center">
|
|
4
|
-
|
|
2
|
+
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/logo.svg" alt="ccusage logo" width="256" height="256">
|
|
3
|
+
<h1>ccusage</h1>
|
|
5
4
|
</div>
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://npmjs.com/package/ccusage"><img src="https://img.shields.io/npm/v/ccusage?color=yellow" alt="npm version" /></a>
|
|
8
|
+
<a href="https://tanstack.com/stats/npm?packageGroups=%5B%7B%22packages%22:%5B%7B%22name%22:%22ccusage%22%7D%5D%7D%5D&range=30-days&transform=none&binType=daily&showDataMode=all&height=400"><img src="https://img.shields.io/npm/dy/ccusage" alt="NPM Downloads" /></a>
|
|
9
|
+
<a href="https://packagephobia.com/result?p=ccusage"><img src="https://packagephobia.com/badge?p=ccusage" alt="install size" /></a>
|
|
10
|
+
<a href="https://deepwiki.com/ryoppippi/ccusage"><img src="https://img.shields.io/badge/DeepWiki-ryoppippi%2Fccusage-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==" alt="DeepWiki" /></a>
|
|
11
|
+
<a href="https://github.com/hesreallyhim/awesome-claude-code"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Claude Code" /></a>
|
|
12
|
+
</p>
|
|
12
13
|
|
|
13
14
|
<div align="center">
|
|
14
|
-
|
|
15
|
+
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/screenshot.png">
|
|
15
16
|
</div>
|
|
16
17
|
|
|
17
18
|
> **ccusage(claude-code-usage)**
|
|
@@ -23,15 +24,15 @@ Inspired by [this article](https://note.com/milliondev/n/n1d018da2d769) about tr
|
|
|
23
24
|
## What is `ccusage` (by NotebookLM)
|
|
24
25
|
|
|
25
26
|
<details>
|
|
26
|
-
|
|
27
|
+
<summary>Podcast</summary>
|
|
27
28
|
|
|
28
29
|
# English
|
|
29
30
|
|
|
30
|
-
https://github.com/user-attachments/assets/7a00f2f3-82a7-41b6-a8da-e04b76b5e35a
|
|
31
|
+
<https://github.com/user-attachments/assets/7a00f2f3-82a7-41b6-a8da-e04b76b5e35a>
|
|
31
32
|
|
|
32
33
|
# 日本語
|
|
33
34
|
|
|
34
|
-
https://github.com/user-attachments/assets/db09fc06-bf57-4d37-9b06-514851bcc1d0
|
|
35
|
+
<https://github.com/user-attachments/assets/db09fc06-bf57-4d37-9b06-514851bcc1d0>
|
|
35
36
|
|
|
36
37
|
</details>
|
|
37
38
|
|
|
@@ -51,12 +52,13 @@ This tool helps you understand the value you're getting from your subscription b
|
|
|
51
52
|
- 📊 **Model Breakdown**: View per-model cost breakdown with `--breakdown` flag
|
|
52
53
|
- 📅 **Date Filtering**: Filter reports by date range using `--since` and `--until`
|
|
53
54
|
- 📁 **Custom Path**: Support for custom Claude data directory locations
|
|
54
|
-
- 🎨 **Beautiful Output**: Colorful table-formatted display with responsive
|
|
55
|
+
- 🎨 **Beautiful Output**: Colorful table-formatted display with automatic responsive layout
|
|
56
|
+
- 📱 **Smart Tables**: Automatic compact mode for narrow terminals (< 100 characters) with essential columns
|
|
57
|
+
- 📋 **Enhanced Model Display**: Model names shown as bulleted lists for better readability
|
|
55
58
|
- 📄 **JSON Output**: Export data in structured JSON format with `--json`
|
|
56
59
|
- 💰 **Cost Tracking**: Shows costs in USD for each day/month/session
|
|
57
60
|
- 🔄 **Cache Token Support**: Tracks and displays cache creation and cache read tokens separately
|
|
58
61
|
- 🌐 **Offline Mode**: Use pre-cached pricing data without network connectivity with `--offline` (Claude models only)
|
|
59
|
-
- 📏 **Responsive Tables**: Automatic table width adjustment for narrow terminals with intelligent word wrapping
|
|
60
62
|
- 🔌 **MCP Integration**: Built-in Model Context Protocol server for integration with other tools
|
|
61
63
|
|
|
62
64
|
## Important Disclaimer
|
|
@@ -122,6 +124,31 @@ bun install
|
|
|
122
124
|
bun run start [subcommand] [options]
|
|
123
125
|
```
|
|
124
126
|
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
### Claude Data Directory Support
|
|
130
|
+
|
|
131
|
+
ccusage automatically detects and aggregates usage data from multiple Claude Code installation directories:
|
|
132
|
+
|
|
133
|
+
- **`~/.config/claude/projects/`** - New default location (Claude Code v1.0.30+)
|
|
134
|
+
- **`~/.claude/projects/`** - Legacy location (pre-v1.0.30)
|
|
135
|
+
|
|
136
|
+
> **Note**: The directory change from `~/.claude` to `~/.config/claude` in Claude Code v1.0.30 was an undocumented breaking change. ccusage handles both locations automatically to ensure compatibility across different Claude Code versions.
|
|
137
|
+
|
|
138
|
+
### Custom Paths
|
|
139
|
+
|
|
140
|
+
You can specify custom Claude data directories using the `CLAUDE_CONFIG_DIR` environment variable:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Single custom path
|
|
144
|
+
export CLAUDE_CONFIG_DIR="/path/to/your/claude/data"
|
|
145
|
+
|
|
146
|
+
# Multiple paths (comma-separated)
|
|
147
|
+
export CLAUDE_CONFIG_DIR="/path/to/claude1,/path/to/claude2"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
When `CLAUDE_CONFIG_DIR` is set, ccusage will use those paths instead of the default locations.
|
|
151
|
+
|
|
125
152
|
## Usage
|
|
126
153
|
|
|
127
154
|
### Daily Report (Default)
|
|
@@ -280,7 +307,7 @@ The blocks report helps you understand Claude Code's 5-hour rolling session wind
|
|
|
280
307
|
- Helps track if you're approaching token limits within a session
|
|
281
308
|
- The `-t max` option automatically uses your highest previous block as the limit
|
|
282
309
|
|
|
283
|
-
#### Blocks-specific options
|
|
310
|
+
#### Blocks-specific options
|
|
284
311
|
|
|
285
312
|
- `-t, --token-limit <number|max>`: Set token limit for quota warnings (use "max" for highest previous block)
|
|
286
313
|
- `-a, --active`: Show only active block with detailed projections
|
|
@@ -353,7 +380,7 @@ Available MCP tools:
|
|
|
353
380
|
#### Claude Desktop Configuration Example
|
|
354
381
|
|
|
355
382
|
<div align="center">
|
|
356
|
-
|
|
383
|
+
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/mcp-claude-desktop.avif">
|
|
357
384
|
</div>
|
|
358
385
|
|
|
359
386
|
To use ccusage MCP with Claude Desktop, add this to your Claude Desktop configuration file:
|
|
@@ -409,9 +436,19 @@ The MCP Inspector provides a web-based interface to:
|
|
|
409
436
|
- Debug server responses
|
|
410
437
|
- Export server configurations
|
|
411
438
|
|
|
439
|
+
## Responsive Display
|
|
440
|
+
|
|
441
|
+
ccusage automatically adapts its table layout based on your terminal width:
|
|
442
|
+
|
|
443
|
+
- **Wide terminals (≥100 characters)**: Shows all columns with bulleted model lists
|
|
444
|
+
- **Narrow terminals (<100 characters)**: Compact mode with essential columns only (Date, Models, Input, Output, Cost)
|
|
445
|
+
- **Smart formatting**: Model names displayed as clean bulleted lists (• opus-4, • sonnet-4) instead of comma-separated text
|
|
446
|
+
|
|
447
|
+
When in compact mode, ccusage displays a helpful message showing how to see the full data.
|
|
448
|
+
|
|
412
449
|
## Output Example
|
|
413
450
|
|
|
414
|
-
### Daily Report
|
|
451
|
+
### Daily Report (Wide Terminal)
|
|
415
452
|
|
|
416
453
|
```
|
|
417
454
|
╭──────────────────────────────────────────╮
|
|
@@ -423,14 +460,41 @@ The MCP Inspector provides a web-based interface to:
|
|
|
423
460
|
┌──────────────┬──────────────────┬────────┬─────────┬──────────────┬────────────┬──────────────┬────────────┐
|
|
424
461
|
│ Date │ Models │ Input │ Output │ Cache Create │ Cache Read │ Total Tokens │ Cost (USD) │
|
|
425
462
|
├──────────────┼──────────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┤
|
|
426
|
-
│ 2025-05-30 │ opus-4
|
|
427
|
-
│
|
|
428
|
-
│ 2025-05-
|
|
463
|
+
│ 2025-05-30 │ • opus-4 │ 277 │ 31,456 │ 512 │ 1,024 │ 33,269 │ $17.58 │
|
|
464
|
+
│ │ • sonnet-4 │ │ │ │ │ │ │
|
|
465
|
+
│ 2025-05-29 │ • sonnet-4 │ 959 │ 39,662 │ 256 │ 768 │ 41,645 │ $16.42 │
|
|
466
|
+
│ 2025-05-28 │ • opus-4 │ 155 │ 21,693 │ 128 │ 512 │ 22,488 │ $8.36 │
|
|
429
467
|
├──────────────┼──────────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┤
|
|
430
468
|
│ Total │ │ 11,174 │ 720,366 │ 896 │ 2,304 │ 734,740 │ $336.47 │
|
|
431
469
|
└──────────────┴──────────────────┴────────┴─────────┴──────────────┴────────────┴──────────────┴────────────┘
|
|
432
470
|
```
|
|
433
471
|
|
|
472
|
+
### Daily Report (Compact Mode - Narrow Terminal)
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
╭──────────────────────────────────────────╮
|
|
476
|
+
│ │
|
|
477
|
+
│ Claude Code Token Usage Report - Daily │
|
|
478
|
+
│ │
|
|
479
|
+
╰──────────────────────────────────────────╯
|
|
480
|
+
|
|
481
|
+
┌───────────┬──────────────────┬────────┬─────────┬────────────┐
|
|
482
|
+
│ Date │ Models │ Input │ Output │ Cost (USD) │
|
|
483
|
+
├───────────┼──────────────────┼────────┼─────────┼────────────┤
|
|
484
|
+
│ 2025 │ • opus-4 │ 277 │ 31,456 │ $17.58 │
|
|
485
|
+
│ 05-30 │ • sonnet-4 │ │ │ │
|
|
486
|
+
│ 2025 │ • sonnet-4 │ 959 │ 39,662 │ $16.42 │
|
|
487
|
+
│ 05-29 │ │ │ │ │
|
|
488
|
+
│ 2025 │ • opus-4 │ 155 │ 21,693 │ $8.36 │
|
|
489
|
+
│ 05-28 │ │ │ │ │
|
|
490
|
+
├───────────┼──────────────────┼────────┼─────────┼────────────┤
|
|
491
|
+
│ Total │ │ 11,174 │ 720,366 │ $336.47 │
|
|
492
|
+
└───────────┴──────────────────┴────────┴─────────┴────────────┘
|
|
493
|
+
|
|
494
|
+
Running in Compact Mode
|
|
495
|
+
Expand terminal width to see cache metrics and total tokens
|
|
496
|
+
```
|
|
497
|
+
|
|
434
498
|
With `--breakdown` flag:
|
|
435
499
|
|
|
436
500
|
```
|
|
@@ -509,17 +573,17 @@ Thanks to [@milliondev](https://note.com/milliondev) for the original concept an
|
|
|
509
573
|
## Sponsors
|
|
510
574
|
|
|
511
575
|
<p align="center">
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
576
|
+
<a href="https://github.com/sponsors/ryoppippi">
|
|
577
|
+
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors/sponsors.svg">
|
|
578
|
+
</a>
|
|
515
579
|
</p>
|
|
516
580
|
|
|
517
581
|
## Star History
|
|
518
582
|
|
|
519
583
|
<a href="https://www.star-history.com/#ryoppippi/ccusage&Date">
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
584
|
+
<picture>
|
|
585
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=ryoppippi/ccusage&type=Date&theme=dark" />
|
|
586
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=ryoppippi/ccusage&type=Date" />
|
|
587
|
+
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=ryoppippi/ccusage&type=Date" />
|
|
588
|
+
</picture>
|
|
525
589
|
</a>
|
package/dist/calculate-cost.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-
|
|
1
|
+
import "./pricing-fetcher-CXnYw4TA.js";
|
|
2
|
+
import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-C1n0ww95.js";
|
|
3
3
|
|
|
4
4
|
//#region src/calculate-cost.d.ts
|
|
5
5
|
/**
|
package/dist/calculate-cost.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CostMode, PricingFetcher, SortOrder } from "./pricing-fetcher-
|
|
1
|
+
import { CostMode, PricingFetcher, SortOrder } from "./pricing-fetcher-CXnYw4TA.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/_session-blocks.d.ts
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Represents a single usage data entry loaded from JSONL files
|
|
@@ -47,9 +47,16 @@ type SessionBlock = {
|
|
|
47
47
|
*/
|
|
48
48
|
//#endregion
|
|
49
49
|
//#region src/data-loader.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* Get all Claude data directories to search for usage data
|
|
52
|
+
* Supports multiple paths: environment variable (comma-separated), new default, and old default
|
|
53
|
+
* @returns Array of valid Claude data directory paths
|
|
54
|
+
*/
|
|
55
|
+
declare function getClaudePaths(): string[];
|
|
50
56
|
/**
|
|
51
57
|
* Default path for Claude data directory
|
|
52
58
|
* Uses environment variable CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
|
|
59
|
+
* @deprecated Use getClaudePaths() instead for multiple path support
|
|
53
60
|
*/
|
|
54
61
|
declare function getDefaultClaudePath(): string;
|
|
55
62
|
/**
|
|
@@ -461,4 +468,4 @@ declare function loadMonthlyUsageData(options?: LoadOptions): Promise<MonthlyUsa
|
|
|
461
468
|
*/
|
|
462
469
|
declare function loadSessionBlockData(options?: LoadOptions): Promise<SessionBlock[]>;
|
|
463
470
|
//#endregion
|
|
464
|
-
export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
|
|
471
|
+
export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx } from "./pricing-fetcher-
|
|
2
|
-
import { activityDateSchema, arrayType, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, versionSchema } from "./
|
|
3
|
-
import { logger } from "./logger-
|
|
1
|
+
import { CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx } from "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import { activityDateSchema, arrayType, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, versionSchema } from "./_types-Cr2YEzKm.js";
|
|
3
|
+
import { logger } from "./logger-fRKbFGRA.js";
|
|
4
4
|
import a, { readFile } from "node:fs/promises";
|
|
5
5
|
import F, { homedir } from "node:os";
|
|
6
6
|
import path, { posix } from "node:path";
|
|
7
7
|
import process$1 from "node:process";
|
|
8
8
|
import b from "node:fs";
|
|
9
|
+
function toArray(array) {
|
|
10
|
+
array = array ?? [];
|
|
11
|
+
return Array.isArray(array) ? array : [array];
|
|
12
|
+
}
|
|
13
|
+
const VOID = Symbol("p-void");
|
|
9
14
|
/**
|
|
10
15
|
* Return `true` if the type of `x` is `string`.
|
|
11
16
|
*
|
|
@@ -3233,20 +3238,67 @@ function filterRecentBlocks(blocks, days = DEFAULT_RECENT_DAYS) {
|
|
|
3233
3238
|
}
|
|
3234
3239
|
var import_usingCtx = __toESM(require_usingCtx(), 1);
|
|
3235
3240
|
/**
|
|
3241
|
+
* Get all Claude data directories to search for usage data
|
|
3242
|
+
* Supports multiple paths: environment variable (comma-separated), new default, and old default
|
|
3243
|
+
* @returns Array of valid Claude data directory paths
|
|
3244
|
+
*/
|
|
3245
|
+
function getClaudePaths() {
|
|
3246
|
+
const paths = [];
|
|
3247
|
+
const normalizedPaths = /* @__PURE__ */ new Set();
|
|
3248
|
+
const envPaths = (process$1.env[CLAUDE_CONFIG_DIR_ENV] ?? "").trim();
|
|
3249
|
+
if (envPaths !== "") {
|
|
3250
|
+
const envPathList = envPaths.split(",").map((p) => p.trim()).filter((p) => p !== "");
|
|
3251
|
+
for (const envPath of envPathList) {
|
|
3252
|
+
const normalizedPath = path.resolve(envPath);
|
|
3253
|
+
if (isDirectorySync(normalizedPath)) {
|
|
3254
|
+
const projectsPath = path.join(normalizedPath, CLAUDE_PROJECTS_DIR_NAME);
|
|
3255
|
+
if (isDirectorySync(projectsPath)) {
|
|
3256
|
+
if (!normalizedPaths.has(normalizedPath)) {
|
|
3257
|
+
normalizedPaths.add(normalizedPath);
|
|
3258
|
+
paths.push(normalizedPath);
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
const defaultPaths = [path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CONFIG_PATH), path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH)];
|
|
3265
|
+
for (const defaultPath of defaultPaths) {
|
|
3266
|
+
const normalizedPath = path.resolve(defaultPath);
|
|
3267
|
+
if (isDirectorySync(normalizedPath)) {
|
|
3268
|
+
const projectsPath = path.join(normalizedPath, CLAUDE_PROJECTS_DIR_NAME);
|
|
3269
|
+
if (isDirectorySync(projectsPath)) {
|
|
3270
|
+
if (!normalizedPaths.has(normalizedPath)) {
|
|
3271
|
+
normalizedPaths.add(normalizedPath);
|
|
3272
|
+
paths.push(normalizedPath);
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
if (paths.length === 0) throw new Error(`No valid Claude data directories found. Please ensure at least one of the following exists:
|
|
3278
|
+
- ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CONFIG_PATH, CLAUDE_PROJECTS_DIR_NAME)}
|
|
3279
|
+
- ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH, CLAUDE_PROJECTS_DIR_NAME)}
|
|
3280
|
+
- Or set ${CLAUDE_CONFIG_DIR_ENV} environment variable to valid directory path(s) containing a '${CLAUDE_PROJECTS_DIR_NAME}' subdirectory`.trim());
|
|
3281
|
+
return paths;
|
|
3282
|
+
}
|
|
3283
|
+
/**
|
|
3236
3284
|
* Default path for Claude data directory
|
|
3237
3285
|
* Uses environment variable CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
|
|
3286
|
+
* @deprecated Use getClaudePaths() instead for multiple path support
|
|
3238
3287
|
*/
|
|
3239
3288
|
function getDefaultClaudePath() {
|
|
3240
|
-
const
|
|
3241
|
-
if (
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
return
|
|
3289
|
+
const envPath = (process$1.env[CLAUDE_CONFIG_DIR_ENV] ?? "").trim();
|
|
3290
|
+
if (envPath !== "") {
|
|
3291
|
+
const firstPath = envPath.split(",")[0]?.trim();
|
|
3292
|
+
if (firstPath != null && firstPath !== "") {
|
|
3293
|
+
if (!isDirectorySync(firstPath)) throw new Error(`CLAUDE_CONFIG_DIR path is not a valid directory: ${firstPath}`);
|
|
3294
|
+
return firstPath;
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
const newDefaultPath = path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CONFIG_PATH);
|
|
3298
|
+
if (isDirectorySync(newDefaultPath)) return newDefaultPath;
|
|
3299
|
+
const oldDefaultPath = path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH);
|
|
3300
|
+
if (isDirectorySync(oldDefaultPath)) return oldDefaultPath;
|
|
3301
|
+
return oldDefaultPath;
|
|
3250
3302
|
}
|
|
3251
3303
|
/**
|
|
3252
3304
|
* Zod schema for validating Claude usage data from JSONL files
|
|
@@ -3559,14 +3611,18 @@ async function calculateCostForEntry(data, mode, fetcher) {
|
|
|
3559
3611
|
async function loadDailyUsageData(options) {
|
|
3560
3612
|
try {
|
|
3561
3613
|
var _usingCtx = (0, import_usingCtx.default)();
|
|
3562
|
-
const
|
|
3563
|
-
const
|
|
3564
|
-
const
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3614
|
+
const claudePaths = toArray(options?.claudePath ?? getClaudePaths());
|
|
3615
|
+
const allFiles = [];
|
|
3616
|
+
for (const claudePath of claudePaths) {
|
|
3617
|
+
const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
|
|
3618
|
+
const files = await glob([USAGE_DATA_GLOB_PATTERN], {
|
|
3619
|
+
cwd: claudeDir,
|
|
3620
|
+
absolute: true
|
|
3621
|
+
});
|
|
3622
|
+
allFiles.push(...files);
|
|
3623
|
+
}
|
|
3624
|
+
if (allFiles.length === 0) return [];
|
|
3625
|
+
const sortedFiles = await sortFilesByTimestamp(allFiles);
|
|
3570
3626
|
const mode = options?.mode ?? "auto";
|
|
3571
3627
|
const fetcher = _usingCtx.u(mode === "display" ? null : new PricingFetcher(options?.offline));
|
|
3572
3628
|
const processedHashes = /* @__PURE__ */ new Set();
|
|
@@ -3623,20 +3679,31 @@ async function loadDailyUsageData(options) {
|
|
|
3623
3679
|
async function loadSessionData(options) {
|
|
3624
3680
|
try {
|
|
3625
3681
|
var _usingCtx3 = (0, import_usingCtx.default)();
|
|
3626
|
-
const
|
|
3627
|
-
const
|
|
3628
|
-
const
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3682
|
+
const claudePaths = toArray(options?.claudePath ?? getClaudePaths());
|
|
3683
|
+
const filesWithBase = [];
|
|
3684
|
+
for (const claudePath of claudePaths) {
|
|
3685
|
+
const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
|
|
3686
|
+
const files = await glob([USAGE_DATA_GLOB_PATTERN], {
|
|
3687
|
+
cwd: claudeDir,
|
|
3688
|
+
absolute: true
|
|
3689
|
+
});
|
|
3690
|
+
for (const file of files) filesWithBase.push({
|
|
3691
|
+
file,
|
|
3692
|
+
baseDir: claudeDir
|
|
3693
|
+
});
|
|
3694
|
+
}
|
|
3695
|
+
if (filesWithBase.length === 0) return [];
|
|
3696
|
+
const fileToBaseMap = new Map(filesWithBase.map((f$1) => [f$1.file, f$1.baseDir]));
|
|
3697
|
+
const sortedFilesWithBase = await sortFilesByTimestamp(filesWithBase.map((f$1) => f$1.file)).then((sortedFiles) => sortedFiles.map((file) => ({
|
|
3698
|
+
file,
|
|
3699
|
+
baseDir: fileToBaseMap.get(file) ?? ""
|
|
3700
|
+
})));
|
|
3634
3701
|
const mode = options?.mode ?? "auto";
|
|
3635
3702
|
const fetcher = _usingCtx3.u(mode === "display" ? null : new PricingFetcher(options?.offline));
|
|
3636
3703
|
const processedHashes = /* @__PURE__ */ new Set();
|
|
3637
3704
|
const allEntries = [];
|
|
3638
|
-
for (const file of
|
|
3639
|
-
const relativePath = path.relative(
|
|
3705
|
+
for (const { file, baseDir } of sortedFilesWithBase) {
|
|
3706
|
+
const relativePath = path.relative(baseDir, file);
|
|
3640
3707
|
const parts = relativePath.split(path.sep);
|
|
3641
3708
|
const sessionId = parts[parts.length - 2] ?? "unknown";
|
|
3642
3709
|
const joinedPath = parts.slice(0, -2).join(path.sep);
|
|
@@ -3744,14 +3811,18 @@ async function loadMonthlyUsageData(options) {
|
|
|
3744
3811
|
async function loadSessionBlockData(options) {
|
|
3745
3812
|
try {
|
|
3746
3813
|
var _usingCtx4 = (0, import_usingCtx.default)();
|
|
3747
|
-
const
|
|
3748
|
-
const
|
|
3749
|
-
const
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3814
|
+
const claudePaths = toArray(options?.claudePath ?? getClaudePaths());
|
|
3815
|
+
const allFiles = [];
|
|
3816
|
+
for (const claudePath of claudePaths) {
|
|
3817
|
+
const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
|
|
3818
|
+
const files = await glob([USAGE_DATA_GLOB_PATTERN], {
|
|
3819
|
+
cwd: claudeDir,
|
|
3820
|
+
absolute: true
|
|
3821
|
+
});
|
|
3822
|
+
allFiles.push(...files);
|
|
3823
|
+
}
|
|
3824
|
+
if (allFiles.length === 0) return [];
|
|
3825
|
+
const sortedFiles = await sortFilesByTimestamp(allFiles);
|
|
3755
3826
|
const mode = options?.mode ?? "auto";
|
|
3756
3827
|
const fetcher = _usingCtx4.u(mode === "display" ? null : new PricingFetcher());
|
|
3757
3828
|
const processedHashes = /* @__PURE__ */ new Set();
|
|
@@ -3798,4 +3869,4 @@ async function loadSessionBlockData(options) {
|
|
|
3798
3869
|
_usingCtx4.d();
|
|
3799
3870
|
}
|
|
3800
3871
|
}
|
|
3801
|
-
export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, usageDataSchema };
|
|
3872
|
+
export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, usageDataSchema };
|
package/dist/data-loader.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-
|
|
3
|
-
export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
|
|
1
|
+
import "./pricing-fetcher-CXnYw4TA.js";
|
|
2
|
+
import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-C1n0ww95.js";
|
|
3
|
+
export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
|
package/dist/data-loader.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import "./
|
|
3
|
-
import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-
|
|
4
|
-
import "./logger-
|
|
5
|
-
export { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
|
|
1
|
+
import "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import "./_types-Cr2YEzKm.js";
|
|
3
|
+
import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-C8KM6jhg.js";
|
|
4
|
+
import "./logger-fRKbFGRA.js";
|
|
5
|
+
export { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __toESM, require_usingCtx } from "./pricing-fetcher-
|
|
2
|
-
import { glob, usageDataSchema } from "./data-loader-
|
|
3
|
-
import { logger } from "./logger-
|
|
1
|
+
import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __toESM, require_usingCtx } from "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import { glob, usageDataSchema } from "./data-loader-C8KM6jhg.js";
|
|
3
|
+
import { logger } from "./logger-fRKbFGRA.js";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
var import_usingCtx = __toESM(require_usingCtx(), 1);
|
package/dist/debug.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import "./
|
|
3
|
-
import "./data-loader-
|
|
4
|
-
import "./logger-
|
|
5
|
-
import { detectMismatches, printMismatchReport } from "./debug-
|
|
1
|
+
import "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import "./_types-Cr2YEzKm.js";
|
|
3
|
+
import "./data-loader-C8KM6jhg.js";
|
|
4
|
+
import "./logger-fRKbFGRA.js";
|
|
5
|
+
import { detectMismatches, printMismatchReport } from "./debug-BJaJWLMi.js";
|
|
6
6
|
export { detectMismatches, printMismatchReport };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, DEFAULT_RECENT_DAYS, MCP_DEFAULT_PORT, __commonJSMin, __require, __toESM } from "./pricing-fetcher-
|
|
3
|
-
import { CostModes, SortOrders, dateSchema } from "./
|
|
2
|
+
import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, DEFAULT_RECENT_DAYS, MCP_DEFAULT_PORT, __commonJSMin, __require, __toESM } from "./pricing-fetcher-Dup-4216.js";
|
|
3
|
+
import { CostModes, SortOrders, dateSchema } from "./_types-Cr2YEzKm.js";
|
|
4
4
|
import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-CoS7we68.js";
|
|
5
|
-
import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, filterRecentBlocks, formatDateCompact, getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, uniq } from "./data-loader-
|
|
6
|
-
import { description, log, logger, name, version } from "./logger-
|
|
7
|
-
import { detectMismatches, printMismatchReport } from "./debug-
|
|
8
|
-
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-
|
|
5
|
+
import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, filterRecentBlocks, formatDateCompact, getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, projectBlockUsage, uniq } from "./data-loader-C8KM6jhg.js";
|
|
6
|
+
import { description, log, logger, name, version } from "./logger-fRKbFGRA.js";
|
|
7
|
+
import { detectMismatches, printMismatchReport } from "./debug-BJaJWLMi.js";
|
|
8
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-Beq_0A1e.js";
|
|
9
9
|
import process$1 from "node:process";
|
|
10
10
|
import { createServer } from "node:http";
|
|
11
11
|
import { Http2ServerRequest } from "node:http2";
|
|
@@ -2940,6 +2940,10 @@ var ResponsiveTable = class {
|
|
|
2940
2940
|
colAligns;
|
|
2941
2941
|
style;
|
|
2942
2942
|
dateFormatter;
|
|
2943
|
+
compactHead;
|
|
2944
|
+
compactColAligns;
|
|
2945
|
+
compactThreshold;
|
|
2946
|
+
compactMode = false;
|
|
2943
2947
|
/**
|
|
2944
2948
|
* Creates a new responsive table instance
|
|
2945
2949
|
* @param options - Table configuration options
|
|
@@ -2949,6 +2953,9 @@ var ResponsiveTable = class {
|
|
|
2949
2953
|
this.colAligns = options.colAligns ?? Array.from({ length: this.head.length }, () => "left");
|
|
2950
2954
|
this.style = options.style;
|
|
2951
2955
|
this.dateFormatter = options.dateFormatter;
|
|
2956
|
+
this.compactHead = options.compactHead;
|
|
2957
|
+
this.compactColAligns = options.compactColAligns;
|
|
2958
|
+
this.compactThreshold = options.compactThreshold ?? 100;
|
|
2952
2959
|
}
|
|
2953
2960
|
/**
|
|
2954
2961
|
* Adds a row to the table
|
|
@@ -2958,26 +2965,75 @@ var ResponsiveTable = class {
|
|
|
2958
2965
|
this.rows.push(row);
|
|
2959
2966
|
}
|
|
2960
2967
|
/**
|
|
2968
|
+
* Filters a row to compact mode columns
|
|
2969
|
+
* @param row - Row to filter
|
|
2970
|
+
* @param compactIndices - Indices of columns to keep in compact mode
|
|
2971
|
+
* @returns Filtered row
|
|
2972
|
+
*/
|
|
2973
|
+
filterRowToCompact(row, compactIndices) {
|
|
2974
|
+
return compactIndices.map((index) => row[index] ?? "");
|
|
2975
|
+
}
|
|
2976
|
+
/**
|
|
2977
|
+
* Gets the current table head and col aligns based on compact mode
|
|
2978
|
+
* @returns Current head and colAligns arrays
|
|
2979
|
+
*/
|
|
2980
|
+
getCurrentTableConfig() {
|
|
2981
|
+
if (this.compactMode && this.compactHead != null && this.compactColAligns != null) return {
|
|
2982
|
+
head: this.compactHead,
|
|
2983
|
+
colAligns: this.compactColAligns
|
|
2984
|
+
};
|
|
2985
|
+
return {
|
|
2986
|
+
head: this.head,
|
|
2987
|
+
colAligns: this.colAligns
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
/**
|
|
2991
|
+
* Gets indices mapping from full table to compact table
|
|
2992
|
+
* @returns Array of column indices to keep in compact mode
|
|
2993
|
+
*/
|
|
2994
|
+
getCompactIndices() {
|
|
2995
|
+
if (this.compactHead == null || !this.compactMode) return Array.from({ length: this.head.length }, (_, i) => i);
|
|
2996
|
+
return this.compactHead.map((compactHeader) => {
|
|
2997
|
+
const index = this.head.indexOf(compactHeader);
|
|
2998
|
+
if (index < 0) {
|
|
2999
|
+
console.warn(`Warning: Compact header "${compactHeader}" not found in table headers [${this.head.join(", ")}]. Using first column as fallback.`);
|
|
3000
|
+
return 0;
|
|
3001
|
+
}
|
|
3002
|
+
return index;
|
|
3003
|
+
});
|
|
3004
|
+
}
|
|
3005
|
+
/**
|
|
3006
|
+
* Returns whether the table is currently in compact mode
|
|
3007
|
+
* @returns True if compact mode is active
|
|
3008
|
+
*/
|
|
3009
|
+
isCompactMode() {
|
|
3010
|
+
return this.compactMode;
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
2961
3013
|
* Renders the table as a formatted string
|
|
2962
3014
|
* Automatically adjusts layout based on terminal width
|
|
2963
3015
|
* @returns Formatted table string
|
|
2964
3016
|
*/
|
|
2965
3017
|
toString() {
|
|
2966
|
-
const terminalWidth = process$1.stdout.columns || 120;
|
|
3018
|
+
const terminalWidth = Number.parseInt(process$1.env.COLUMNS ?? "", 10) || process$1.stdout.columns || 120;
|
|
3019
|
+
this.compactMode = terminalWidth < this.compactThreshold && this.compactHead != null;
|
|
3020
|
+
const { head, colAligns } = this.getCurrentTableConfig();
|
|
3021
|
+
const compactIndices = this.getCompactIndices();
|
|
2967
3022
|
const dataRows = this.rows.filter((row) => !this.isSeparatorRow(row));
|
|
2968
|
-
const
|
|
3023
|
+
const processedDataRows = this.compactMode ? dataRows.map((row) => this.filterRowToCompact(row, compactIndices)) : dataRows;
|
|
3024
|
+
const allRows = [head.map(String), ...processedDataRows.map((row) => row.map((cell) => {
|
|
2969
3025
|
if (typeof cell === "object" && cell != null && "content" in cell) return String(cell.content);
|
|
2970
3026
|
return String(cell ?? "");
|
|
2971
3027
|
}))];
|
|
2972
|
-
const contentWidths =
|
|
3028
|
+
const contentWidths = head.map((_, colIndex) => {
|
|
2973
3029
|
const maxLength = Math.max(...allRows.map((row) => stringWidth(String(row[colIndex] ?? ""))));
|
|
2974
3030
|
return maxLength;
|
|
2975
3031
|
});
|
|
2976
|
-
const numColumns =
|
|
3032
|
+
const numColumns = head.length;
|
|
2977
3033
|
const tableOverhead = 3 * numColumns + 1;
|
|
2978
3034
|
const availableWidth = terminalWidth - tableOverhead;
|
|
2979
3035
|
const columnWidths = contentWidths.map((width, index) => {
|
|
2980
|
-
const align =
|
|
3036
|
+
const align = colAligns[index];
|
|
2981
3037
|
if (align === "right") return Math.max(width + 3, 11);
|
|
2982
3038
|
else if (index === 1) return Math.max(width + 2, 15);
|
|
2983
3039
|
return Math.max(width + 2, 10);
|
|
@@ -2986,7 +3042,7 @@ var ResponsiveTable = class {
|
|
|
2986
3042
|
if (totalRequiredWidth > terminalWidth) {
|
|
2987
3043
|
const scaleFactor = availableWidth / columnWidths.reduce((sum, width) => sum + width, 0);
|
|
2988
3044
|
const adjustedWidths = columnWidths.map((width, index) => {
|
|
2989
|
-
const align =
|
|
3045
|
+
const align = colAligns[index];
|
|
2990
3046
|
let adjustedWidth = Math.floor(width * scaleFactor);
|
|
2991
3047
|
if (align === "right") adjustedWidth = Math.max(adjustedWidth, 10);
|
|
2992
3048
|
else if (index === 0) adjustedWidth = Math.max(adjustedWidth, 10);
|
|
@@ -2995,33 +3051,37 @@ var ResponsiveTable = class {
|
|
|
2995
3051
|
return adjustedWidth;
|
|
2996
3052
|
});
|
|
2997
3053
|
const table = new import_cli_table3.default({
|
|
2998
|
-
head
|
|
3054
|
+
head,
|
|
2999
3055
|
style: this.style,
|
|
3000
|
-
colAligns
|
|
3056
|
+
colAligns,
|
|
3001
3057
|
colWidths: adjustedWidths,
|
|
3002
3058
|
wordWrap: true,
|
|
3003
3059
|
wrapOnWordBoundary: true
|
|
3004
3060
|
});
|
|
3005
3061
|
for (const row of this.rows) if (this.isSeparatorRow(row)) continue;
|
|
3006
3062
|
else {
|
|
3007
|
-
|
|
3063
|
+
let processedRow = row.map((cell, index) => {
|
|
3008
3064
|
if (index === 0 && this.dateFormatter != null && typeof cell === "string" && this.isDateString(cell)) return this.dateFormatter(cell);
|
|
3009
3065
|
return cell;
|
|
3010
3066
|
});
|
|
3067
|
+
if (this.compactMode) processedRow = this.filterRowToCompact(processedRow, compactIndices);
|
|
3011
3068
|
table.push(processedRow);
|
|
3012
3069
|
}
|
|
3013
3070
|
return table.toString();
|
|
3014
3071
|
} else {
|
|
3015
3072
|
const table = new import_cli_table3.default({
|
|
3016
|
-
head
|
|
3073
|
+
head,
|
|
3017
3074
|
style: this.style,
|
|
3018
|
-
colAligns
|
|
3075
|
+
colAligns,
|
|
3019
3076
|
colWidths: columnWidths,
|
|
3020
3077
|
wordWrap: true,
|
|
3021
3078
|
wrapOnWordBoundary: true
|
|
3022
3079
|
});
|
|
3023
3080
|
for (const row of this.rows) if (this.isSeparatorRow(row)) continue;
|
|
3024
|
-
else
|
|
3081
|
+
else {
|
|
3082
|
+
const processedRow = this.compactMode ? this.filterRowToCompact(row, compactIndices) : row;
|
|
3083
|
+
table.push(processedRow);
|
|
3084
|
+
}
|
|
3025
3085
|
return table.toString();
|
|
3026
3086
|
}
|
|
3027
3087
|
}
|
|
@@ -3073,14 +3133,14 @@ function formatModelName(modelName) {
|
|
|
3073
3133
|
return modelName;
|
|
3074
3134
|
}
|
|
3075
3135
|
/**
|
|
3076
|
-
* Formats an array of model names for display
|
|
3136
|
+
* Formats an array of model names for display with each model on a new line
|
|
3077
3137
|
* Removes duplicates and sorts alphabetically
|
|
3078
3138
|
* @param models - Array of model names
|
|
3079
|
-
* @returns Formatted string with unique, sorted model names
|
|
3139
|
+
* @returns Formatted string with unique, sorted model names as a bulleted list
|
|
3080
3140
|
*/
|
|
3081
|
-
function
|
|
3141
|
+
function formatModelsDisplayMultiline(models) {
|
|
3082
3142
|
const uniqueModels = uniq(models.map(formatModelName));
|
|
3083
|
-
return uniqueModels.sort().join("
|
|
3143
|
+
return uniqueModels.sort().map((model) => `- ${model}`).join("\n");
|
|
3084
3144
|
}
|
|
3085
3145
|
/**
|
|
3086
3146
|
* Pushes model breakdown rows to a table
|
|
@@ -3143,12 +3203,11 @@ function formatBlockTime(block, compact = false) {
|
|
|
3143
3203
|
/**
|
|
3144
3204
|
* Formats the list of models used in a block for display
|
|
3145
3205
|
* @param models - Array of model names
|
|
3146
|
-
* @param compact - Whether to use compact formatting (unused currently)
|
|
3147
3206
|
* @returns Formatted model names string
|
|
3148
3207
|
*/
|
|
3149
|
-
function formatModels(models
|
|
3208
|
+
function formatModels(models) {
|
|
3150
3209
|
if (models.length === 0) return "-";
|
|
3151
|
-
return
|
|
3210
|
+
return formatModelsDisplayMultiline(models);
|
|
3152
3211
|
}
|
|
3153
3212
|
/**
|
|
3154
3213
|
* Parses token limit argument, supporting 'max' keyword
|
|
@@ -3347,7 +3406,7 @@ const blocksCommand = define({
|
|
|
3347
3406
|
const row = [
|
|
3348
3407
|
formatBlockTime(block, useCompactFormat),
|
|
3349
3408
|
status,
|
|
3350
|
-
formatModels(block.models
|
|
3409
|
+
formatModels(block.models),
|
|
3351
3410
|
formatNumber(totalTokens)
|
|
3352
3411
|
];
|
|
3353
3412
|
if (actualTokenLimit != null && actualTokenLimit > 0) {
|
|
@@ -3469,12 +3528,27 @@ const dailyCommand = define({
|
|
|
3469
3528
|
"right",
|
|
3470
3529
|
"right"
|
|
3471
3530
|
],
|
|
3472
|
-
dateFormatter: formatDateCompact
|
|
3531
|
+
dateFormatter: formatDateCompact,
|
|
3532
|
+
compactHead: [
|
|
3533
|
+
"Date",
|
|
3534
|
+
"Models",
|
|
3535
|
+
"Input",
|
|
3536
|
+
"Output",
|
|
3537
|
+
"Cost (USD)"
|
|
3538
|
+
],
|
|
3539
|
+
compactColAligns: [
|
|
3540
|
+
"left",
|
|
3541
|
+
"left",
|
|
3542
|
+
"right",
|
|
3543
|
+
"right",
|
|
3544
|
+
"right"
|
|
3545
|
+
],
|
|
3546
|
+
compactThreshold: 100
|
|
3473
3547
|
});
|
|
3474
3548
|
for (const data of dailyData) {
|
|
3475
3549
|
table.push([
|
|
3476
3550
|
data.date,
|
|
3477
|
-
|
|
3551
|
+
formatModelsDisplayMultiline(data.modelsUsed),
|
|
3478
3552
|
formatNumber(data.inputTokens),
|
|
3479
3553
|
formatNumber(data.outputTokens),
|
|
3480
3554
|
formatNumber(data.cacheCreationTokens),
|
|
@@ -3505,6 +3579,10 @@ const dailyCommand = define({
|
|
|
3505
3579
|
import_picocolors$2.default.yellow(formatCurrency(totals.totalCost))
|
|
3506
3580
|
]);
|
|
3507
3581
|
log(table.toString());
|
|
3582
|
+
if (table.isCompactMode()) {
|
|
3583
|
+
logger.info("\nRunning in Compact Mode");
|
|
3584
|
+
logger.info("Expand terminal width to see cache metrics and total tokens");
|
|
3585
|
+
}
|
|
3508
3586
|
}
|
|
3509
3587
|
}
|
|
3510
3588
|
});
|
|
@@ -3992,12 +4070,27 @@ const monthlyCommand = define({
|
|
|
3992
4070
|
"right",
|
|
3993
4071
|
"right"
|
|
3994
4072
|
],
|
|
3995
|
-
dateFormatter: formatDateCompact
|
|
4073
|
+
dateFormatter: formatDateCompact,
|
|
4074
|
+
compactHead: [
|
|
4075
|
+
"Month",
|
|
4076
|
+
"Models",
|
|
4077
|
+
"Input",
|
|
4078
|
+
"Output",
|
|
4079
|
+
"Cost (USD)"
|
|
4080
|
+
],
|
|
4081
|
+
compactColAligns: [
|
|
4082
|
+
"left",
|
|
4083
|
+
"left",
|
|
4084
|
+
"right",
|
|
4085
|
+
"right",
|
|
4086
|
+
"right"
|
|
4087
|
+
],
|
|
4088
|
+
compactThreshold: 100
|
|
3996
4089
|
});
|
|
3997
4090
|
for (const data of monthlyData) {
|
|
3998
4091
|
table.push([
|
|
3999
4092
|
data.month,
|
|
4000
|
-
|
|
4093
|
+
formatModelsDisplayMultiline(data.modelsUsed),
|
|
4001
4094
|
formatNumber(data.inputTokens),
|
|
4002
4095
|
formatNumber(data.outputTokens),
|
|
4003
4096
|
formatNumber(data.cacheCreationTokens),
|
|
@@ -4028,6 +4121,10 @@ const monthlyCommand = define({
|
|
|
4028
4121
|
import_picocolors$1.default.yellow(formatCurrency(totals.totalCost))
|
|
4029
4122
|
]);
|
|
4030
4123
|
log(table.toString());
|
|
4124
|
+
if (table.isCompactMode()) {
|
|
4125
|
+
logger.info("\nRunning in Compact Mode");
|
|
4126
|
+
logger.info("Expand terminal width to see cache metrics and total tokens");
|
|
4127
|
+
}
|
|
4031
4128
|
}
|
|
4032
4129
|
}
|
|
4033
4130
|
});
|
|
@@ -4099,7 +4196,24 @@ const sessionCommand = define({
|
|
|
4099
4196
|
"right",
|
|
4100
4197
|
"left"
|
|
4101
4198
|
],
|
|
4102
|
-
dateFormatter: formatDateCompact
|
|
4199
|
+
dateFormatter: formatDateCompact,
|
|
4200
|
+
compactHead: [
|
|
4201
|
+
"Session",
|
|
4202
|
+
"Models",
|
|
4203
|
+
"Input",
|
|
4204
|
+
"Output",
|
|
4205
|
+
"Cost (USD)",
|
|
4206
|
+
"Last Activity"
|
|
4207
|
+
],
|
|
4208
|
+
compactColAligns: [
|
|
4209
|
+
"left",
|
|
4210
|
+
"left",
|
|
4211
|
+
"right",
|
|
4212
|
+
"right",
|
|
4213
|
+
"right",
|
|
4214
|
+
"left"
|
|
4215
|
+
],
|
|
4216
|
+
compactThreshold: 100
|
|
4103
4217
|
});
|
|
4104
4218
|
let maxSessionLength = 0;
|
|
4105
4219
|
for (const data of sessionData) {
|
|
@@ -4107,7 +4221,7 @@ const sessionCommand = define({
|
|
|
4107
4221
|
maxSessionLength = Math.max(maxSessionLength, sessionDisplay.length);
|
|
4108
4222
|
table.push([
|
|
4109
4223
|
sessionDisplay,
|
|
4110
|
-
|
|
4224
|
+
formatModelsDisplayMultiline(data.modelsUsed),
|
|
4111
4225
|
formatNumber(data.inputTokens),
|
|
4112
4226
|
formatNumber(data.outputTokens),
|
|
4113
4227
|
formatNumber(data.cacheCreationTokens),
|
|
@@ -4141,6 +4255,10 @@ const sessionCommand = define({
|
|
|
4141
4255
|
""
|
|
4142
4256
|
]);
|
|
4143
4257
|
log(table.toString());
|
|
4258
|
+
if (table.isCompactMode()) {
|
|
4259
|
+
logger.info("\nRunning in Compact Mode");
|
|
4260
|
+
logger.info("Expand terminal width to see cache metrics and total tokens");
|
|
4261
|
+
}
|
|
4144
4262
|
}
|
|
4145
4263
|
}
|
|
4146
4264
|
});
|
|
@@ -951,7 +951,7 @@ function _getDefaultLogLevel() {
|
|
|
951
951
|
}
|
|
952
952
|
const consola = createConsola$1();
|
|
953
953
|
var name = "ccusage";
|
|
954
|
-
var version = "
|
|
954
|
+
var version = "14.0.0";
|
|
955
955
|
var description = "Usage analysis tool for Claude Code";
|
|
956
956
|
/**
|
|
957
957
|
* Application logger instance with package name tag
|
package/dist/logger.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { log, logger } from "./logger-
|
|
1
|
+
import { log, logger } from "./logger-fRKbFGRA.js";
|
|
2
2
|
export { log, logger };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-
|
|
2
|
-
import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, dateSchema, discriminatedUnionType, enumType, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./
|
|
3
|
-
import { getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-
|
|
4
|
-
import { name, version } from "./logger-
|
|
1
|
+
import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, dateSchema, discriminatedUnionType, enumType, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-Cr2YEzKm.js";
|
|
3
|
+
import { getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-C8KM6jhg.js";
|
|
4
|
+
import { name, version } from "./logger-fRKbFGRA.js";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
const LATEST_PROTOCOL_VERSION = "2025-03-26";
|
|
7
7
|
const SUPPORTED_PROTOCOL_VERSIONS = [
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import { LoadOptions } from "./data-loader-
|
|
1
|
+
import "./pricing-fetcher-CXnYw4TA.js";
|
|
2
|
+
import { LoadOptions } from "./data-loader-C1n0ww95.js";
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import { Hono } from "hono/tiny";
|
|
5
5
|
|
package/dist/mcp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import "./
|
|
3
|
-
import "./data-loader-
|
|
4
|
-
import "./logger-
|
|
5
|
-
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-
|
|
1
|
+
import "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import "./_types-Cr2YEzKm.js";
|
|
3
|
+
import "./data-loader-C8KM6jhg.js";
|
|
4
|
+
import "./logger-fRKbFGRA.js";
|
|
5
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-Beq_0A1e.js";
|
|
6
6
|
export { createMcpHttpApp, createMcpServer, startMcpServerStdio };
|
|
@@ -73,7 +73,7 @@ type NumberBool = typeof numberBool[number];
|
|
|
73
73
|
*/
|
|
74
74
|
type TupleToUnion<ArrayType> = ArrayType extends readonly unknown[] ? ArrayType[number] : never;
|
|
75
75
|
//#endregion
|
|
76
|
-
//#region src/
|
|
76
|
+
//#region src/_types.d.ts
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* Available cost calculation modes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { modelPricingSchema } from "./
|
|
2
|
-
import { logger } from "./logger-
|
|
1
|
+
import { modelPricingSchema } from "./_types-Cr2YEzKm.js";
|
|
2
|
+
import { logger } from "./logger-fRKbFGRA.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
var __create = Object.create;
|
|
@@ -59,6 +59,16 @@ const DEBUG_MATCH_THRESHOLD_PERCENT = .1;
|
|
|
59
59
|
*/
|
|
60
60
|
const DEFAULT_CLAUDE_CODE_PATH = ".claude";
|
|
61
61
|
/**
|
|
62
|
+
* Additional default Claude data directory path (~/.config/claude)
|
|
63
|
+
* Used as secondary path for loading usage data from JSONL files
|
|
64
|
+
*/
|
|
65
|
+
const DEFAULT_CLAUDE_CONFIG_PATH = ".config/claude";
|
|
66
|
+
/**
|
|
67
|
+
* Environment variable for specifying multiple Claude data directories
|
|
68
|
+
* Supports comma-separated paths for multiple locations
|
|
69
|
+
*/
|
|
70
|
+
const CLAUDE_CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
|
|
71
|
+
/**
|
|
62
72
|
* Claude projects directory name within the data directory
|
|
63
73
|
* Contains subdirectories for each project with usage data
|
|
64
74
|
*/
|
|
@@ -362,4 +372,4 @@ var PricingFetcher = class {
|
|
|
362
372
|
return cost;
|
|
363
373
|
}
|
|
364
374
|
};
|
|
365
|
-
export { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_RECENT_DAYS, MCP_DEFAULT_PORT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx };
|
|
375
|
+
export { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, MCP_DEFAULT_PORT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PricingFetcher } from "./pricing-fetcher-
|
|
1
|
+
import { PricingFetcher } from "./pricing-fetcher-CXnYw4TA.js";
|
|
2
2
|
export { PricingFetcher };
|
package/dist/pricing-fetcher.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PricingFetcher } from "./pricing-fetcher-
|
|
2
|
-
import "./
|
|
3
|
-
import "./logger-
|
|
1
|
+
import { PricingFetcher } from "./pricing-fetcher-Dup-4216.js";
|
|
2
|
+
import "./_types-Cr2YEzKm.js";
|
|
3
|
+
import "./logger-fRKbFGRA.js";
|
|
4
4
|
export { PricingFetcher };
|
package/package.json
CHANGED
|
File without changes
|