vibestats 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -35
- package/dist/index.js +67 -0
- package/package.json +6 -7
package/README.md
CHANGED
|
@@ -1,79 +1,98 @@
|
|
|
1
|
-
#
|
|
1
|
+
# vibestats
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI coding stats CLI for **Claude Code** and **OpenAI Codex**. Track your usage and generate annual "Spotify Wrapped" style summaries.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install -g
|
|
8
|
+
npm install -g vibestats
|
|
9
|
+
# or run directly
|
|
10
|
+
npx vibestats
|
|
9
11
|
```
|
|
10
12
|
|
|
11
13
|
## Usage
|
|
12
14
|
|
|
13
15
|
```bash
|
|
14
|
-
|
|
16
|
+
# Usage stats (default)
|
|
17
|
+
vibestats # Daily usage table
|
|
18
|
+
vibestats --monthly # Monthly aggregation
|
|
19
|
+
vibestats --model # Aggregate by model
|
|
20
|
+
vibestats --total # Show only totals
|
|
21
|
+
|
|
22
|
+
# Wrapped summary
|
|
23
|
+
vibestats --wrapped # Annual wrapped summary
|
|
15
24
|
```
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
## CLI Flags
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
- Longest and current coding streaks
|
|
21
|
-
- Peak coding hour and favorite day
|
|
22
|
-
- Model usage breakdown
|
|
23
|
-
- Words generated estimate
|
|
24
|
-
- Shareable URL to view your wrapped online
|
|
28
|
+
### Usage Mode (default)
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
| Flag | Description |
|
|
31
|
+
|------|-------------|
|
|
32
|
+
| `--monthly` | Aggregate by month |
|
|
33
|
+
| `--model` | Aggregate by model |
|
|
34
|
+
| `--total` | Show only totals |
|
|
35
|
+
| `--since YYYY-MM-DD` | Filter from date |
|
|
36
|
+
| `--until YYYY-MM-DD` | Filter to date |
|
|
37
|
+
| `--compact`, `-c` | Compact table (hide cache columns) |
|
|
38
|
+
| `--json` | Output raw JSON |
|
|
39
|
+
|
|
40
|
+
### Wrapped Mode
|
|
27
41
|
|
|
28
42
|
| Flag | Description |
|
|
29
43
|
|------|-------------|
|
|
44
|
+
| `--wrapped` | Generate wrapped summary |
|
|
30
45
|
| `--json` | Output raw JSON stats |
|
|
31
46
|
| `--quiet`, `-q` | Only output the shareable URL |
|
|
32
|
-
| `--
|
|
33
|
-
| `--init` | Create a default config file |
|
|
34
|
-
| `--config` | Show current config location and values |
|
|
47
|
+
| `--no-short` | Disable shortlink generation |
|
|
35
48
|
|
|
36
|
-
|
|
49
|
+
### Data Source
|
|
37
50
|
|
|
38
|
-
|
|
51
|
+
| Flag | Description |
|
|
52
|
+
|------|-------------|
|
|
53
|
+
| `--codex` | OpenAI Codex only |
|
|
54
|
+
| `--combined` | Claude + Codex combined |
|
|
55
|
+
|
|
56
|
+
### Config
|
|
57
|
+
|
|
58
|
+
| Flag | Description |
|
|
59
|
+
|------|-------------|
|
|
60
|
+
| `--init` | Create config file |
|
|
61
|
+
| `--config` | Show current config |
|
|
62
|
+
| `--url <url>` | Custom base URL |
|
|
63
|
+
|
|
64
|
+
## Config File
|
|
39
65
|
|
|
40
66
|
```bash
|
|
41
|
-
|
|
67
|
+
vibestats --init
|
|
42
68
|
```
|
|
43
69
|
|
|
44
|
-
|
|
70
|
+
Creates `~/.vibestats.json`:
|
|
45
71
|
|
|
46
72
|
```json
|
|
47
73
|
{
|
|
48
|
-
"baseUrl": "https://
|
|
74
|
+
"baseUrl": "https://vibestats.wolfai.dev",
|
|
49
75
|
"outputFormat": "normal",
|
|
50
|
-
"theme": {
|
|
51
|
-
"enabled": true
|
|
52
|
-
},
|
|
76
|
+
"theme": { "enabled": true },
|
|
53
77
|
"hideCost": false
|
|
54
78
|
}
|
|
55
79
|
```
|
|
56
80
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
| Option | Type | Default | Description |
|
|
60
|
-
|--------|------|---------|-------------|
|
|
61
|
-
| `baseUrl` | string | `https://wrapped.wolfai.dev` | Base URL for shareable links |
|
|
62
|
-
| `outputFormat` | `"normal"` \| `"json"` \| `"quiet"` | `"normal"` | Default output format |
|
|
63
|
-
| `theme.enabled` | boolean | `true` | Enable terminal colors |
|
|
64
|
-
| `statsCachePath` | string | `~/.claude/stats-cache.json` | Custom stats file path |
|
|
65
|
-
| `hideCost` | boolean | `false` | Hide cost from output |
|
|
81
|
+
## Data Sources
|
|
66
82
|
|
|
67
|
-
|
|
83
|
+
| Source | Location |
|
|
84
|
+
|--------|----------|
|
|
85
|
+
| Claude Code | `~/.claude/projects/**/*.jsonl` |
|
|
86
|
+
| OpenAI Codex | `~/.codex/sessions/*.jsonl` |
|
|
68
87
|
|
|
69
88
|
## Requirements
|
|
70
89
|
|
|
71
90
|
- Node.js 18+
|
|
72
|
-
- Claude Code
|
|
91
|
+
- Claude Code or OpenAI Codex CLI usage data
|
|
73
92
|
|
|
74
93
|
## View Online
|
|
75
94
|
|
|
76
|
-
Visit [
|
|
95
|
+
Visit [vibestats.wolfai.dev](https://vibestats.wolfai.dev) to view your wrapped in the browser.
|
|
77
96
|
|
|
78
97
|
## License
|
|
79
98
|
|
package/dist/index.js
CHANGED
|
@@ -1436,6 +1436,49 @@ function getModelAbbrevFromDisplayName(displayName) {
|
|
|
1436
1436
|
};
|
|
1437
1437
|
return map[displayName] || displayName.slice(0, 5).toLowerCase();
|
|
1438
1438
|
}
|
|
1439
|
+
function encodeUsageToUrl(stats, baseUrl = "https://vibestats.wolfai.dev") {
|
|
1440
|
+
const params = new URLSearchParams();
|
|
1441
|
+
const aggMap = { daily: "d", monthly: "m", model: "mo", total: "t" };
|
|
1442
|
+
params.set("agg", aggMap[stats.aggregation] || "d");
|
|
1443
|
+
if (stats.source !== "claude") {
|
|
1444
|
+
params.set("src", stats.source);
|
|
1445
|
+
}
|
|
1446
|
+
const formatDateCompact = (d) => d.replace(/-/g, "");
|
|
1447
|
+
params.set("dr", `${formatDateCompact(stats.dateRange.start)}-${formatDateCompact(stats.dateRange.end)}`);
|
|
1448
|
+
const rows = stats.rows.slice(0, 31).map((row) => {
|
|
1449
|
+
let key = row.key;
|
|
1450
|
+
if (stats.aggregation === "daily" && row.key.length === 10) {
|
|
1451
|
+
key = row.key.slice(5).replace("-", "");
|
|
1452
|
+
}
|
|
1453
|
+
return [
|
|
1454
|
+
key,
|
|
1455
|
+
formatCompactNumber(row.inputTokens),
|
|
1456
|
+
formatCompactNumber(row.outputTokens),
|
|
1457
|
+
formatCompactNumber(row.cacheWriteTokens),
|
|
1458
|
+
formatCompactNumber(row.cacheReadTokens),
|
|
1459
|
+
formatCompactNumber(row.totalTokens),
|
|
1460
|
+
row.cost.toFixed(2)
|
|
1461
|
+
].join(":");
|
|
1462
|
+
});
|
|
1463
|
+
params.set("rows", rows.join("|"));
|
|
1464
|
+
const t = stats.totals;
|
|
1465
|
+
params.set("tot", [
|
|
1466
|
+
formatCompactNumber(t.inputTokens),
|
|
1467
|
+
formatCompactNumber(t.outputTokens),
|
|
1468
|
+
formatCompactNumber(t.cacheWriteTokens),
|
|
1469
|
+
formatCompactNumber(t.cacheReadTokens),
|
|
1470
|
+
formatCompactNumber(t.totalTokens),
|
|
1471
|
+
t.cost.toFixed(2)
|
|
1472
|
+
].join(":"));
|
|
1473
|
+
if (stats.modelBreakdown.length > 0) {
|
|
1474
|
+
const mb = stats.modelBreakdown.slice(0, 5).map((m) => {
|
|
1475
|
+
const abbr = getModelAbbrevFromDisplayName(m.model);
|
|
1476
|
+
return `${abbr}:${m.percentage}:${m.cost.toFixed(2)}`;
|
|
1477
|
+
});
|
|
1478
|
+
params.set("mb", mb.join(","));
|
|
1479
|
+
}
|
|
1480
|
+
return `${baseUrl}?${params.toString()}`;
|
|
1481
|
+
}
|
|
1439
1482
|
|
|
1440
1483
|
// src/display.ts
|
|
1441
1484
|
var colors2 = {
|
|
@@ -1704,6 +1747,13 @@ var main = defineCommand({
|
|
|
1704
1747
|
description: "Use compact table format (hide cache columns)",
|
|
1705
1748
|
default: false
|
|
1706
1749
|
},
|
|
1750
|
+
// Share option for usage mode
|
|
1751
|
+
share: {
|
|
1752
|
+
type: "boolean",
|
|
1753
|
+
alias: "s",
|
|
1754
|
+
description: "Generate a shareable URL (usage mode)",
|
|
1755
|
+
default: false
|
|
1756
|
+
},
|
|
1707
1757
|
// Wrapped-specific options
|
|
1708
1758
|
url: {
|
|
1709
1759
|
type: "string",
|
|
@@ -1769,6 +1819,19 @@ async function runUsage(args, config) {
|
|
|
1769
1819
|
}
|
|
1770
1820
|
process.exit(1);
|
|
1771
1821
|
}
|
|
1822
|
+
const baseUrl = args.url || config.baseUrl || "https://vibestats.wolfai.dev";
|
|
1823
|
+
let shareUrl = null;
|
|
1824
|
+
if (args.share) {
|
|
1825
|
+
const fullUrl = encodeUsageToUrl(stats, baseUrl);
|
|
1826
|
+
if (!args["no-short"]) {
|
|
1827
|
+
shareUrl = await createShortlink(fullUrl, baseUrl);
|
|
1828
|
+
}
|
|
1829
|
+
shareUrl = shareUrl || fullUrl;
|
|
1830
|
+
}
|
|
1831
|
+
if (args.quiet && args.share && shareUrl) {
|
|
1832
|
+
console.log(shareUrl);
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1772
1835
|
if (args.json) {
|
|
1773
1836
|
console.log(JSON.stringify(stats, null, 2));
|
|
1774
1837
|
} else if (args.quiet) {
|
|
@@ -1787,6 +1850,10 @@ async function runUsage(args, config) {
|
|
|
1787
1850
|
showColors: config.theme?.enabled !== false
|
|
1788
1851
|
});
|
|
1789
1852
|
}
|
|
1853
|
+
if (args.share && shareUrl && !args.json) {
|
|
1854
|
+
console.log();
|
|
1855
|
+
console.log(`\u{1F517} ${shareUrl}`);
|
|
1856
|
+
}
|
|
1790
1857
|
}
|
|
1791
1858
|
async function runWrapped(args, config) {
|
|
1792
1859
|
const options = resolveOptions(args, config);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibestats",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "AI coding stats - usage tracking and annual wrapped for Claude Code & Codex",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,11 +18,6 @@
|
|
|
18
18
|
"files": [
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"dev": "tsx src/index.ts",
|
|
23
|
-
"build": "tsup src/index.ts --format esm --dts --clean --shims",
|
|
24
|
-
"prepublishOnly": "pnpm build"
|
|
25
|
-
},
|
|
26
21
|
"keywords": [
|
|
27
22
|
"claude",
|
|
28
23
|
"claude-code",
|
|
@@ -50,5 +45,9 @@
|
|
|
50
45
|
},
|
|
51
46
|
"engines": {
|
|
52
47
|
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"dev": "tsx src/index.ts",
|
|
51
|
+
"build": "tsup src/index.ts --format esm --dts --clean --shims"
|
|
53
52
|
}
|
|
54
|
-
}
|
|
53
|
+
}
|