tokentracker-cli 1.3.4 → 1.3.6
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.de.md +5 -5
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +6 -5
- package/README.zh-CN.md +3 -3
- package/dashboard/dist/assets/{AchievementBadge-CKjtQp-U.js → AchievementBadge-CHDt55IP.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-DpOXrabE.js → AchievementsPage-DpbRHmb8.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-DiXyIoa0.js → AchievementsSection-Ck5CiX4P.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-CILTTkPF.js → BadgeDetailModal-BVPqlh0X.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-CrBHWiRi.js → BotAnimated-CVsv6kxT.js} +1 -1
- package/dashboard/dist/assets/{Card-DUItW3xI.js → Card-C9FjyAwh.js} +1 -1
- package/dashboard/dist/assets/{CloudCheckoutPage-C_t_PDlG.js → CloudCheckoutPage-ChkjId9l.js} +1 -1
- package/dashboard/dist/assets/{CloudPage-pvJUrhya.js → CloudPage-D1nrt3MG.js} +1 -1
- package/dashboard/dist/assets/{CloudUsageExport-DQbDwiyk.js → CloudUsageExport-jXdoiD0e.js} +1 -1
- package/dashboard/dist/assets/{CommandPalette-BvHilrbV.js → CommandPalette-DFnEeZzc.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-CizxEYv-.js → CommunityStatsModal-CZDS8gPA.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-h9nISVy7.js → ConfirmModal-DRhgBoGE.js} +1 -1
- package/dashboard/dist/assets/{Controls-BjdIonTX.js → Controls-BmT6-x_L.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-Bxryr4qp.js → DashboardPage-DfwwXZBo.js} +1 -1
- package/dashboard/dist/assets/{DateRangePopover-DpKh-0l8.js → DateRangePopover-DuqNLatr.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-DUJR9hJC.js → DevicePage-BtI0bWyg.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-BmVAmN-o.js → DialogClose-DjnC3P4V.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-yy_QHg7O.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-BsaIbN8k.js → DialogTitle-B9NNSz5p.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-BpSt2P_W.js → FadeIn-fsVQmJGa.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-Cc_VHB0R.js → HeaderGithubStar-Cg-f1iZc.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-WFd21iP9.js → HoverTooltip-DRIRlzXH.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-C_mUPSRB.js → IpCheckPage-DaAubaJQ.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-DVR8ClZO.js → LandingPage-DjBGIjHk.js} +2 -2
- package/dashboard/dist/assets/LeaderboardPage-BkCXqhz7.js +2 -0
- package/dashboard/dist/assets/{LeaderboardProBadge-BjX4EFl2.js → LeaderboardProBadge-Ds-wiWcN.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfileModal-vbPMNn7W.js → LeaderboardProfileModal-X_rfSQT5.js} +4 -4
- package/dashboard/dist/assets/{LeaderboardProfilePage-CqClmuA-.js → LeaderboardProfilePage-rpl1Ozwj.js} +1 -1
- package/dashboard/dist/assets/LimitsPage-BUvDBmgD.js +9 -0
- package/dashboard/dist/assets/{LocalOnlyNotice-B6nDke_u.js → LocalOnlyNotice-LBH1DBrs.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-C28QVjd7.js → LoginCard-B0vRJEcg.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-Bx1btNhH.js → LoginModal-DdzgP43f.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-DVOGNGYI.js → LoginPage-B4VCQxzn.js} +1 -1
- package/dashboard/dist/assets/{PetPage-nOKryTde.js → PetPage-Cmf6aXc9.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-Ch6NLnu6.js → PopoverPopup-BzfELnIC.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-BRY2br-g.js → ProviderIcon-ClHXNkQ0.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-ko1OQecQ.js → ResetPasswordPage-BeUpNt_6.js} +1 -1
- package/dashboard/dist/assets/{Select-Q8mS3_od.js → Select-BHEXdYHu.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-C1id8GDj.js → SelectItemText-aaQK_QIt.js} +1 -1
- package/dashboard/dist/assets/{SelfHostPage-Dzb2bDiM.js → SelfHostPage-ClNhKnlP.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-ewFwz29J.js → ServiceStatusPage-Byd_s6FS.js} +1 -1
- package/dashboard/dist/assets/SessionsPage-u3_b4PO7.js +3 -0
- package/dashboard/dist/assets/SettingsPage-DweCAbsy.js +2 -0
- package/dashboard/dist/assets/{SkillsPage-CcG77tqU.js → SkillsPage-Bb-PVfux.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-D2HDrbQR.js → TokenGalaxy-CubA3PXu.js} +1 -1
- package/dashboard/dist/assets/{TooltipPopup-C_bF2ZwO.js → TooltipPopup-DMliWhoK.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-BcyoN5ns.js → TrendMonitor-as8idaOy.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-BirK0U_N.js → WidgetsPage-DDPR4v0R.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-thsXBuw6.js → WrappedPage-zZzgYz6s.js} +1 -1
- package/dashboard/dist/assets/{__vite-browser-external-Bq8nj-JV.js → __vite-browser-external-DWN9Fb-H.js} +12 -12
- package/dashboard/dist/assets/__vite-browser-external-LpFw4zXh.css +1 -0
- package/dashboard/dist/assets/agent-logos-CoNhCm9-.js +1 -0
- package/dashboard/dist/assets/{arrow-left-c_NOSfoq.js → arrow-left-C5hDp7fc.js} +1 -1
- package/dashboard/dist/assets/{arrow-right-CP7drKCT.js → arrow-right-DEvMmSiA.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-DQ6QfCpo.js → arrow-up-right-DxY0neJ4.js} +1 -1
- package/dashboard/dist/assets/{calendar-days-D_pxFQvT.js → calendar-days-bzh7-lab.js} +1 -1
- package/dashboard/dist/assets/{check-HAS31kTT.js → check-CSZvcC3X.js} +1 -1
- package/dashboard/dist/assets/{chevron-down-BIMuk6oN.js → chevron-down-CsiGcG0G.js} +1 -1
- package/dashboard/dist/assets/{cloud-checkout-COmDwrUT.js → cloud-checkout-z_eDVwm6.js} +1 -1
- package/dashboard/dist/assets/{composite-kLwqpqEk.js → composite-Cq0CmNAv.js} +1 -1
- package/dashboard/dist/assets/{download-9RgsZIiH.js → download-DqLpubIF.js} +1 -1
- package/dashboard/dist/assets/{external-link-C_gYjHGF.js → external-link-B8E8tbB3.js} +1 -1
- package/dashboard/dist/assets/{flame-BSsCvgT8.js → flame-CrJDlnro.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-N22Wqv1X.js → format-tokens-DPIGGOlt.js} +1 -1
- package/dashboard/dist/assets/gift-CCp4Hh50.js +1 -0
- package/dashboard/dist/assets/{host-mode-JzrhHX7F.js → host-mode-xzpMLcwP.js} +1 -1
- package/dashboard/dist/assets/{icons-pK99mIMv.js → icons-CbB9Y-eV.js} +1 -1
- package/dashboard/dist/assets/{index-BhviBroj.js → index-BiK5-tQp.js} +1 -1
- package/dashboard/dist/assets/{index-CmD84EJi.js → index-DX7nYrHb.js} +1 -1
- package/dashboard/dist/assets/{index-Dk43KNa6.js → index-zuC7FU-t.js} +1 -1
- package/dashboard/dist/assets/{info-D-RLFnSK.js → info-B3NKYwWG.js} +1 -1
- package/dashboard/dist/assets/{link-2-BiKXW9mV.js → link-2-BRc8d8M9.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-KVUaEKV2.js → loader-circle-Cm5Nsgp-.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-5NK8j3mT.js → modifiers.esm-CYLYBECB.js} +1 -1
- package/dashboard/dist/assets/module-BNnaKM__.js +3 -0
- package/dashboard/dist/assets/{monitor-smartphone-u9yr-_Es.js → monitor-smartphone--IZ4D84F.js} +1 -1
- package/dashboard/dist/assets/{play-D0MaDCOx.js → play-CUrMOLtq.js} +1 -1
- package/dashboard/dist/assets/{plus-DTJVtoAJ.js → plus-0hrCDl4r.js} +1 -1
- package/dashboard/dist/assets/{provider-display-YhtG0I9Y.js → provider-display-CNK0FN3Q.js} +1 -1
- package/dashboard/dist/assets/{react-gIVxucOB.js → react-CCNSVHEA.js} +1 -1
- package/dashboard/dist/assets/{safePolygon-C_sPnJ1L.js → safePolygon-DsolkMUX.js} +1 -1
- package/dashboard/dist/assets/{search-DdQRwFYV.js → search-DYmYb9xY.js} +1 -1
- package/dashboard/dist/assets/{server-M0rmbGWy.js → server-CYcqzdSW.js} +1 -1
- package/dashboard/dist/assets/{shield-check-9-sqQKdD.js → shield-check-5zABLIr6.js} +1 -1
- package/dashboard/dist/assets/{skills-api-B0qBWnuK.js → skills-api-CD-ojBGj.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-iqbm7x5D.js → sortable.esm-BCn2Ms6R.js} +1 -1
- package/dashboard/dist/assets/{store-DstuWd4a.js → store-B22kwLs0.js} +1 -1
- package/dashboard/dist/assets/{terminal-Dz0MxHNG.js → terminal-CTv-oTU2.js} +1 -1
- package/dashboard/dist/assets/{trash-DBMFOFVz.js → trash-C5MAh3GO.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-CacbAcUR.js → use-community-stats-BrgrxUD2.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-nBuQVZOR.js → use-latest-request-guard-B1_rbvgH.js} +1 -1
- package/dashboard/dist/assets/use-limits-display-prefs-BOk5f-HM.js +1 -0
- package/dashboard/dist/assets/{use-native-settings-EAqAFx2x.js → use-native-settings-B2gc_m9W.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-DGLjjU6Q.js → use-ordered-list-N3sGpJ0u.js} +1 -1
- package/dashboard/dist/assets/{use-pet-settings-C5MzWHE7.js → use-pet-settings-sWFXgR3m.js} +2 -2
- package/dashboard/dist/assets/use-reduced-motion-C3MBYVqm.js +1 -0
- package/dashboard/dist/assets/{use-transform-C25eCuz_.js → use-transform-BsaLmw46.js} +1 -1
- package/dashboard/dist/assets/use-usage-limits-wL7v-S0r.js +1 -0
- package/dashboard/dist/assets/{useCurrency-t3PYQi1l.js → useCurrency-CbCnjf-N.js} +1 -1
- package/dashboard/dist/assets/{usePositioner-C59mj6kG.js → usePositioner-MepYlL0A.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-C0xQsBGf.js → useTokenFormat-Bq-rwuKa.js} +1 -1
- package/dashboard/dist/assets/{zap-CyH0tvKM.js → zap-1ah5e11g.js} +1 -1
- package/dashboard/dist/index.html +14 -12
- package/dashboard/dist/ip-check.html +2 -2
- package/dashboard/dist/leaderboard.html +2 -2
- package/dashboard/dist/llms.txt +2 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +2 -2
- package/src/cli.js +1 -1
- package/src/commands/init.js +43 -1
- package/src/commands/status.js +27 -0
- package/src/commands/sync.js +54 -4
- package/src/commands/uninstall.js +19 -0
- package/src/lib/claude-config.js +47 -15
- package/src/lib/codex-rollout-parser.js +11 -3
- package/src/lib/command-runner.js +15 -1
- package/src/lib/cursor-config.js +2 -1
- package/src/lib/gemini-config.js +3 -2
- package/src/lib/local-api.js +13 -3
- package/src/lib/notify-command.js +38 -0
- package/src/lib/openclaw-session-plugin.js +47 -14
- package/src/lib/passive-mode.js +12 -0
- package/src/lib/pricing/curated-overrides.json +42 -5
- package/src/lib/pricing/matcher.js +14 -5
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +199 -44
- package/src/lib/session-analytics.js +653 -60
- package/src/lib/session-performance.js +24 -1
- package/src/lib/usage-limits.js +183 -20
- package/src/lib/zcode-limits.js +218 -18
- package/src/lib/zcode-reset-credits.js +66 -0
- package/dashboard/dist/assets/DialogDescription-C0Cgq67g.js +0 -1
- package/dashboard/dist/assets/LeaderboardPage-D8ydzVpn.js +0 -2
- package/dashboard/dist/assets/LimitsPage-DaRggHge.js +0 -8
- package/dashboard/dist/assets/SessionsPage-C6Y8kbnM.js +0 -3
- package/dashboard/dist/assets/SettingsPage-nztCXEPs.js +0 -2
- package/dashboard/dist/assets/__vite-browser-external-BwmeEfv7.css +0 -1
- package/dashboard/dist/assets/agent-logos-CK6SzhI7.js +0 -1
- package/dashboard/dist/assets/module-WSx8viXK.js +0 -3
- package/dashboard/dist/assets/use-limits-display-prefs-fqg8hs6b.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-DK2oZ2uC.js +0 -1
- package/dashboard/dist/assets/use-usage-limits-BhqnEai3.js +0 -1
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"price": "0",
|
|
123
123
|
"priceCurrency": "USD"
|
|
124
124
|
},
|
|
125
|
-
"description": "Local-first AI coding usage tracker for
|
|
125
|
+
"description": "Local-first AI coding usage tracker for 44 tools, with a desktop pet, four widgets, achievements, native macOS and Windows apps, accurate cross-provider deduplication, and no prompt collection."
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
128
|
"@type": "WebSite",
|
|
@@ -205,7 +205,8 @@
|
|
|
205
205
|
{ "@type": "ListItem", "position": 40, "name": "Cline" },
|
|
206
206
|
{ "@type": "ListItem", "position": 41, "name": "MiniMax Code" },
|
|
207
207
|
{ "@type": "ListItem", "position": 42, "name": "Command Code" },
|
|
208
|
-
{ "@type": "ListItem", "position": 43, "name": "TRAE" }
|
|
208
|
+
{ "@type": "ListItem", "position": 43, "name": "TRAE" },
|
|
209
|
+
{ "@type": "ListItem", "position": 44, "name": "WorkBuddy AI" }
|
|
209
210
|
]
|
|
210
211
|
},
|
|
211
212
|
{
|
|
@@ -224,7 +225,7 @@
|
|
|
224
225
|
"name": "Which AI coding CLIs does Token Tracker support?",
|
|
225
226
|
"acceptedAnswer": {
|
|
226
227
|
"@type": "Answer",
|
|
227
|
-
"text": "Token Tracker supports
|
|
228
|
+
"text": "Token Tracker supports 44 AI coding tools, including Claude Code, Codex CLI, AStudio, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, WorkBuddy AI, Grok Build, oh-my-pi, OmO, pi, Dots, Prime Agent, Craft Agents, Reasonix, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Droid, Mimo Code, ZCode, Qoder, AnythingLLM Desktop, Claude Science, DeepSeek Harness, TRAE Work CN, LM Studio, Unsloth Studio, Devin CLI, Cline, MiniMax Code, Command Code, and TRAE."
|
|
228
229
|
}
|
|
229
230
|
},
|
|
230
231
|
{
|
|
@@ -256,7 +257,7 @@
|
|
|
256
257
|
"name": "How do I monitor AI token usage and cost across tools?",
|
|
257
258
|
"acceptedAnswer": {
|
|
258
259
|
"@type": "Answer",
|
|
259
|
-
"text": "Install Token Tracker with npx tokentracker-cli. It is an AI token usage and cost tracker that monitors token consumption and spend across all
|
|
260
|
+
"text": "Install Token Tracker with npx tokentracker-cli. It is an AI token usage and cost tracker that monitors token consumption and spend across all 44 supported tools in one dashboard, with per-model pricing across 2,200+ models so you can see cost by model, project, and time window without manual tracking."
|
|
260
261
|
}
|
|
261
262
|
},
|
|
262
263
|
{
|
|
@@ -272,15 +273,15 @@
|
|
|
272
273
|
]
|
|
273
274
|
}
|
|
274
275
|
</script>
|
|
275
|
-
<script type="module" crossorigin src="/assets/__vite-browser-external-
|
|
276
|
-
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-
|
|
276
|
+
<script type="module" crossorigin src="/assets/__vite-browser-external-DWN9Fb-H.js"></script>
|
|
277
|
+
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-LpFw4zXh.css">
|
|
277
278
|
</head>
|
|
278
279
|
<body>
|
|
279
280
|
<main class="aeo-seed-content" aria-label="Token Tracker AI-readable summary">
|
|
280
281
|
<h1>Token Tracker: monitor AI token usage and cost with a local dashboard and desktop companion</h1>
|
|
281
282
|
<p>
|
|
282
283
|
Token Tracker is a free, open-source, local-first dashboard that automatically tracks and monitors token usage
|
|
283
|
-
and cost across
|
|
284
|
+
and cost across 44 AI coding tools — including Claude Code, OpenAI Codex, AStudio, Cursor, Gemini CLI, LM Studio, and Unsloth Studio. A desktop pet
|
|
284
285
|
reacts to real token activity, four desktop widgets
|
|
285
286
|
keep usage visible, and achievements turn coding history into progress. Native macOS and Windows apps
|
|
286
287
|
sit on top of accurate cross-provider deduplication. Token counts only — never prompts or conversations.
|
|
@@ -305,7 +306,7 @@
|
|
|
305
306
|
<li><strong>Desktop pet</strong> — a pixel companion that reacts to real token burn, streaks, and rest.</li>
|
|
306
307
|
<li><strong>Four desktop widgets</strong> — usage, activity heatmap, top models, and limits at a glance.</li>
|
|
307
308
|
<li><strong>Achievements</strong> — unlock milestones from local and optional account-wide activity.</li>
|
|
308
|
-
<li><strong>Unified usage dashboard</strong> — input, output, cached, and cache-creation tokens across
|
|
309
|
+
<li><strong>Unified usage dashboard</strong> — input, output, cached, and cache-creation tokens across 44 AI coding tools.</li>
|
|
309
310
|
<li><strong>Cost analysis</strong> — per-model pricing across 2,200+ models with an offline snapshot.</li>
|
|
310
311
|
<li><strong>Usage limits view</strong> — live quota and subscription status for 17 providers, with last-good caching for local providers such as Antigravity and Qoder.</li>
|
|
311
312
|
<li><strong>Service Status page</strong> — live operational and incident status from eight official provider status pages.</li>
|
|
@@ -316,11 +317,11 @@
|
|
|
316
317
|
</ul>
|
|
317
318
|
<p><em>Privacy by design</em>: token counts only, never prompts or conversation content. Local-first; cloud sync is optional and powers only the public leaderboard.</p>
|
|
318
319
|
|
|
319
|
-
<h2>Supported AI coding tools (
|
|
320
|
+
<h2>Supported AI coding tools (44)</h2>
|
|
320
321
|
<p>
|
|
321
322
|
Use Token Tracker as a Claude Code token tracker, Codex token tracker, Cursor token tracker,
|
|
322
323
|
Gemini token tracker, OpenCode token tracker, GitHub Copilot token tracker, or DeepSeek Harness token tracker — one dashboard
|
|
323
|
-
covers all
|
|
324
|
+
covers all 44 tools below.
|
|
324
325
|
</p>
|
|
325
326
|
<ul>
|
|
326
327
|
<li><strong>Claude Code</strong> — Anthropic's official coding agent CLI; integrated via SessionEnd hook.</li>
|
|
@@ -338,6 +339,7 @@
|
|
|
338
339
|
<li><strong>Kimi Code</strong> — passive <code>wire.jsonl</code> reader.</li>
|
|
339
340
|
<li><strong>CodeBuddy (Tencent)</strong> — Claude-Code fork; SessionEnd hook in <code>~/.codebuddy/settings.json</code>.</li>
|
|
340
341
|
<li><strong>WorkBuddy (Tencent)</strong> — SessionEnd hook and passive session reader.</li>
|
|
342
|
+
<li><strong>WorkBuddy AI</strong> — International WorkBuddy build with separate session tracking.</li>
|
|
341
343
|
<li><strong>Grok Build</strong> — hook and passive cumulative usage reader.</li>
|
|
342
344
|
<li><strong>oh-my-pi</strong> — passive JSONL session reader.</li>
|
|
343
345
|
<li><strong>OmO</strong> — passive JSONL session reader, including nested subagent transcripts.</li>
|
|
@@ -396,7 +398,7 @@
|
|
|
396
398
|
<p>Run <code>npx tokentracker-cli</code>. The CLI auto-detects your AI coding tools, installs hooks, and opens the dashboard.</p>
|
|
397
399
|
|
|
398
400
|
<h3>Which AI coding tools does Token Tracker support?</h3>
|
|
399
|
-
<p>Token Tracker supports
|
|
401
|
+
<p>Token Tracker supports 44 tools: Claude Code, Codex CLI, AStudio, Cursor, Gemini CLI, Antigravity, Kiro, OpenCode, OpenClaw, Every Code, Hermes Agent, GitHub Copilot, Kimi Code, CodeBuddy, WorkBuddy, WorkBuddy AI, Grok Build, oh-my-pi, OmO, pi, Dots, Prime Agent, Craft Agents, Reasonix, Kilo CLI, Kilo Code, Roo Code, Zed Agent, Goose, Droid, Mimo Code, ZCode, Qoder, AnythingLLM Desktop, Claude Science, DeepSeek Harness, TRAE Work CN, LM Studio, Unsloth Studio, Devin CLI, Cline, MiniMax Code, Command Code, and TRAE.</p>
|
|
400
402
|
|
|
401
403
|
<h3>Is Token Tracker free and open source?</h3>
|
|
402
404
|
<p>Yes. Source on GitHub at <a href="https://github.com/xiufengsun/TokenTracker">github.com/xiufengsun/TokenTracker</a>; npm package <code>tokentracker-cli</code>.</p>
|
|
@@ -408,7 +410,7 @@
|
|
|
408
410
|
<p>Input, output, cached, and cache-creation tokens per model, project, and time window. It also surfaces usage limits for 17 providers, including Claude, Codex, Cursor, Gemini, Antigravity, Qoder, Qoder CN, Command Code, and Devin.</p>
|
|
409
411
|
|
|
410
412
|
<h3>How do I monitor AI token usage and cost across tools?</h3>
|
|
411
|
-
<p>Token Tracker is an AI token usage and cost tracker: install it with <code>npx tokentracker-cli</code>, and it monitors token consumption and spend across all
|
|
413
|
+
<p>Token Tracker is an AI token usage and cost tracker: install it with <code>npx tokentracker-cli</code>, and it monitors token consumption and spend across all 44 tools in one dashboard, with per-model pricing across 2,200+ models so you can see cost by model, project, and time window without manual tracking.</p>
|
|
412
414
|
|
|
413
415
|
<h3>Does Token Tracker work offline?</h3>
|
|
414
416
|
<p>Yes. Token Tracker is local-first. All parsing, aggregation, and dashboard rendering happen on your machine. Cloud sync is optional and powers only the public leaderboard.</p>
|
|
@@ -164,8 +164,8 @@
|
|
|
164
164
|
]
|
|
165
165
|
}
|
|
166
166
|
</script>
|
|
167
|
-
<script type="module" crossorigin src="/assets/__vite-browser-external-
|
|
168
|
-
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-
|
|
167
|
+
<script type="module" crossorigin src="/assets/__vite-browser-external-DWN9Fb-H.js"></script>
|
|
168
|
+
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-LpFw4zXh.css">
|
|
169
169
|
</head>
|
|
170
170
|
<body>
|
|
171
171
|
<main class="aeo-seed-content" aria-label="Claude IP Check AI-readable summary">
|
|
@@ -135,8 +135,8 @@
|
|
|
135
135
|
]
|
|
136
136
|
}
|
|
137
137
|
</script>
|
|
138
|
-
<script type="module" crossorigin src="/assets/__vite-browser-external-
|
|
139
|
-
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-
|
|
138
|
+
<script type="module" crossorigin src="/assets/__vite-browser-external-DWN9Fb-H.js"></script>
|
|
139
|
+
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-LpFw4zXh.css">
|
|
140
140
|
</head>
|
|
141
141
|
<body>
|
|
142
142
|
<main class="aeo-seed-content" aria-label="AI Coding Token Usage Leaderboard AI-readable summary">
|
package/dashboard/dist/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Token Tracker LLMs Index
|
|
2
2
|
|
|
3
3
|
Token Tracker is a free, open-source, local-first AI coding usage and cost
|
|
4
|
-
tracker for
|
|
4
|
+
tracker for 44 tools. Its distinctive desktop experience includes a pixel pet
|
|
5
5
|
powered by real token activity, four desktop widgets, and achievements. The
|
|
6
6
|
same data powers a cross-platform CLI, a native macOS menu bar app, a native
|
|
7
7
|
Windows system tray app, and a dashboard. It records token counts and
|
|
@@ -23,7 +23,7 @@ timestamps, never prompts, responses, or source code.
|
|
|
23
23
|
- [npm package](https://www.npmjs.com/package/tokentracker-cli)
|
|
24
24
|
- [Latest release](https://github.com/xiufengsun/TokenTracker/releases/latest)
|
|
25
25
|
|
|
26
|
-
## Supported AI coding tools (
|
|
26
|
+
## Supported AI coding tools (44)
|
|
27
27
|
- Claude Code
|
|
28
28
|
- Codex CLI
|
|
29
29
|
- AStudio
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"description": "Shareable Token Tracker dashboard snapshot."
|
|
76
76
|
}
|
|
77
77
|
</script>
|
|
78
|
-
<script type="module" crossorigin src="/assets/__vite-browser-external-
|
|
79
|
-
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-
|
|
78
|
+
<script type="module" crossorigin src="/assets/__vite-browser-external-DWN9Fb-H.js"></script>
|
|
79
|
+
<link rel="stylesheet" crossorigin href="/assets/__vite-browser-external-LpFw4zXh.css">
|
|
80
80
|
</head>
|
|
81
81
|
<body>
|
|
82
82
|
<main class="aeo-seed-content" aria-label="Token Tracker share page summary">
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokentracker-cli",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "Local-first AI coding token usage and cost tracker for
|
|
3
|
+
"version": "1.3.6",
|
|
4
|
+
"description": "Local-first AI coding token usage and cost tracker for 44 tools, with a dashboard, desktop pet, widgets, achievements, and native macOS/Windows apps.",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"tokentracker-cli": "bin/tracker.js",
|
package/src/cli.js
CHANGED
|
@@ -98,7 +98,7 @@ function printHelp() {
|
|
|
98
98
|
" - --from-openclaw marks sync runs triggered by the OpenClaw session plugin.",
|
|
99
99
|
" - --debug shows original backend errors.",
|
|
100
100
|
" - device-login pairs a headless CLI / SSH session with a browser sign-in (15-min code).",
|
|
101
|
-
" - sessions exports metadata-only Claude/Codex efficiency analytics; no prompt or response text is retained.",
|
|
101
|
+
" - sessions exports metadata-only Claude/Codex/Grok/ZCode efficiency analytics; no prompt or response text is retained.",
|
|
102
102
|
"",
|
|
103
103
|
].join("\n"),
|
|
104
104
|
);
|
package/src/commands/init.js
CHANGED
|
@@ -13,6 +13,7 @@ const {
|
|
|
13
13
|
chmod600IfPossible,
|
|
14
14
|
} = require("../lib/fs");
|
|
15
15
|
const { resolveMimoNativeDbPath } = require("../lib/install-resolver");
|
|
16
|
+
const { expandHome } = require("../lib/scan-roots");
|
|
16
17
|
const { prompt, promptHidden } = require("../lib/prompt");
|
|
17
18
|
const {
|
|
18
19
|
upsertCodexNotify,
|
|
@@ -130,6 +131,7 @@ const SUPPORTED_PROVIDERS = [
|
|
|
130
131
|
"Kimi Code",
|
|
131
132
|
"CodeBuddy",
|
|
132
133
|
"WorkBuddy",
|
|
134
|
+
"WorkBuddy AI",
|
|
133
135
|
"Grok Build",
|
|
134
136
|
"oh-my-pi",
|
|
135
137
|
"OmO",
|
|
@@ -578,6 +580,10 @@ async function repairRuntimeIntegrations({
|
|
|
578
580
|
settingsPath: context.workbuddySettingsPath,
|
|
579
581
|
hookCommand: context.workbuddyHookCommand,
|
|
580
582
|
})],
|
|
583
|
+
["workbuddy-ai", context.workbuddyAiDir, () => upsertClaudeHook({
|
|
584
|
+
settingsPath: context.workbuddyAiSettingsPath,
|
|
585
|
+
hookCommand: context.workbuddyAiHookCommand,
|
|
586
|
+
})],
|
|
581
587
|
];
|
|
582
588
|
for (const [key, configDir, repair] of hookRepairs) {
|
|
583
589
|
if (await isDir(configDir)) await attempt(key, repair);
|
|
@@ -622,6 +628,12 @@ function buildIntegrationTargets({ home, trackerDir, notifyPath }) {
|
|
|
622
628
|
const workbuddyDir = process.env.WORKBUDDY_HOME || path.join(home, ".workbuddy");
|
|
623
629
|
const workbuddySettingsPath = path.join(workbuddyDir, "settings.json");
|
|
624
630
|
const workbuddyHookCommand = buildHookCommand(notifyPath, "workbuddy");
|
|
631
|
+
// WorkBuddy AI is the international build of the very same CLI. It keeps its
|
|
632
|
+
// data in a sibling home (~/.workbuddy-ai), so it needs its own hook install
|
|
633
|
+
// and its own --source token to be attributed separately from the CN build.
|
|
634
|
+
const workbuddyAiDir = expandHome(process.env.WORKBUDDY_AI_HOME, home) || path.join(home, ".workbuddy-ai");
|
|
635
|
+
const workbuddyAiSettingsPath = path.join(workbuddyAiDir, "settings.json");
|
|
636
|
+
const workbuddyAiHookCommand = buildHookCommand(notifyPath, "workbuddy-ai");
|
|
625
637
|
const geminiConfigDir = resolveGeminiConfigDir({ home, env: process.env });
|
|
626
638
|
const geminiSettingsPath = resolveGeminiSettingsPath({ configDir: geminiConfigDir });
|
|
627
639
|
const geminiHookCommand = buildGeminiHookCommand(notifyPath);
|
|
@@ -647,6 +659,9 @@ function buildIntegrationTargets({ home, trackerDir, notifyPath }) {
|
|
|
647
659
|
workbuddyDir,
|
|
648
660
|
workbuddySettingsPath,
|
|
649
661
|
workbuddyHookCommand,
|
|
662
|
+
workbuddyAiDir,
|
|
663
|
+
workbuddyAiSettingsPath,
|
|
664
|
+
workbuddyAiHookCommand,
|
|
650
665
|
geminiConfigDir,
|
|
651
666
|
geminiSettingsPath,
|
|
652
667
|
geminiHookCommand,
|
|
@@ -1034,6 +1049,18 @@ async function applyIntegrationSetup({
|
|
|
1034
1049
|
summary.push({ label: "WorkBuddy", status: "skipped", detail: "Config not found" });
|
|
1035
1050
|
}
|
|
1036
1051
|
|
|
1052
|
+
// WorkBuddy AI: international build, same hook schema, sibling home.
|
|
1053
|
+
const workbuddyAiDirExists = await isDir(context.workbuddyAiDir);
|
|
1054
|
+
if (workbuddyAiDirExists) {
|
|
1055
|
+
await upsertClaudeHook({
|
|
1056
|
+
settingsPath: context.workbuddyAiSettingsPath,
|
|
1057
|
+
hookCommand: context.workbuddyAiHookCommand,
|
|
1058
|
+
});
|
|
1059
|
+
summary.push({ label: "WorkBuddy AI", status: "installed", detail: "Hooks installed" });
|
|
1060
|
+
} else {
|
|
1061
|
+
summary.push({ label: "WorkBuddy AI", status: "skipped", detail: "Config not found" });
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1037
1064
|
const openclawBefore = await probeOpenclawSessionPluginState({
|
|
1038
1065
|
home,
|
|
1039
1066
|
trackerDir,
|
|
@@ -1187,6 +1214,21 @@ async function previewIntegrations({ context }) {
|
|
|
1187
1214
|
summary.push({ label: "WorkBuddy", status: "skipped", detail: "Config not found" });
|
|
1188
1215
|
}
|
|
1189
1216
|
|
|
1217
|
+
const workbuddyAiDirExists = await isDir(context.workbuddyAiDir);
|
|
1218
|
+
if (workbuddyAiDirExists) {
|
|
1219
|
+
const configured = await isClaudeHookConfigured({
|
|
1220
|
+
settingsPath: context.workbuddyAiSettingsPath,
|
|
1221
|
+
hookCommand: context.workbuddyAiHookCommand,
|
|
1222
|
+
});
|
|
1223
|
+
summary.push({
|
|
1224
|
+
label: "WorkBuddy AI",
|
|
1225
|
+
status: "installed",
|
|
1226
|
+
detail: configured ? "Hooks already installed" : "Will install hooks",
|
|
1227
|
+
});
|
|
1228
|
+
} else {
|
|
1229
|
+
summary.push({ label: "WorkBuddy AI", status: "skipped", detail: "Config not found" });
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1190
1232
|
const geminiConfigExists = await isDir(context.geminiConfigDir);
|
|
1191
1233
|
if (geminiConfigExists) {
|
|
1192
1234
|
const configured = await isGeminiHookConfigured({
|
|
@@ -1491,7 +1533,7 @@ try {
|
|
|
1491
1533
|
? codeOriginalPath
|
|
1492
1534
|
: source === 'acode'
|
|
1493
1535
|
? acodeOriginalPath
|
|
1494
|
-
: source === 'claude' || source === 'opencode' || source === 'gemini' || source === 'codebuddy' || source === 'workbuddy'
|
|
1536
|
+
: source === 'claude' || source === 'opencode' || source === 'gemini' || source === 'codebuddy' || source === 'workbuddy' || source === 'workbuddy-ai'
|
|
1495
1537
|
? null
|
|
1496
1538
|
: codexOriginalPath;
|
|
1497
1539
|
if (originalPath) {
|
package/src/commands/status.js
CHANGED
|
@@ -221,6 +221,11 @@ async function cmdStatus(argv = []) {
|
|
|
221
221
|
resolveWorkbuddyHome(process.env) || path.join(home, ".workbuddy"),
|
|
222
222
|
"settings.json",
|
|
223
223
|
);
|
|
224
|
+
// WorkBuddy AI — international build, sibling home (~/.workbuddy-ai).
|
|
225
|
+
const workbuddyAiSettingsPath = path.join(
|
|
226
|
+
resolveWorkbuddyHome(process.env, "workbuddy-ai") || path.join(home, ".workbuddy-ai"),
|
|
227
|
+
"settings.json",
|
|
228
|
+
);
|
|
224
229
|
const geminiConfigDir = resolveGeminiConfigDir({ home, env: process.env });
|
|
225
230
|
const geminiSettingsPath = resolveGeminiSettingsPath({
|
|
226
231
|
configDir: geminiConfigDir,
|
|
@@ -235,6 +240,7 @@ async function cmdStatus(argv = []) {
|
|
|
235
240
|
const claudeHookCommand = buildClaudeHookCommand(notifyPath);
|
|
236
241
|
const codebuddyHookCommand = buildHookCommand(notifyPath, "codebuddy");
|
|
237
242
|
const workbuddyHookCommand = buildHookCommand(notifyPath, "workbuddy");
|
|
243
|
+
const workbuddyAiHookCommand = buildHookCommand(notifyPath, "workbuddy-ai");
|
|
238
244
|
const geminiHookCommand = buildGeminiHookCommand(notifyPath);
|
|
239
245
|
|
|
240
246
|
const config = await readJson(configPath);
|
|
@@ -308,6 +314,10 @@ async function cmdStatus(argv = []) {
|
|
|
308
314
|
settingsPath: workbuddySettingsPath,
|
|
309
315
|
hookCommand: workbuddyHookCommand,
|
|
310
316
|
});
|
|
317
|
+
const workbuddyAiHookConfigured = await isClaudeHookConfigured({
|
|
318
|
+
settingsPath: workbuddyAiSettingsPath,
|
|
319
|
+
hookCommand: workbuddyAiHookCommand,
|
|
320
|
+
});
|
|
311
321
|
const geminiHookConfigured = await isGeminiHookConfigured({
|
|
312
322
|
settingsPath: geminiSettingsPath,
|
|
313
323
|
hookCommand: geminiHookCommand,
|
|
@@ -493,6 +503,15 @@ async function cmdStatus(argv = []) {
|
|
|
493
503
|
? fssync.existsSync(path.join(workbuddyHome, "workbuddy.db"))
|
|
494
504
|
: false;
|
|
495
505
|
|
|
506
|
+
const workbuddyAiHome = resolveWorkbuddyHome(process.env, "workbuddy-ai");
|
|
507
|
+
const workbuddyAiInstalled = Boolean(workbuddyAiHome && fssync.existsSync(workbuddyAiHome));
|
|
508
|
+
const workbuddyAiFiles = workbuddyAiInstalled
|
|
509
|
+
? resolveWorkbuddyProjectFiles(process.env, "workbuddy-ai")
|
|
510
|
+
: [];
|
|
511
|
+
const workbuddyAiDbExists = workbuddyAiInstalled
|
|
512
|
+
? fssync.existsSync(path.join(workbuddyAiHome, "workbuddy.db"))
|
|
513
|
+
: false;
|
|
514
|
+
|
|
496
515
|
// oh-my-pi — passive scan + optional notify extension.
|
|
497
516
|
const ompAgentDir = resolveOmpAgentDir(process.env);
|
|
498
517
|
const ompInstalled = Boolean(ompAgentDir) && fssync.existsSync(path.join(ompAgentDir, "sessions"));
|
|
@@ -1003,6 +1022,7 @@ async function cmdStatus(argv = []) {
|
|
|
1003
1022
|
openclaw_session_plugin: Boolean(openclawSessionPluginState?.configured),
|
|
1004
1023
|
codebuddy: Boolean(codebuddyHookConfigured),
|
|
1005
1024
|
workbuddy: Boolean(workbuddyHookConfigured),
|
|
1025
|
+
"workbuddy-ai": Boolean(workbuddyAiHookConfigured),
|
|
1006
1026
|
grok: Boolean(grokHookState?.configured),
|
|
1007
1027
|
},
|
|
1008
1028
|
});
|
|
@@ -1046,6 +1066,7 @@ async function cmdStatus(argv = []) {
|
|
|
1046
1066
|
openclaw_legacy: Boolean(openclawHookState?.configured),
|
|
1047
1067
|
codebuddy: codebuddyInstalled ? Boolean(codebuddyHookConfigured) : null,
|
|
1048
1068
|
workbuddy: workbuddyInstalled ? Boolean(workbuddyHookConfigured) : null,
|
|
1069
|
+
"workbuddy-ai": workbuddyAiInstalled ? Boolean(workbuddyAiHookConfigured) : null,
|
|
1049
1070
|
grok: grokInstalled ? Boolean(grokHookState?.configured) : null,
|
|
1050
1071
|
},
|
|
1051
1072
|
providers: {
|
|
@@ -1077,6 +1098,9 @@ async function cmdStatus(argv = []) {
|
|
|
1077
1098
|
workbuddy: workbuddyInstalled
|
|
1078
1099
|
? { installed: true, files: workbuddyFiles.length }
|
|
1079
1100
|
: { installed: false },
|
|
1101
|
+
workbuddy_ai: workbuddyAiInstalled
|
|
1102
|
+
? { installed: true, files: workbuddyAiFiles.length }
|
|
1103
|
+
: { installed: false },
|
|
1080
1104
|
omp: ompInstalled || ompHookState.ompPresent
|
|
1081
1105
|
? {
|
|
1082
1106
|
installed: true,
|
|
@@ -1275,6 +1299,9 @@ async function cmdStatus(argv = []) {
|
|
|
1275
1299
|
workbuddyInstalled
|
|
1276
1300
|
? `- WorkBuddy hooks: ${workbuddyHookConfigured ? "set" : "unset"} (${workbuddyFiles.length} session jsonl file${workbuddyFiles.length !== 1 ? "s" : ""} found, SQLite DB ${workbuddyDbExists ? "found" : "not found"})`
|
|
1277
1301
|
: null,
|
|
1302
|
+
workbuddyAiInstalled
|
|
1303
|
+
? `- WorkBuddy AI hooks: ${workbuddyAiHookConfigured ? "set" : "unset"} (${workbuddyAiFiles.length} session jsonl file${workbuddyAiFiles.length !== 1 ? "s" : ""} found, SQLite DB ${workbuddyAiDbExists ? "found" : "not found"})`
|
|
1304
|
+
: null,
|
|
1278
1305
|
ompInstalled || ompHookState.ompPresent
|
|
1279
1306
|
? `- oh-my-pi: passive reader (${ompFiles.length} session jsonl file${ompFiles.length !== 1 ? "s" : ""} found${ompHookState.configured ? ", notify extension: yes" : ", notify extension: no"})`
|
|
1280
1307
|
: null,
|
package/src/commands/sync.js
CHANGED
|
@@ -354,6 +354,7 @@ const AUTO_SYNC_SOURCES = new Set([
|
|
|
354
354
|
"trae",
|
|
355
355
|
"unsloth",
|
|
356
356
|
"workbuddy",
|
|
357
|
+
"workbuddy-ai",
|
|
357
358
|
"zcode",
|
|
358
359
|
"zed",
|
|
359
360
|
]);
|
|
@@ -984,8 +985,9 @@ async function cmdSync(argv, context = {}) {
|
|
|
984
985
|
// Plugin-triggered sync points at one specific session file; a normal full
|
|
985
986
|
// sync also passively scans every on-disk OpenClaw transcript so usage is
|
|
986
987
|
// captured even when the session plugin never fires (issue #264). The scan
|
|
987
|
-
// is gated to full syncs
|
|
988
|
-
//
|
|
988
|
+
// is gated to full syncs except for gateway lifecycle signals. A scoped
|
|
989
|
+
// agent_end reads only its transcript or its session in the agent database,
|
|
990
|
+
// and the ordinary background tick stays cheap. The
|
|
989
991
|
// event-identity dedup makes the plugin and passive paths idempotent, so
|
|
990
992
|
// overlap on the same file is safe.
|
|
991
993
|
//
|
|
@@ -999,12 +1001,22 @@ async function cmdSync(argv, context = {}) {
|
|
|
999
1001
|
path: openclawSignal.sessionFile,
|
|
1000
1002
|
source: "openclaw",
|
|
1001
1003
|
});
|
|
1004
|
+
for (const dbPath of [
|
|
1005
|
+
path.join(openclawSignal.openclawHome, "agents", openclawSignal.agentId, "agent", "openclaw-agent.sqlite"),
|
|
1006
|
+
path.join(openclawSignal.openclawHome, "agents", openclawSignal.agentId, "openclaw-agent.sqlite"),
|
|
1007
|
+
]) {
|
|
1008
|
+
if (!(await fs.stat(dbPath).catch(() => null))?.isFile()) continue;
|
|
1009
|
+
openclawSessionFiles.set(openclawCursorKey(dbPath), {
|
|
1010
|
+
path: dbPath, source: "openclaw", sessionId: openclawSignal.sessionId,
|
|
1011
|
+
});
|
|
1012
|
+
break;
|
|
1013
|
+
}
|
|
1002
1014
|
}
|
|
1003
|
-
if (isFullSourceScan && sourceAllowed("openclaw")) {
|
|
1015
|
+
if ((isFullSourceScan || (opts.fromOpenclaw && !openclawSignal)) && sourceAllowed("openclaw")) {
|
|
1004
1016
|
try {
|
|
1005
1017
|
for (const f of await resolveOpenclawSessionFiles(process.env)) {
|
|
1006
1018
|
const key = openclawCursorKey(f);
|
|
1007
|
-
if (!openclawSessionFiles.has(key)) {
|
|
1019
|
+
if (!openclawSessionFiles.has(key) || f.endsWith(".sqlite")) {
|
|
1008
1020
|
openclawSessionFiles.set(key, { path: f, source: "openclaw" });
|
|
1009
1021
|
}
|
|
1010
1022
|
}
|
|
@@ -2597,6 +2609,42 @@ async function cmdSync(argv, context = {}) {
|
|
|
2597
2609
|
}
|
|
2598
2610
|
}
|
|
2599
2611
|
|
|
2612
|
+
// ── WorkBuddy AI — international build (~/.workbuddy-ai/projects/**/*.jsonl) ──
|
|
2613
|
+
// Same Claude-fork family and byte-identical JSONL as the CN build above;
|
|
2614
|
+
// only the home directory differs, so it reuses the WorkBuddy parser and
|
|
2615
|
+
// gets its own source key (and cursor namespace) so the two builds stay
|
|
2616
|
+
// separable instead of merging into one provider row.
|
|
2617
|
+
let workbuddyAiResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
2618
|
+
const workbuddyAiFiles = sourceAllowed("workbuddy-ai")
|
|
2619
|
+
? mergeBothFileSources({
|
|
2620
|
+
resolveFiles: (resolveEnv) => resolveWorkbuddyProjectFiles(resolveEnv, "workbuddy-ai"),
|
|
2621
|
+
env: process.env,
|
|
2622
|
+
})
|
|
2623
|
+
: [];
|
|
2624
|
+
if (sourceAllowed("workbuddy-ai")) {
|
|
2625
|
+
if (progress?.enabled) {
|
|
2626
|
+
progress.start(`Parsing WorkBuddy AI ${renderBar(0)} | buckets 0`);
|
|
2627
|
+
}
|
|
2628
|
+
try {
|
|
2629
|
+
workbuddyAiResult = await parseWorkbuddyIncremental({
|
|
2630
|
+
projectFiles: workbuddyAiFiles,
|
|
2631
|
+
cursors,
|
|
2632
|
+
queuePath,
|
|
2633
|
+
env: process.env,
|
|
2634
|
+
source: "workbuddy-ai",
|
|
2635
|
+
onProgress: (p) => {
|
|
2636
|
+
if (!progress?.enabled) return;
|
|
2637
|
+
const pct = p.total > 0 ? p.index / p.total : 1;
|
|
2638
|
+
progress.update(
|
|
2639
|
+
`Parsing WorkBuddy AI ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} files | buckets ${formatNumber(p.bucketsQueued)}`,
|
|
2640
|
+
);
|
|
2641
|
+
},
|
|
2642
|
+
});
|
|
2643
|
+
} catch (err) {
|
|
2644
|
+
warnProviderParseFailure("WorkBuddy AI", err, opts);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2600
2648
|
// ── oh-my-pi (passive ~/.omp/agent/sessions/**/*.jsonl reader) ──
|
|
2601
2649
|
// Task-subagent transcripts (nested below the cwd level) are scanned too,
|
|
2602
2650
|
// so their usage counts toward the omp totals.
|
|
@@ -3256,6 +3304,7 @@ async function cmdSync(argv, context = {}) {
|
|
|
3256
3304
|
kimiCodeResult.recordsProcessed +
|
|
3257
3305
|
codebuddyResult.recordsProcessed +
|
|
3258
3306
|
workbuddyResult.recordsProcessed +
|
|
3307
|
+
workbuddyAiResult.recordsProcessed +
|
|
3259
3308
|
ompResult.recordsProcessed +
|
|
3260
3309
|
omoResult.recordsProcessed +
|
|
3261
3310
|
piResult.recordsProcessed +
|
|
@@ -3300,6 +3349,7 @@ async function cmdSync(argv, context = {}) {
|
|
|
3300
3349
|
kimiCodeResult.bucketsQueued +
|
|
3301
3350
|
codebuddyResult.bucketsQueued +
|
|
3302
3351
|
workbuddyResult.bucketsQueued +
|
|
3352
|
+
workbuddyAiResult.bucketsQueued +
|
|
3303
3353
|
ompResult.bucketsQueued +
|
|
3304
3354
|
omoResult.bucketsQueued +
|
|
3305
3355
|
piResult.bucketsQueued +
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const os = require("node:os");
|
|
2
2
|
const path = require("node:path");
|
|
3
3
|
const fs = require("node:fs/promises");
|
|
4
|
+
const { expandHome } = require("../lib/scan-roots");
|
|
4
5
|
|
|
5
6
|
const {
|
|
6
7
|
restoreCodexNotify,
|
|
@@ -44,6 +45,9 @@ async function cmdUninstall(argv) {
|
|
|
44
45
|
const codebuddySettingsPath = path.join(codebuddyDir, "settings.json");
|
|
45
46
|
const workbuddyDir = process.env.WORKBUDDY_HOME || path.join(home, ".workbuddy");
|
|
46
47
|
const workbuddySettingsPath = path.join(workbuddyDir, "settings.json");
|
|
48
|
+
// WorkBuddy AI — international build, sibling home (~/.workbuddy-ai).
|
|
49
|
+
const workbuddyAiDir = expandHome(process.env.WORKBUDDY_AI_HOME, home) || path.join(home, ".workbuddy-ai");
|
|
50
|
+
const workbuddyAiSettingsPath = path.join(workbuddyAiDir, "settings.json");
|
|
47
51
|
const geminiConfigDir = resolveGeminiConfigDir({ home, env: process.env });
|
|
48
52
|
const geminiSettingsPath = resolveGeminiSettingsPath({ configDir: geminiConfigDir });
|
|
49
53
|
const opencodeConfigDir = resolveOpencodeConfigDir({ home, env: process.env });
|
|
@@ -57,6 +61,7 @@ async function cmdUninstall(argv) {
|
|
|
57
61
|
const claudeHookCommand = buildClaudeHookCommand(notifyPath);
|
|
58
62
|
const codebuddyHookCommand = buildHookCommand(notifyPath, "codebuddy");
|
|
59
63
|
const workbuddyHookCommand = buildHookCommand(notifyPath, "workbuddy");
|
|
64
|
+
const workbuddyAiHookCommand = buildHookCommand(notifyPath, "workbuddy-ai");
|
|
60
65
|
const geminiHookCommand = buildGeminiHookCommand(notifyPath);
|
|
61
66
|
|
|
62
67
|
const codexConfigExists = await isFile(codexConfigPath);
|
|
@@ -65,6 +70,7 @@ async function cmdUninstall(argv) {
|
|
|
65
70
|
const claudeConfigExists = await isFile(claudeSettingsPath);
|
|
66
71
|
const codebuddyConfigExists = await isFile(codebuddySettingsPath);
|
|
67
72
|
const workbuddyConfigExists = await isFile(workbuddySettingsPath);
|
|
73
|
+
const workbuddyAiConfigExists = await isFile(workbuddyAiSettingsPath);
|
|
68
74
|
const geminiConfigExists = await isDir(geminiConfigDir);
|
|
69
75
|
const opencodeConfigExists = await isDir(opencodeConfigDir);
|
|
70
76
|
const codexRestore = codexConfigExists
|
|
@@ -106,6 +112,12 @@ async function cmdUninstall(argv) {
|
|
|
106
112
|
hookCommand: workbuddyHookCommand,
|
|
107
113
|
})
|
|
108
114
|
: { removed: false, skippedReason: "config-missing" };
|
|
115
|
+
const workbuddyAiRemove = workbuddyAiConfigExists
|
|
116
|
+
? await removeClaudeHook({
|
|
117
|
+
settingsPath: workbuddyAiSettingsPath,
|
|
118
|
+
hookCommand: workbuddyAiHookCommand,
|
|
119
|
+
})
|
|
120
|
+
: { removed: false, skippedReason: "config-missing" };
|
|
109
121
|
const geminiRemove = geminiConfigExists
|
|
110
122
|
? await removeGeminiHook({ settingsPath: geminiSettingsPath, hookCommand: geminiHookCommand })
|
|
111
123
|
: { removed: false, skippedReason: "config-missing" };
|
|
@@ -191,6 +203,13 @@ async function cmdUninstall(argv) {
|
|
|
191
203
|
? "- WorkBuddy hooks: no change"
|
|
192
204
|
: "- WorkBuddy hooks: skipped"
|
|
193
205
|
: "- WorkBuddy hooks: skipped (settings.json not found)",
|
|
206
|
+
workbuddyAiConfigExists
|
|
207
|
+
? workbuddyAiRemove?.removed
|
|
208
|
+
? `- WorkBuddy AI hooks removed: ${workbuddyAiSettingsPath}`
|
|
209
|
+
: workbuddyAiRemove?.skippedReason === "hook-missing"
|
|
210
|
+
? "- WorkBuddy AI hooks: no change"
|
|
211
|
+
: "- WorkBuddy AI hooks: skipped"
|
|
212
|
+
: "- WorkBuddy AI hooks: skipped (settings.json not found)",
|
|
194
213
|
geminiConfigExists
|
|
195
214
|
? geminiRemove?.removed
|
|
196
215
|
? `- Gemini hooks removed: ${geminiSettingsPath}`
|