nomnomtokens 0.4.0 → 0.5.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.
Files changed (120) hide show
  1. package/README.md +45 -25
  2. package/dist/index.js +1180 -109
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/web/nitro.json +1 -1
  6. package/web/public/_nuxt/AuWqCQTg.js +1 -0
  7. package/web/public/_nuxt/{W3KL_OjU.js → B1SHP0x7.js} +1 -1
  8. package/web/public/_nuxt/{DQEnwY-5.js → B4lg_KdO.js} +1 -1
  9. package/web/public/_nuxt/B8pNcdCn.js +1 -0
  10. package/web/public/_nuxt/{COwSpxrx.js → BL80uXr2.js} +1 -1
  11. package/web/public/_nuxt/{B2aHje2L.js → BOu13FsZ.js} +1 -1
  12. package/web/public/_nuxt/{CvIugsJe2.js → BYf03To42.js} +1 -1
  13. package/web/public/_nuxt/{CkRZsevx.js → B_fydnl_.js} +1 -1
  14. package/web/public/_nuxt/{DnTwjl0_2.js → BboXpc0v2.js} +2 -2
  15. package/web/public/_nuxt/{CfBMjq8x.js → Bg-w_mbM.js} +1 -1
  16. package/web/public/_nuxt/{B1jhn8zK.js → BsIJiDwC.js} +1 -1
  17. package/web/public/_nuxt/BsfWsX6E.js +1 -0
  18. package/web/public/_nuxt/{C9MiT_Wm.js → BuKW47N9.js} +2 -2
  19. package/web/public/_nuxt/{4C_a23zt.js → BvB3OU0z.js} +1 -1
  20. package/web/public/_nuxt/CLdT3CQk.js +1 -0
  21. package/web/public/_nuxt/{D9j6aFUy.js → Car0xtsn.js} +1 -1
  22. package/web/public/_nuxt/Ch1ysvEi.js +1 -0
  23. package/web/public/_nuxt/{BOKlFKrX.js → Ck5ddq-9.js} +1 -1
  24. package/web/public/_nuxt/{Cq1Sq3Go.js → CsVo4EXo.js} +1 -1
  25. package/web/public/_nuxt/CzaLG4_B2.js +1 -0
  26. package/web/public/_nuxt/{C51OzH6V.js → D9MZNmok.js} +1 -1
  27. package/web/public/_nuxt/{D9Mxq5ER.js → DQ6vgNw-.js} +1 -1
  28. package/web/public/_nuxt/{D49wVVwm2.js → DZ0oUjlX2.js} +1 -1
  29. package/web/public/_nuxt/DbTv-m36.js +1 -0
  30. package/web/public/_nuxt/{D4C6J8YV.js → DdHo_MGy.js} +1 -1
  31. package/web/public/_nuxt/{m3-Vaz25.js → DmteO8Ul.js} +1 -1
  32. package/web/public/_nuxt/DyoXCutE.js +1 -0
  33. package/web/public/_nuxt/{DPnm6zS2.js → DyvBBld_2.js} +1 -1
  34. package/web/public/_nuxt/{CIKwfDBl.js → PaV2v2OF.js} +1 -1
  35. package/web/public/_nuxt/{BMSLzLlT.js → RjmsMzM7.js} +1 -1
  36. package/web/public/_nuxt/builds/latest.json +1 -1
  37. package/web/public/_nuxt/builds/meta/2bf417d4-fc60-4108-8624-e631e05f5a46.json +1 -0
  38. package/web/public/_nuxt/entry.CE8-9Sal.css +2 -0
  39. package/web/public/_nuxt/{Dy30RUCD2.js → hPGLTkZo2.js} +1 -1
  40. package/web/public/_nuxt/{Bprokln-.js → jeqgGzjf.js} +1 -1
  41. package/web/public/_nuxt/n29w62AT.js +1 -0
  42. package/web/public/_nuxt/{CDzUujek.js → tShBBc0S.js} +2 -2
  43. package/web/server/chunks/_/filters.mjs +1 -0
  44. package/web/server/chunks/_/filters.mjs.map +1 -1
  45. package/web/server/chunks/build/AuditCard-CgGiEb_r.mjs +290 -0
  46. package/web/server/chunks/build/AuditCard-CgGiEb_r.mjs.map +1 -0
  47. package/web/server/chunks/build/{CardContent-C_IMqI8K.mjs → CardDescription-Bi5t5iXj.mjs} +30 -30
  48. package/web/server/chunks/build/CardDescription-Bi5t5iXj.mjs.map +1 -0
  49. package/web/server/chunks/build/{FilterBar-BlEsJ5dy.mjs → FilterBar-BYBOdTrl.mjs} +2 -2
  50. package/web/server/chunks/build/{FilterBar-BlEsJ5dy.mjs.map → FilterBar-BYBOdTrl.mjs.map} +1 -1
  51. package/web/server/chunks/build/{Sparkline-CaCRq45J.mjs → Sparkline-B3kazZhU.mjs} +2 -2
  52. package/web/server/chunks/build/{Sparkline-CaCRq45J.mjs.map → Sparkline-B3kazZhU.mjs.map} +1 -1
  53. package/web/server/chunks/build/{_id_-BvccBwzH.mjs → _id_-DPUt6OzN.mjs} +4 -4
  54. package/web/server/chunks/build/{_id_-BvccBwzH.mjs.map → _id_-DPUt6OzN.mjs.map} +1 -1
  55. package/web/server/chunks/build/asyncData-CMa0z9Yw.mjs +2 -2
  56. package/web/server/chunks/build/audit-BPAlwhzn.mjs +1180 -0
  57. package/web/server/chunks/build/audit-BPAlwhzn.mjs.map +1 -0
  58. package/web/server/chunks/build/{default-BokiYQNv.mjs → default-CvQF0-O_.mjs} +46 -22
  59. package/web/server/chunks/build/default-CvQF0-O_.mjs.map +1 -0
  60. package/web/server/chunks/build/export-CwC19yOz.mjs +232 -0
  61. package/web/server/chunks/build/export-CwC19yOz.mjs.map +1 -0
  62. package/web/server/chunks/build/fetch-DJ9NNbFP.mjs +1 -1
  63. package/web/server/chunks/build/{import-CO3NEu0P.mjs → import-BmoVtcGR.mjs} +31 -15
  64. package/web/server/chunks/build/import-BmoVtcGR.mjs.map +1 -0
  65. package/web/server/chunks/build/{limits-CX9zBSqw.mjs → limits-C21_a18j.mjs} +5 -5
  66. package/web/server/chunks/build/{limits-CX9zBSqw.mjs.map → limits-C21_a18j.mjs.map} +1 -1
  67. package/web/server/chunks/build/nuxt-link-mYiLFsJs.mjs +2 -2
  68. package/web/server/chunks/build/{pages-DyXqJyPq.mjs → pages-CJpczmoA.mjs} +81 -11
  69. package/web/server/chunks/build/pages-CJpczmoA.mjs.map +1 -0
  70. package/web/server/chunks/build/{providers-Ca7keu2G.mjs → providers-BBVw9CDb.mjs} +4 -4
  71. package/web/server/chunks/build/{providers-Ca7keu2G.mjs.map → providers-BBVw9CDb.mjs.map} +1 -1
  72. package/web/server/chunks/build/{scopes-E5z80S19.mjs → scopes-DpYnOAM9.mjs} +203 -62
  73. package/web/server/chunks/build/scopes-DpYnOAM9.mjs.map +1 -0
  74. package/web/server/chunks/build/{sessions-CESRiCOS.mjs → sessions-B-Y_ifp1.mjs} +5 -5
  75. package/web/server/chunks/build/{sessions-CESRiCOS.mjs.map → sessions-B-Y_ifp1.mjs.map} +1 -1
  76. package/web/server/chunks/build/{timeline-d27OlbZN.mjs → timeline-8kK28WQB.mjs} +5 -5
  77. package/web/server/chunks/build/{timeline-d27OlbZN.mjs.map → timeline-8kK28WQB.mjs.map} +1 -1
  78. package/web/server/chunks/build/useFormat-NkyUqeik.mjs +1 -1
  79. package/web/server/chunks/build/{useStats-CmYzpdbE.mjs → useStats-BQQJIKQO.mjs} +7 -5
  80. package/web/server/chunks/build/{useStats-CmYzpdbE.mjs.map → useStats-BQQJIKQO.mjs.map} +1 -1
  81. package/web/server/chunks/nitro/nitro.mjs +695 -217
  82. package/web/server/chunks/nitro/nitro.mjs.map +1 -1
  83. package/web/server/chunks/routes/api/export.get.mjs +22 -3
  84. package/web/server/chunks/routes/api/export.get.mjs.map +1 -1
  85. package/web/server/chunks/routes/api/import/csv.post.mjs +20 -6
  86. package/web/server/chunks/routes/api/import/csv.post.mjs.map +1 -1
  87. package/web/server/chunks/routes/api/ingest.post.mjs +1 -1
  88. package/web/server/chunks/routes/api/meta.get.mjs +1 -1
  89. package/web/server/chunks/routes/api/scopes/_hash_.patch.mjs +35 -0
  90. package/web/server/chunks/routes/api/scopes/_hash_.patch.mjs.map +1 -0
  91. package/web/server/chunks/routes/api/stats/audit.get.mjs +60 -0
  92. package/web/server/chunks/routes/api/stats/audit.get.mjs.map +1 -0
  93. package/web/server/chunks/routes/api/stats/limits.get.mjs +1 -1
  94. package/web/server/chunks/routes/api/stats/providers.get.mjs +1 -1
  95. package/web/server/chunks/routes/api/stats/scopes.get.mjs +1 -1
  96. package/web/server/chunks/routes/api/stats/session/_id_.get.mjs +1 -1
  97. package/web/server/chunks/routes/api/stats/summary.get.mjs +1 -1
  98. package/web/server/chunks/routes/api/stats/verdict.get.mjs +35 -0
  99. package/web/server/chunks/routes/api/stats/verdict.get.mjs.map +1 -0
  100. package/web/server/chunks/routes/renderer.mjs +2 -2
  101. package/web/server/chunks/virtual/entry.mjs +17 -12
  102. package/web/server/chunks/virtual/precomputed.mjs +1 -1
  103. package/web/server/chunks/virtual/precomputed.mjs.map +1 -1
  104. package/web/server/index.mjs +1 -1
  105. package/web/public/_nuxt/Bia8fJFj.js +0 -1
  106. package/web/public/_nuxt/CIHIOSzn.js +0 -1
  107. package/web/public/_nuxt/CZSbzIi-.js +0 -1
  108. package/web/public/_nuxt/DMgad8mU.js +0 -1
  109. package/web/public/_nuxt/DhJW7zb9.js +0 -1
  110. package/web/public/_nuxt/OU1MVgXQ.js +0 -1
  111. package/web/public/_nuxt/builds/meta/b80e2306-16ec-4868-89f8-b713594d0c00.json +0 -1
  112. package/web/public/_nuxt/cbxnBwm6.js +0 -1
  113. package/web/public/_nuxt/entry.MbqNBIeH.css +0 -2
  114. package/web/server/chunks/build/CardContent-C_IMqI8K.mjs.map +0 -1
  115. package/web/server/chunks/build/default-BokiYQNv.mjs.map +0 -1
  116. package/web/server/chunks/build/export-BhfwmSMl.mjs +0 -184
  117. package/web/server/chunks/build/export-BhfwmSMl.mjs.map +0 -1
  118. package/web/server/chunks/build/import-CO3NEu0P.mjs.map +0 -1
  119. package/web/server/chunks/build/pages-DyXqJyPq.mjs.map +0 -1
  120. package/web/server/chunks/build/scopes-E5z80S19.mjs.map +0 -1
package/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # nomnomtokens
2
2
 
3
- > nom nom nom — your agent is eating tokens. The dashboard shows exactly how many.
3
+ > nom nom nom — your agents are eating tokens. One local store shows where.
4
4
 
5
- A local-first dashboard for AI coding agent spend. Run one command and a
6
- dashboard opens in your browser: how much your agent ate today, on which
7
- projects, and when you'll hit your limit.
5
+ A local-first dashboard for AI coding agent spend across Claude Code, Codex,
6
+ and Cursor. Run one command and a dashboard opens in your browser: how much
7
+ went today, on which projects and models, how much of that was cache or
8
+ subagents, and when you'll hit your limit.
8
9
 
9
10
  ```sh
10
11
  npx nomnomtokens
@@ -14,21 +15,27 @@ npx nomnomtokens
14
15
 
15
16
  ![nomnomtokens Timeline — spend stacked by model and activity heatmap](docs/timeline.png)
16
17
 
17
- Claude Code, Cursor (when its local IDE database has token fields), and Codex
18
- CLI/IDE session rollouts. The event contract is deliberately not AI-shaped, so
19
- other agents and eventually CI minutes and cloud bills plug in as adapters
20
- without touching the core.
18
+ One store for Claude Code, Codex CLI/IDE session rollouts, and Cursor (when its
19
+ local IDE database has token fields). The point is not another total — it is
20
+ history you can filter and audit: model mix, cache vs fresh tokens, and
21
+ subagent share where the transcript marks it. The event contract is deliberately
22
+ not AI-shaped, so other agents — and eventually CI minutes and cloud bills —
23
+ plug in as adapters without touching the core.
21
24
 
22
25
  ## What you get
23
26
 
24
- - **Overview** — eaten today / this week / this month, with a limits widget that
25
- projects when you'll hit the cap at your current burn rate.
27
+ - **Overview** — eaten today / this week / this month, a limits widget that
28
+ projects when you'll hit the cap, a **Where it went** card (cache hit,
29
+ subagent share, model mix, tips), and a **Verdict** when weekly limit
30
+ snapshots exist.
31
+ - **Audit** — the full report: models, top sessions, cold resumes, tips. Same
32
+ numbers as `nnt audit`.
26
33
  - **Timeline** — spend over time stacked by model, plus an hour×weekday heatmap
27
34
  of when you actually work.
28
35
  - **Projects** — per-project cost with trend against the preceding period. Click
29
- a row to filter every screen. This is the one that lets a freelancer bill a
30
- client.
31
- - **Providers** — cache hit rate and cost per 1,000 changed lines.
36
+ a row to filter every screen; expand a row to tag a client for invoices.
37
+ - **Providers** — per-agent and per-model breakdown: cache hit rate and cost per
38
+ 1,000 changed lines.
32
39
  - **Sessions** — every conversation, drilling into how the bill accumulated.
33
40
  - **Limits** — window-fill history with a burn-rate projection and markers for
34
41
  the moments you actually hit the cap.
@@ -54,12 +61,15 @@ live updates.
54
61
  The hook doubles as a real status line:
55
62
 
56
63
  ```
57
- (^u^) $4.20 ctx 37% 5h 73% ·1h47m 7d 41% ·4d3h 138 lines
64
+ (^u^) $4.20 ctx 37% 7d 81% ·4d3h 5h 73% ·1h47m 138 lines
58
65
  ```
59
66
 
60
67
  The countdown after each window is the time left until it resets: the
61
68
  percentage tells you whether to slow down, the countdown tells you what slowing
62
- down would cost. It is omitted when Claude Code sends no `resets_at`.
69
+ down would cost. It is omitted when Claude Code sends no `resets_at`. The
70
+ weekly window is shown first when it is the tighter of the two. If Claude's
71
+ week is nearly full and a recent Codex snapshot in the store still has
72
+ headroom, a `codex 7d N%` suffix is appended.
63
73
 
64
74
  ## Commands
65
75
 
@@ -70,16 +80,22 @@ down would cost. It is omitted when Claude Code sends no `resets_at`.
70
80
  | `nnt serve [--port]` | open the dashboard |
71
81
  | `nnt init [--force]` | wire up the status line hook |
72
82
  | `nnt statusline` | ingest a session payload and print a status line |
73
- | `nnt doctor` | why is it empty? checks sources, hook, and store |
74
- | `nnt import <file.csv>` | import a billing CSV into the local store |
75
- | `nnt export` | dump filtered events as CSV/JSON |
83
+ | `nnt doctor` | why is it empty? checks sources, hook, store, and transcript wipe |
84
+ | `nnt import <file>` | billing CSV or nnt archive JSON into the local store |
85
+ | `nnt export` | dump filtered events as CSV/JSON, or `--format nnt` for a portable store |
76
86
  | `nnt prices [show\|refresh]` | local model price table (`~/.nomnomtokens/prices.json`) |
77
87
  | `nnt alerts [show\|check]` | limit % / daily $ thresholds (`~/.nomnomtokens/alerts.json`) |
88
+ | `nnt audit [--days] [--json]` | where spend went: cache, subagents, models, cold resumes, tips |
89
+ | `nnt verdict [--json]` | which Claude plan weekly fill actually needs (dated estimates) |
90
+ | `nnt weigh [--json]` | weekly limit points per list-price dollar, when one model owns the gap |
91
+ | `nnt otel --endpoint <url>` | opt-in OTLP/HTTP JSON export of numbers and hashes |
78
92
 
79
93
  ## Privacy
80
94
 
81
- Your data never leaves your machine. No account, no telemetry, no network calls
82
- at all — not even a font or a CDN script.
95
+ Your data never leaves your machine unless you opt in. No account, no telemetry.
96
+ The dashboard makes no outbound calls — not even a font or a CDN script. The
97
+ only network is explicit: `nnt prices refresh --from`, alert webhooks, and
98
+ `nnt otel --endpoint`.
83
99
 
84
100
  The event type has nowhere to put a prompt, a diff, or a path:
85
101
 
@@ -145,9 +161,11 @@ the core, the contract is wrong and that's a bug worth reporting.
145
161
 
146
162
  ## Roadmap
147
163
 
148
- Shipped: Claude Code / Cursor / Codex adapters, CSV import & export, Projects
149
- grouped by name, local `prices.json` refresh, limit/daily alerts, all dashboard
150
- screens, limits with forecasting, live updates.
164
+ Shipped: Claude Code / Cursor / Codex adapters, CSV and nnt-archive import &
165
+ export, Projects grouped by name with optional client tags, local `prices.json`
166
+ refresh, limit/daily alerts, all dashboard screens including `/audit`, limits
167
+ with forecasting, live updates, Overview audit + verdict, `nnt audit` /
168
+ `nnt verdict`, and opt-in `nnt otel`.
151
169
 
152
170
  Cursor caveat: the IDE often stores zero token counts in local bubbles. We only
153
171
  emit events when numbers are present (exact `tokenCount`, or
@@ -155,8 +173,10 @@ emit events when numbers are present (exact `tokenCount`, or
155
173
  local counts will not appear until Cursor writes them — or until you import a
156
174
  billing CSV.
157
175
 
158
- Next: OTLP receiver, then cloud mode a second sink for the same events, never
159
- a rewrite, and never in the critical path.
176
+ Next: a desktop window and menu bar around the same local store. Cloud mode
177
+ stays a later second sink for the same events, never a rewrite, and never in
178
+ the critical path. An OTLP *receiver* is not on the roadmap — `nnt otel`
179
+ exports into Grafana/Datadog you already run.
160
180
 
161
181
  ## License
162
182