tokmon 0.5.0 → 0.5.2
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 +42 -43
- package/dist/cli.js +20 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,31 +1,10 @@
|
|
|
1
1
|
# tokmon
|
|
2
2
|
|
|
3
|
-
Terminal dashboard for Claude Code usage
|
|
3
|
+
Terminal dashboard for Claude Code usage, costs, and rate limits.
|
|
4
4
|
|
|
5
5
|
Built with [Ink](https://github.com/vadimdemedes/ink), TypeScript.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
◉ tokmon · 2s 01:17:09 AM
|
|
9
|
-
|
|
10
|
-
Dashboard Daily ←→ or 1-2
|
|
11
|
-
|
|
12
|
-
┃ Claude
|
|
13
|
-
┃
|
|
14
|
-
┃ Today $166.10 252.7M tokens
|
|
15
|
-
┃ This Week $399.79 608.2M tokens
|
|
16
|
-
┃ This Month $1337.03 2.2B tokens
|
|
17
|
-
|
|
18
|
-
┃ Active Block 12m remaining
|
|
19
|
-
┃
|
|
20
|
-
┃ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━─ 96%
|
|
21
|
-
┃
|
|
22
|
-
┃ $314.37 spent · ~$328.01 proj · $65.60/hr
|
|
23
|
-
|
|
24
|
-
──────────────────────────────────────────────────
|
|
25
|
-
Total $1337.03
|
|
26
|
-
|
|
27
|
-
by David Ilie (davidilie.com)
|
|
28
|
-
```
|
|
7
|
+

|
|
29
8
|
|
|
30
9
|
## Quick Start
|
|
31
10
|
|
|
@@ -45,7 +24,7 @@ pnpm dlx tokmon
|
|
|
45
24
|
npm install -g tokmon
|
|
46
25
|
```
|
|
47
26
|
|
|
48
|
-
Then just run `tokmon`. Press `
|
|
27
|
+
Then just run `tokmon`. Press `q` to quit.
|
|
49
28
|
|
|
50
29
|
## Options
|
|
51
30
|
|
|
@@ -54,45 +33,65 @@ Then just run `tokmon`. Press `Ctrl+C` to exit.
|
|
|
54
33
|
-h, --help Show help
|
|
55
34
|
```
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
tokmon -i 5 # refresh every 5 seconds
|
|
59
|
-
```
|
|
36
|
+
## Keybindings
|
|
60
37
|
|
|
61
|
-
|
|
38
|
+
| Key | Action |
|
|
39
|
+
|-----|--------|
|
|
40
|
+
| `Tab` / `←→` | Switch between Dashboard and Table |
|
|
41
|
+
| `1` `2` | Jump to view |
|
|
42
|
+
| `d` `w` `m` | Daily / Weekly / Monthly (in Table view) |
|
|
43
|
+
| `↑` `↓` | Scroll table |
|
|
44
|
+
| `PgUp` `PgDn` | Scroll table fast |
|
|
45
|
+
| `s` | Settings |
|
|
46
|
+
| `q` | Quit |
|
|
62
47
|
|
|
63
|
-
|
|
48
|
+
## Views
|
|
64
49
|
|
|
65
50
|
| View | Description |
|
|
66
51
|
|------|-------------|
|
|
67
|
-
| **Dashboard** | Today / week / month cost summaries,
|
|
68
|
-
| **Daily** | Per-day breakdown
|
|
52
|
+
| **Dashboard** | Today / week / month cost summaries, burn rate ($/hr), real-time rate limits with reset countdowns |
|
|
53
|
+
| **Table → Daily** | Per-day breakdown with models, tokens, and costs (6 months of history) |
|
|
54
|
+
| **Table → Weekly** | Grouped by ISO week |
|
|
55
|
+
| **Table → Monthly** | Grouped by month |
|
|
56
|
+
|
|
57
|
+
## Rate Limits
|
|
58
|
+
|
|
59
|
+
Fetches real billing data from Anthropic's OAuth API (reads your token from macOS Keychain automatically). Shows:
|
|
60
|
+
|
|
61
|
+
- **Session** — 5-hour utilization with reset countdown
|
|
62
|
+
- **Weekly** — 7-day utilization with reset countdown
|
|
63
|
+
- **Sonnet** — Sonnet-specific limits (if applicable)
|
|
64
|
+
- **Extra usage** — spend vs monthly limit
|
|
65
|
+
|
|
66
|
+
Polls every 2 minutes to stay within API rate limits.
|
|
67
|
+
|
|
68
|
+
## Settings
|
|
69
|
+
|
|
70
|
+
Press `s` to open settings. Persisted to `~/.config/tokmon/config.json` (macOS/Linux) or `%APPDATA%\tokmon\config.json` (Windows).
|
|
71
|
+
|
|
72
|
+
- **Refresh interval** — adjust with `←→`
|
|
73
|
+
- **Clear screen** — on/off toggle
|
|
69
74
|
|
|
70
75
|
## How It Works
|
|
71
76
|
|
|
72
|
-
Reads Claude Code's JSONL session logs directly from `~/.claude/projects/`. Calculates costs using Claude model pricing (Opus, Sonnet, Haiku). Caches file reads by mtime so
|
|
77
|
+
Reads Claude Code's JSONL session logs directly from `~/.claude/projects/`. Calculates costs using Claude model pricing (Opus, Sonnet, Haiku). Caches file reads by mtime so refreshes are near-instant.
|
|
78
|
+
|
|
79
|
+
Dashboard loads current month only (fast). Table loads 6 months lazily on first switch.
|
|
73
80
|
|
|
74
81
|
Cross-platform: supports macOS, Linux, and Windows (`%APPDATA%`, `XDG_CONFIG_HOME`, `CLAUDE_CONFIG_DIR`).
|
|
75
82
|
|
|
76
83
|
## CI/CD
|
|
77
84
|
|
|
78
|
-
Publishes to npm
|
|
85
|
+
Publishes to npm via GitHub Actions on version tags:
|
|
79
86
|
|
|
80
87
|
```bash
|
|
81
|
-
git tag v0.
|
|
88
|
+
git tag v0.5.0 && git push --tags
|
|
82
89
|
```
|
|
83
90
|
|
|
84
91
|
## Requirements
|
|
85
92
|
|
|
86
93
|
- Node.js 20+
|
|
87
|
-
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
88
|
-
|
|
89
|
-
## Tech Stack
|
|
90
|
-
|
|
91
|
-
| Tool | Purpose |
|
|
92
|
-
|------|---------|
|
|
93
|
-
| Ink 5 | React terminal UI |
|
|
94
|
-
| TypeScript 5.7+ | Strict mode |
|
|
95
|
-
| tsup | Build |
|
|
94
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
96
95
|
|
|
97
96
|
## Author
|
|
98
97
|
|
package/dist/cli.js
CHANGED
|
@@ -198,11 +198,20 @@ async function fetchDashboard() {
|
|
|
198
198
|
const todayStart = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
|
199
199
|
const weekDay = d.getDay();
|
|
200
200
|
const weekStart = new Date(d.getFullYear(), d.getMonth(), d.getDate() - (weekDay === 0 ? 6 : weekDay - 1)).getTime();
|
|
201
|
+
const now = Date.now();
|
|
201
202
|
const entries = await loadEntries(monthStart);
|
|
203
|
+
const todayEntries = entries.filter((e) => e.ts >= todayStart);
|
|
204
|
+
let burnRate = 0;
|
|
205
|
+
if (todayEntries.length > 0) {
|
|
206
|
+
const oldest = Math.min(...todayEntries.map((e) => e.ts));
|
|
207
|
+
const hrs = (now - oldest) / 36e5;
|
|
208
|
+
if (hrs > 0) burnRate = todayEntries.reduce((s, e) => s + e.cost, 0) / hrs;
|
|
209
|
+
}
|
|
202
210
|
return {
|
|
203
|
-
today: sum(
|
|
211
|
+
today: sum(todayEntries),
|
|
204
212
|
week: sum(entries.filter((e) => e.ts >= weekStart)),
|
|
205
|
-
month: sum(entries.filter((e) => e.ts >= monthStart))
|
|
213
|
+
month: sum(entries.filter((e) => e.ts >= monthStart)),
|
|
214
|
+
burnRate
|
|
206
215
|
};
|
|
207
216
|
}
|
|
208
217
|
async function fetchTable() {
|
|
@@ -615,7 +624,15 @@ function DashboardView({ data, billing }) {
|
|
|
615
624
|
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
616
625
|
/* @__PURE__ */ jsx(SummaryRow, { label: "Today", summary: data.today }),
|
|
617
626
|
/* @__PURE__ */ jsx(SummaryRow, { label: "This Week", summary: data.week }),
|
|
618
|
-
/* @__PURE__ */ jsx(SummaryRow, { label: "This Month", summary: data.month })
|
|
627
|
+
/* @__PURE__ */ jsx(SummaryRow, { label: "This Month", summary: data.month }),
|
|
628
|
+
data.burnRate > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
629
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
630
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
631
|
+
/* @__PURE__ */ jsx(Box, { width: 14, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Burn rate" }) }),
|
|
632
|
+
/* @__PURE__ */ jsx(Box, { width: 12, justifyContent: "flex-end", children: /* @__PURE__ */ jsx(Text, { color: "red", children: currency(data.burnRate) }) }),
|
|
633
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/hr" })
|
|
634
|
+
] })
|
|
635
|
+
] })
|
|
619
636
|
]
|
|
620
637
|
}
|
|
621
638
|
),
|