tokentracker-cli 0.2.24 → 0.2.26
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 +21 -33
- package/bin/tracker.js +1 -1
- package/dashboard/dist/assets/{AsciiBox-vyDhXYY5.js → AsciiBox-fxqdUErY.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-CrplxZFL.js → DashboardPage-rdYpdfso.js} +1 -1
- package/dashboard/dist/assets/{LandingExtras-DlrtqIDj.js → LandingExtras-7PDallbH.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-Czwkjje0.js → LeaderboardPage-CU_JeLPO.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfilePage-C4rorru6.js → LeaderboardProfilePage-D3B45Jjd.js} +1 -1
- package/dashboard/dist/assets/{MatrixRain-bGmRmuOW.js → MatrixRain-DR9XEe-r.js} +1 -1
- package/dashboard/dist/assets/{MatrixShell-BfOGBm5o.js → MatrixShell-B6_X7zAp.js} +1 -1
- package/dashboard/dist/assets/{main-BYPG1_bI.js → main-B206gspN.js} +4 -4
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/commands/init.js +5 -5
- package/src/commands/sync.js +9 -9
- package/src/lib/debug-flags.js +1 -1
- package/src/lib/insforge-client.js +2 -2
- package/src/lib/openclaw-hook.js +10 -10
- package/src/lib/openclaw-session-plugin.js +10 -10
- package/src/lib/opencode-config.js +1 -1
- package/src/lib/runtime-config.js +7 -7
- package/README.old.md +0 -324
- package/README.zh-CN.md +0 -440
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
]
|
|
108
108
|
}
|
|
109
109
|
</script>
|
|
110
|
-
<script type="module" crossorigin src="/assets/main-
|
|
110
|
+
<script type="module" crossorigin src="/assets/main-B206gspN.js"></script>
|
|
111
111
|
<link rel="stylesheet" crossorigin href="/assets/main-hwTpulbk.css">
|
|
112
112
|
</head>
|
|
113
113
|
<body>
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"description": "Shareable Token Tracker dashboard snapshot."
|
|
52
52
|
}
|
|
53
53
|
</script>
|
|
54
|
-
<script type="module" crossorigin src="/assets/main-
|
|
54
|
+
<script type="module" crossorigin src="/assets/main-B206gspN.js"></script>
|
|
55
55
|
<link rel="stylesheet" crossorigin href="/assets/main-hwTpulbk.css">
|
|
56
56
|
</head>
|
|
57
57
|
<body>
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -166,7 +166,7 @@ async function cmdInit(argv) {
|
|
|
166
166
|
let deviceId = setup.deviceId;
|
|
167
167
|
|
|
168
168
|
// Cloud account linking — only when explicitly requested via env or flags
|
|
169
|
-
const wantCloudLink = setup.pendingBrowserAuth && (opts.linkCode || process.env.
|
|
169
|
+
const wantCloudLink = setup.pendingBrowserAuth && (opts.linkCode || process.env.TOKENTRACKER_DEVICE_TOKEN || process.env.TOKENTRACKER_ACCESS_TOKEN);
|
|
170
170
|
|
|
171
171
|
if (wantCloudLink) {
|
|
172
172
|
const deviceName = opts.deviceName || os.hostname();
|
|
@@ -758,8 +758,8 @@ const fallbackPkg = ${JSON.stringify(fallbackPkg)};
|
|
|
758
758
|
const selfPath = path.resolve(__filename);
|
|
759
759
|
const home = os.homedir();
|
|
760
760
|
const debugLogPath = path.join(trackerDir, 'notify.debug.jsonl');
|
|
761
|
-
const debugEnabled = ['1', 'true'].includes((process.env.
|
|
762
|
-
const debugMaxBytesRaw = Number.parseInt(process.env.
|
|
761
|
+
const debugEnabled = ['1', 'true'].includes((process.env.TOKENTRACKER_NOTIFY_DEBUG || '').toLowerCase());
|
|
762
|
+
const debugMaxBytesRaw = Number.parseInt(process.env.TOKENTRACKER_NOTIFY_DEBUG_MAX_BYTES || '', 10);
|
|
763
763
|
const debugMaxBytes = Number.isFinite(debugMaxBytesRaw) && debugMaxBytesRaw > 0
|
|
764
764
|
? debugMaxBytesRaw
|
|
765
765
|
: 1_000_000;
|
|
@@ -791,7 +791,7 @@ if (debugEnabled) {
|
|
|
791
791
|
// Throttle spawn: at most once per 20 seconds.
|
|
792
792
|
try {
|
|
793
793
|
const throttlePath = path.join(trackerDir, 'sync.throttle');
|
|
794
|
-
let deviceToken = process.env.
|
|
794
|
+
let deviceToken = process.env.TOKENTRACKER_DEVICE_TOKEN || null;
|
|
795
795
|
if (!deviceToken) {
|
|
796
796
|
try {
|
|
797
797
|
const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
@@ -967,5 +967,5 @@ async function copyRuntimeDependencies({ from, to }) {
|
|
|
967
967
|
}
|
|
968
968
|
|
|
969
969
|
function isDebugEnabled() {
|
|
970
|
-
return process.env.
|
|
970
|
+
return process.env.TOKENTRACKER_DEBUG === "1";
|
|
971
971
|
}
|
package/src/commands/sync.js
CHANGED
|
@@ -486,26 +486,26 @@ function normalizeString(value) {
|
|
|
486
486
|
function resolveOpenclawSignal({ home, env } = {}) {
|
|
487
487
|
if (!env) return null;
|
|
488
488
|
|
|
489
|
-
const agentId = normalizeString(env.
|
|
490
|
-
const sessionId = normalizeString(env.
|
|
489
|
+
const agentId = normalizeString(env.TOKENTRACKER_OPENCLAW_AGENT_ID);
|
|
490
|
+
const sessionId = normalizeString(env.TOKENTRACKER_OPENCLAW_PREV_SESSION_ID);
|
|
491
491
|
if (!agentId || !sessionId) return null;
|
|
492
492
|
|
|
493
493
|
const openclawHome =
|
|
494
|
-
normalizeString(env.
|
|
494
|
+
normalizeString(env.TOKENTRACKER_OPENCLAW_HOME) || path.join(home || os.homedir(), ".openclaw");
|
|
495
495
|
const sessionFile = path.join(openclawHome, "agents", agentId, "sessions", `${sessionId}.jsonl`);
|
|
496
496
|
|
|
497
497
|
const prevTotals = {
|
|
498
|
-
totalTokens: normalizeNonNegativeInt(env.
|
|
499
|
-
inputTokens: normalizeNonNegativeInt(env.
|
|
500
|
-
outputTokens: normalizeNonNegativeInt(env.
|
|
501
|
-
model: normalizeString(env.
|
|
502
|
-
updatedAt: normalizeIsoOrEpoch(env.
|
|
498
|
+
totalTokens: normalizeNonNegativeInt(env.TOKENTRACKER_OPENCLAW_PREV_TOTAL_TOKENS),
|
|
499
|
+
inputTokens: normalizeNonNegativeInt(env.TOKENTRACKER_OPENCLAW_PREV_INPUT_TOKENS),
|
|
500
|
+
outputTokens: normalizeNonNegativeInt(env.TOKENTRACKER_OPENCLAW_PREV_OUTPUT_TOKENS),
|
|
501
|
+
model: normalizeString(env.TOKENTRACKER_OPENCLAW_PREV_MODEL),
|
|
502
|
+
updatedAt: normalizeIsoOrEpoch(env.TOKENTRACKER_OPENCLAW_PREV_UPDATED_AT),
|
|
503
503
|
};
|
|
504
504
|
|
|
505
505
|
return {
|
|
506
506
|
agentId,
|
|
507
507
|
sessionId,
|
|
508
|
-
sessionKey: normalizeString(env.
|
|
508
|
+
sessionKey: normalizeString(env.TOKENTRACKER_OPENCLAW_SESSION_KEY),
|
|
509
509
|
openclawHome,
|
|
510
510
|
sessionFile,
|
|
511
511
|
prevTotals,
|
package/src/lib/debug-flags.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function stripDebugFlag(argv, env = process.env) {
|
|
2
2
|
const filtered = Array.isArray(argv) ? argv.filter((arg) => arg !== "--debug") : [];
|
|
3
|
-
const debugEnv = String(env?.
|
|
3
|
+
const debugEnv = String(env?.TOKENTRACKER_DEBUG || "") === "1";
|
|
4
4
|
return { argv: filtered, debug: filtered.length !== (argv || []).length || debugEnv };
|
|
5
5
|
}
|
|
6
6
|
|
|
@@ -11,11 +11,11 @@ function loadInsforgeSdk() {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function getAnonKey({ env = process.env } = {}) {
|
|
14
|
-
return env.
|
|
14
|
+
return env.TOKENTRACKER_INSFORGE_ANON_KEY || "";
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function getHttpTimeoutMs({ env = process.env } = {}) {
|
|
18
|
-
const raw = readEnvValue(env, ["
|
|
18
|
+
const raw = readEnvValue(env, ["TOKENTRACKER_HTTP_TIMEOUT_MS"]);
|
|
19
19
|
if (raw == null || raw === "") return 20_000;
|
|
20
20
|
const n = Number(raw);
|
|
21
21
|
if (!Number.isFinite(n)) return 20_000;
|
package/src/lib/openclaw-hook.js
CHANGED
|
@@ -14,7 +14,7 @@ function resolveOpenclawHookPaths({ home = os.homedir(), trackerDir, env = proce
|
|
|
14
14
|
normalizeString(env.OPENCLAW_CONFIG_PATH) || path.join(home, ".openclaw", "openclaw.json");
|
|
15
15
|
|
|
16
16
|
const openclawHome =
|
|
17
|
-
normalizeString(env.
|
|
17
|
+
normalizeString(env.TOKENTRACKER_OPENCLAW_HOME) ||
|
|
18
18
|
normalizeString(env.OPENCLAW_STATE_DIR) ||
|
|
19
19
|
path.join(home, ".openclaw");
|
|
20
20
|
|
|
@@ -324,21 +324,21 @@ function buildHookHandler({ trackerDir, packageName = "vibeusage", openclawHome
|
|
|
324
324
|
`\n` +
|
|
325
325
|
` const env = {\n` +
|
|
326
326
|
` ...process.env,\n` +
|
|
327
|
-
`
|
|
328
|
-
`
|
|
329
|
-
`
|
|
330
|
-
`
|
|
327
|
+
` TOKENTRACKER_OPENCLAW_AGENT_ID: agentId,\n` +
|
|
328
|
+
` TOKENTRACKER_OPENCLAW_SESSION_KEY: sessionKey,\n` +
|
|
329
|
+
` TOKENTRACKER_OPENCLAW_PREV_SESSION_ID: sessionId,\n` +
|
|
330
|
+
` TOKENTRACKER_OPENCLAW_HOME: openclawHome\n` +
|
|
331
331
|
` };\n` +
|
|
332
332
|
` const prevTotalTokens = toNonNegativeInt(sessionEntry && sessionEntry.totalTokens);\n` +
|
|
333
333
|
` const prevInputTokens = toNonNegativeInt(sessionEntry && sessionEntry.inputTokens);\n` +
|
|
334
334
|
` const prevOutputTokens = toNonNegativeInt(sessionEntry && sessionEntry.outputTokens);\n` +
|
|
335
335
|
` const prevModel = normalize(sessionEntry && sessionEntry.model);\n` +
|
|
336
336
|
` const prevUpdatedAt = toIso(sessionEntry && sessionEntry.updatedAt);\n` +
|
|
337
|
-
` if (prevTotalTokens != null) env.
|
|
338
|
-
` if (prevInputTokens != null) env.
|
|
339
|
-
` if (prevOutputTokens != null) env.
|
|
340
|
-
` if (prevModel) env.
|
|
341
|
-
` if (prevUpdatedAt) env.
|
|
337
|
+
` if (prevTotalTokens != null) env.TOKENTRACKER_OPENCLAW_PREV_TOTAL_TOKENS = String(prevTotalTokens);\n` +
|
|
338
|
+
` if (prevInputTokens != null) env.TOKENTRACKER_OPENCLAW_PREV_INPUT_TOKENS = String(prevInputTokens);\n` +
|
|
339
|
+
` if (prevOutputTokens != null) env.TOKENTRACKER_OPENCLAW_PREV_OUTPUT_TOKENS = String(prevOutputTokens);\n` +
|
|
340
|
+
` if (prevModel) env.TOKENTRACKER_OPENCLAW_PREV_MODEL = prevModel;\n` +
|
|
341
|
+
` if (prevUpdatedAt) env.TOKENTRACKER_OPENCLAW_PREV_UPDATED_AT = prevUpdatedAt;\n` +
|
|
342
342
|
`\n` +
|
|
343
343
|
` const hasLocalRuntime = fs.existsSync(trackerBinPath);\n` +
|
|
344
344
|
` const hasLocalDeps = fs.existsSync(depsMarkerPath);\n` +
|
|
@@ -18,7 +18,7 @@ function resolveOpenclawSessionPluginPaths({
|
|
|
18
18
|
normalizeString(env.OPENCLAW_CONFIG_PATH) || path.join(home, ".openclaw", "openclaw.json");
|
|
19
19
|
|
|
20
20
|
const openclawHome =
|
|
21
|
-
normalizeString(env.
|
|
21
|
+
normalizeString(env.TOKENTRACKER_OPENCLAW_HOME) ||
|
|
22
22
|
normalizeString(env.OPENCLAW_STATE_DIR) ||
|
|
23
23
|
path.join(home, ".openclaw");
|
|
24
24
|
|
|
@@ -414,22 +414,22 @@ function buildSessionPluginIndex({ trackerDir, packageName = "vibeusage", opencl
|
|
|
414
414
|
`\n` +
|
|
415
415
|
`function buildSessionEnv({ agentId, sessionId, sessionKey, sessionEntry }) {\n` +
|
|
416
416
|
` const out = {\n` +
|
|
417
|
-
`
|
|
418
|
-
`
|
|
419
|
-
`
|
|
417
|
+
` TOKENTRACKER_OPENCLAW_AGENT_ID: agentId,\n` +
|
|
418
|
+
` TOKENTRACKER_OPENCLAW_PREV_SESSION_ID: sessionId,\n` +
|
|
419
|
+
` TOKENTRACKER_OPENCLAW_HOME: openclawHome\n` +
|
|
420
420
|
` };\n` +
|
|
421
421
|
` const key = normalize(sessionKey);\n` +
|
|
422
|
-
` if (key) out.
|
|
422
|
+
` if (key) out.TOKENTRACKER_OPENCLAW_SESSION_KEY = key;\n` +
|
|
423
423
|
` const prevTotalTokens = toNonNegativeInt(sessionEntry && sessionEntry.totalTokens);\n` +
|
|
424
424
|
` const prevInputTokens = toNonNegativeInt(sessionEntry && sessionEntry.inputTokens);\n` +
|
|
425
425
|
` const prevOutputTokens = toNonNegativeInt(sessionEntry && sessionEntry.outputTokens);\n` +
|
|
426
426
|
` const prevModel = normalize(sessionEntry && sessionEntry.model);\n` +
|
|
427
427
|
` const prevUpdatedAt = toIso(sessionEntry && sessionEntry.updatedAt);\n` +
|
|
428
|
-
` if (prevTotalTokens != null) out.
|
|
429
|
-
` if (prevInputTokens != null) out.
|
|
430
|
-
` if (prevOutputTokens != null) out.
|
|
431
|
-
` if (prevModel) out.
|
|
432
|
-
` if (prevUpdatedAt) out.
|
|
428
|
+
` if (prevTotalTokens != null) out.TOKENTRACKER_OPENCLAW_PREV_TOTAL_TOKENS = String(prevTotalTokens);\n` +
|
|
429
|
+
` if (prevInputTokens != null) out.TOKENTRACKER_OPENCLAW_PREV_INPUT_TOKENS = String(prevInputTokens);\n` +
|
|
430
|
+
` if (prevOutputTokens != null) out.TOKENTRACKER_OPENCLAW_PREV_OUTPUT_TOKENS = String(prevOutputTokens);\n` +
|
|
431
|
+
` if (prevModel) out.TOKENTRACKER_OPENCLAW_PREV_MODEL = prevModel;\n` +
|
|
432
|
+
` if (prevUpdatedAt) out.TOKENTRACKER_OPENCLAW_PREV_UPDATED_AT = prevUpdatedAt;\n` +
|
|
433
433
|
` return out;\n` +
|
|
434
434
|
`}\n` +
|
|
435
435
|
`\n` +
|
|
@@ -5,7 +5,7 @@ const fs = require("node:fs/promises");
|
|
|
5
5
|
const { ensureDir } = require("./fs");
|
|
6
6
|
|
|
7
7
|
const DEFAULT_PLUGIN_NAME = "vibeusage-tracker.js";
|
|
8
|
-
const PLUGIN_MARKER = "
|
|
8
|
+
const PLUGIN_MARKER = "TOKENTRACKER_PLUGIN";
|
|
9
9
|
const DEFAULT_EVENT = "session.updated";
|
|
10
10
|
|
|
11
11
|
function resolveOpencodeConfigDir({ home = os.homedir(), env = process.env } = {}) {
|
|
@@ -6,36 +6,36 @@ function resolveRuntimeConfig({ cli = {}, config = {}, env = process.env, defaul
|
|
|
6
6
|
const baseUrl = pickString(
|
|
7
7
|
cli.baseUrl,
|
|
8
8
|
config.baseUrl,
|
|
9
|
-
env?.
|
|
9
|
+
env?.TOKENTRACKER_INSFORGE_BASE_URL,
|
|
10
10
|
defaults.baseUrl,
|
|
11
11
|
DEFAULT_BASE_URL,
|
|
12
12
|
);
|
|
13
13
|
const dashboardUrl = pickString(
|
|
14
14
|
cli.dashboardUrl,
|
|
15
15
|
config.dashboardUrl,
|
|
16
|
-
env?.
|
|
16
|
+
env?.TOKENTRACKER_DASHBOARD_URL,
|
|
17
17
|
defaults.dashboardUrl,
|
|
18
18
|
DEFAULT_DASHBOARD_URL,
|
|
19
19
|
);
|
|
20
20
|
const deviceToken = pickString(
|
|
21
21
|
cli.deviceToken,
|
|
22
22
|
config.deviceToken,
|
|
23
|
-
env?.
|
|
23
|
+
env?.TOKENTRACKER_DEVICE_TOKEN,
|
|
24
24
|
defaults.deviceToken,
|
|
25
25
|
null,
|
|
26
26
|
);
|
|
27
27
|
const httpTimeoutMs = pickHttpTimeoutMs(
|
|
28
28
|
cli.httpTimeoutMs,
|
|
29
29
|
config.httpTimeoutMs,
|
|
30
|
-
env?.
|
|
30
|
+
env?.TOKENTRACKER_HTTP_TIMEOUT_MS,
|
|
31
31
|
defaults.httpTimeoutMs,
|
|
32
32
|
DEFAULT_HTTP_TIMEOUT_MS,
|
|
33
33
|
);
|
|
34
|
-
const debug = pickBoolean(cli.debug, config.debug, env?.
|
|
34
|
+
const debug = pickBoolean(cli.debug, config.debug, env?.TOKENTRACKER_DEBUG, defaults.debug, false);
|
|
35
35
|
const insforgeAnonKey = pickString(
|
|
36
36
|
cli.insforgeAnonKey,
|
|
37
37
|
config.insforgeAnonKey,
|
|
38
|
-
env?.
|
|
38
|
+
env?.TOKENTRACKER_INSFORGE_ANON_KEY,
|
|
39
39
|
defaults.insforgeAnonKey,
|
|
40
40
|
"",
|
|
41
41
|
);
|
|
@@ -43,7 +43,7 @@ function resolveRuntimeConfig({ cli = {}, config = {}, env = process.env, defaul
|
|
|
43
43
|
const autoRetryNoSpawn = pickBoolean(
|
|
44
44
|
cli.autoRetryNoSpawn,
|
|
45
45
|
config.autoRetryNoSpawn,
|
|
46
|
-
env?.
|
|
46
|
+
env?.TOKENTRACKER_AUTO_RETRY_NO_SPAWN,
|
|
47
47
|
defaults.autoRetryNoSpawn,
|
|
48
48
|
false,
|
|
49
49
|
);
|
package/README.old.md
DELETED
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
<img src="dashboard/public/icon-192.png" width="96" alt="VibeUsage Icon" />
|
|
4
|
-
|
|
5
|
-
# 🟢 VIBEUSAGE
|
|
6
|
-
|
|
7
|
-
**QUANTIFY YOUR AI OUTPUT**
|
|
8
|
-
_Real-time AI Analytics for Codex CLI_
|
|
9
|
-
|
|
10
|
-
[**www.vibeusage.cc**](https://www.vibeusage.cc)
|
|
11
|
-
|
|
12
|
-
[](https://opensource.org/licenses/MIT)
|
|
13
|
-
[](https://nodejs.org/)
|
|
14
|
-
[](https://www.apple.com/macos/)
|
|
15
|
-
|
|
16
|
-
[**English**](README.md) • [**中文说明**](README.zh-CN.md)
|
|
17
|
-
|
|
18
|
-
[**Documentation**](docs/) • [**Dashboard**](dashboard/) • [**Backend API**](BACKEND_API.md)
|
|
19
|
-
|
|
20
|
-
<br/>
|
|
21
|
-
|
|
22
|
-
<img src="docs/screenshots/dashboard.png" width="900" alt="VibeUsage Dashboard Preview"/>
|
|
23
|
-
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 🌌 Overview
|
|
29
|
-
|
|
30
|
-
**VibeUsage** is an intelligent token usage tracking system designed specifically for macOS developers. Through the all-new **Matrix-A Design System**, it provides a high-fidelity cyberpunk-style dashboard that transforms your **AI Output** into quantifiable metrics, supported by the **Neural Divergence Map** for real-time monitoring of multi-model compute distribution.
|
|
31
|
-
|
|
32
|
-
> [!TIP] > **Core Index**: Our signature metric that reflects your flow state by analyzing token consumption rates and patterns.
|
|
33
|
-
|
|
34
|
-
## 🔒 Privacy-First Architecture (Stealth Protocol)
|
|
35
|
-
|
|
36
|
-
We believe your code and thoughts are your own. VibeUsage is built with strict privacy pillars to ensure your data never leaves your control.
|
|
37
|
-
|
|
38
|
-
- 🛡️ **No Content Upload**: We never upload prompts or responses. We only compute token counts locally and send counts plus minimal metadata (timestamps, model, device).
|
|
39
|
-
- 📡 **Local Aggregation**: All token consumption analysis happens on your machine. We only relay quantized 30-minute usage buckets to the cloud.
|
|
40
|
-
- 🔐 **Hashed Identity**: Device tokens are hashed using SHA-256 server-side. Your raw credentials never exist in our database.
|
|
41
|
-
- 🔦 **Full Transparency**: Audit the sync logic yourself in `src/lib/rollout.js`. We literally only capture numbers and timestamps.
|
|
42
|
-
|
|
43
|
-
## 🚀 Key Features
|
|
44
|
-
|
|
45
|
-
- 📡 **Auto-Sync**: Real-time interception of AI CLI pipes with **automatic background synchronization**. Once initialized, your tokens are tracked and synced without any manual commands.
|
|
46
|
-
- 🧭 **Universal-Sync**: Native support for multiple AI CLI tools:
|
|
47
|
-
- **Codex CLI** - OpenAI's official CLI
|
|
48
|
-
- **Every Code** - Community Codex alternative
|
|
49
|
-
- **Gemini CLI** - Google's AI CLI
|
|
50
|
-
- **Opencode** - AI coding assistant
|
|
51
|
-
- **Claude Code** - Anthropic's official CLI
|
|
52
|
-
- Whether it's GPT-4, Claude 3.5 Sonnet, or o1/Gemini, token consumption from all models is unified and counted.
|
|
53
|
-
- 📊 **Matrix Dashboard**: High-performance dashboard built with React + Vite, featuring the new **Matrix-A** design language.
|
|
54
|
-
- **Neural Divergence Map**: Visualize multi-engine load balancing and compute distribution.
|
|
55
|
-
- **Cost Intelligence**: Real-time, multi-dimensional cost breakdown and forecasting.
|
|
56
|
-
- **Activity Heatmap**: GitHub-style contribution graph with streak tracking.
|
|
57
|
-
- **Smart Notifications**: Non-intrusive system-level alerts using a Golden (Gold/Amber) visual style for high-value information.
|
|
58
|
-
- ⚡ **AI Analytics**: Deep analysis of Input/Output tokens, with dedicated tracking for Cached and Reasoning components.
|
|
59
|
-
- 📈 **Leaderboard**: Daily, weekly, monthly, and all-time rankings with privacy-safe display names.
|
|
60
|
-
- 🌐 **Public View**: Share your AI usage journey with a privacy-safe public profile.
|
|
61
|
-
- 📁 **Project Stats**: Track token usage by project/repository across all time.
|
|
62
|
-
- 🔒 **Identity Core**: Robust authentication and permission management to secure your development data.
|
|
63
|
-
|
|
64
|
-
### 🌌 Visual Preview
|
|
65
|
-
|
|
66
|
-
<img src="docs/screenshots/landing.png" width="900" alt="VibeUsage Landing Preview"/>
|
|
67
|
-
|
|
68
|
-
## 🛠️ Quick Start
|
|
69
|
-
|
|
70
|
-
### Installation
|
|
71
|
-
|
|
72
|
-
Initialize your environment once and forget it. VibeUsage handles all synchronization in the background automatically.
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
npx --yes vibeusage init
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**Authentication Methods:**
|
|
79
|
-
|
|
80
|
-
1. **Browser Auth** (default) - Opens browser for secure authentication
|
|
81
|
-
2. **Link Code** - Use `--link-code` to authenticate via dashboard-generated code
|
|
82
|
-
3. **Password** - Direct password authentication (fallback)
|
|
83
|
-
4. **Access Token** - For CI/automated environments
|
|
84
|
-
|
|
85
|
-
**CLI Options:**
|
|
86
|
-
- `--yes` - Skip consent prompts in non-interactive environments
|
|
87
|
-
- `--dry-run` - Preview changes without writing files
|
|
88
|
-
- `--link-code <code>` - Authenticate using a link code from dashboard
|
|
89
|
-
- `--base-url <url>` - Override the default API endpoint
|
|
90
|
-
|
|
91
|
-
**Supported CLI Tools Auto-Configuration:**
|
|
92
|
-
|
|
93
|
-
| Tool | Config Location | Method |
|
|
94
|
-
|------|----------------|--------|
|
|
95
|
-
| Codex CLI | `~/.codex/config.toml` | `notify` hook |
|
|
96
|
-
| Every Code | `~/.code/config.toml` (or `CODE_HOME`) | `notify` hook |
|
|
97
|
-
| Gemini CLI | `~/.gemini/settings.json` (or `GEMINI_HOME`) | `SessionEnd` hook |
|
|
98
|
-
| Opencode | Global plugins | Message parser plugin |
|
|
99
|
-
| Claude Code | `~/.claude/hooks/` | Hook configuration |
|
|
100
|
-
|
|
101
|
-
Once `init` completes, all supported CLI tools are automatically configured for data sync. No further intervention required.
|
|
102
|
-
|
|
103
|
-
### Sync & Status
|
|
104
|
-
|
|
105
|
-
While sync happens automatically, you can manually trigger a synchronization or check status anytime:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
# Manually sync latest local session data (Optional)
|
|
109
|
-
npx --yes vibeusage sync
|
|
110
|
-
|
|
111
|
-
# Check current link status
|
|
112
|
-
npx --yes vibeusage status
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Doctor
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
# Run health checks
|
|
119
|
-
npx --yes vibeusage doctor
|
|
120
|
-
|
|
121
|
-
# Emit JSON report (and write to file)
|
|
122
|
-
npx --yes vibeusage doctor --json --out doctor.json
|
|
123
|
-
|
|
124
|
-
# Override base URL (diagnostics only)
|
|
125
|
-
npx --yes vibeusage doctor --base-url https://example.invalid
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Uninstall
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
# Standard uninstall (keeps data)
|
|
132
|
-
npx --yes vibeusage uninstall
|
|
133
|
-
|
|
134
|
-
# Full purge - removes all data including config and cached sessions
|
|
135
|
-
npx --yes vibeusage uninstall --purge
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Log Sources
|
|
139
|
-
|
|
140
|
-
| Tool | Log Location | Override Env |
|
|
141
|
-
|------|-------------|--------------|
|
|
142
|
-
| Codex CLI | `~/.codex/sessions/**/rollout-*.jsonl` | `CODEX_HOME` |
|
|
143
|
-
| Every Code | `~/.code/sessions/**/rollout-*.jsonl` | `CODE_HOME` |
|
|
144
|
-
| Gemini CLI | `~/.gemini/tmp/**/chats/session-*.json` | `GEMINI_HOME` |
|
|
145
|
-
| Opencode | `~/.opencode/messages/*.json` | - |
|
|
146
|
-
| Claude Code | Parsed from hook output | - |
|
|
147
|
-
|
|
148
|
-
## 🔧 Environment Variables
|
|
149
|
-
|
|
150
|
-
### Core Settings
|
|
151
|
-
|
|
152
|
-
| Variable | Description | Default |
|
|
153
|
-
|----------|-------------|---------|
|
|
154
|
-
| `VIBEUSAGE_HTTP_TIMEOUT_MS` | CLI HTTP timeout in ms (`0` disables, clamped `1000..120000`) | `20000` |
|
|
155
|
-
| `VITE_VIBEUSAGE_HTTP_TIMEOUT_MS` | Dashboard request timeout in ms (`0` disables, clamped `1000..30000`) | `15000` |
|
|
156
|
-
| `VIBEUSAGE_DEBUG` | Enable debug output (`1` or `true` to enable) | - |
|
|
157
|
-
| `VIBEUSAGE_DASHBOARD_URL` | Custom dashboard URL | `https://www.vibeusage.cc` |
|
|
158
|
-
| `VIBEUSAGE_INSFORGE_BASE_URL` | Custom API base URL | `https://5tmappuk.us-east.insforge.app` |
|
|
159
|
-
| `VIBEUSAGE_DEVICE_TOKEN` | Pre-configured device token (for CI) | - |
|
|
160
|
-
|
|
161
|
-
### CLI Tool Overrides
|
|
162
|
-
|
|
163
|
-
| Variable | Description | Default |
|
|
164
|
-
|----------|-------------|---------|
|
|
165
|
-
| `CODEX_HOME` | Codex CLI directory override | `~/.codex` |
|
|
166
|
-
| `CODE_HOME` | Every Code directory override | `~/.code` |
|
|
167
|
-
| `GEMINI_HOME` | Gemini CLI directory override | `~/.gemini` |
|
|
168
|
-
|
|
169
|
-
### Deprecated
|
|
170
|
-
|
|
171
|
-
- `VIBEUSAGE_ROLLUP_ENABLED`: Currently ignored; rollup aggregation is disabled pending table deployment.
|
|
172
|
-
|
|
173
|
-
## 🧰 Troubleshooting
|
|
174
|
-
|
|
175
|
-
### Debug Mode
|
|
176
|
-
|
|
177
|
-
Enable debug output to see detailed request/response information:
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
VIBEUSAGE_DEBUG=1 npx --yes vibeusage sync
|
|
181
|
-
# or
|
|
182
|
-
npx --yes vibeusage sync --debug
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Health Check
|
|
186
|
-
|
|
187
|
-
Run the built-in doctor command to diagnose issues:
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
# Basic health check
|
|
191
|
-
npx --yes vibeusage doctor
|
|
192
|
-
|
|
193
|
-
# JSON output for debugging
|
|
194
|
-
npx --yes vibeusage doctor --json --out doctor.json
|
|
195
|
-
|
|
196
|
-
# Test against a different endpoint
|
|
197
|
-
npx --yes vibeusage doctor --base-url https://your-instance.insforge.app
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### Streak shows 0 days while totals look correct
|
|
201
|
-
|
|
202
|
-
- Streak is defined as consecutive days ending today. If today's total is 0, streak will be 0.
|
|
203
|
-
- If you expect a non-zero streak, clear cached auth/heatmap data and sign in again:
|
|
204
|
-
|
|
205
|
-
```js
|
|
206
|
-
localStorage.removeItem("vibeusage.dashboard.auth.v1");
|
|
207
|
-
Object.keys(localStorage)
|
|
208
|
-
.filter((k) => k.startsWith("vibeusage.heatmap."))
|
|
209
|
-
.forEach((k) => localStorage.removeItem(k));
|
|
210
|
-
location.reload();
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
- Complete the landing page sign-in flow again after reload.
|
|
214
|
-
- Note: `insforge-auth-token` is not used by the dashboard; use `vibeusage.dashboard.auth.v1`.
|
|
215
|
-
|
|
216
|
-
### Sync Issues
|
|
217
|
-
|
|
218
|
-
If data isn't appearing in the dashboard:
|
|
219
|
-
|
|
220
|
-
1. Check status: `npx --yes vibeusage status`
|
|
221
|
-
2. Force manual sync: `npx --yes vibeusage sync`
|
|
222
|
-
3. Verify CLI tool hooks are configured (re-run `init` if needed)
|
|
223
|
-
4. Check debug output: `VIBEUSAGE_DEBUG=1 npx vibeusage sync`
|
|
224
|
-
|
|
225
|
-
### Timeout Errors
|
|
226
|
-
|
|
227
|
-
Increase HTTP timeout for slow connections:
|
|
228
|
-
|
|
229
|
-
```bash
|
|
230
|
-
VIBEUSAGE_HTTP_TIMEOUT_MS=60000 npx --yes vibeusage sync
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## 🏗️ Architecture
|
|
234
|
-
|
|
235
|
-
```mermaid
|
|
236
|
-
graph TD
|
|
237
|
-
A[Codex CLI] -->|Rollout Logs| F(Tracker CLI)
|
|
238
|
-
B[Every Code] -->|Rollout Logs| F
|
|
239
|
-
C[Gemini CLI] -->|Session Logs| F
|
|
240
|
-
D[Opencode] -->|Message Logs| F
|
|
241
|
-
E[Claude Code] -->|Hook Output| F
|
|
242
|
-
F -->|AI Tokens| G{Core Relay}
|
|
243
|
-
G --> H[VibeUsage Dashboard]
|
|
244
|
-
G --> I[AI Analytics Engine]
|
|
245
|
-
G --> J[Leaderboard Service]
|
|
246
|
-
G --> K[Public View API]
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Components
|
|
250
|
-
|
|
251
|
-
- **Tracker CLI** (`src/`): Node.js CLI that parses logs from multiple AI tools and syncs token data
|
|
252
|
-
- **Core Relay** (InsForge Edge Functions): Serverless backend handling ingestion, aggregation, and API
|
|
253
|
-
- **Dashboard** (`dashboard/`): React + Vite frontend for visualization
|
|
254
|
-
- **AI Analytics Engine**: Cost calculation, model breakdown, and usage forecasting
|
|
255
|
-
|
|
256
|
-
## 💻 Developer Guide
|
|
257
|
-
|
|
258
|
-
To run locally or contribute:
|
|
259
|
-
|
|
260
|
-
### Dashboard Development
|
|
261
|
-
|
|
262
|
-
```bash
|
|
263
|
-
# Install dependencies
|
|
264
|
-
cd dashboard
|
|
265
|
-
npm install
|
|
266
|
-
|
|
267
|
-
# Start dev server
|
|
268
|
-
npm run dev
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Debug Payload (Usage Endpoints)
|
|
272
|
-
|
|
273
|
-
When `debug=1` is included in a usage endpoint request, the response adds a `debug` object that helps the dashboard attribute slow queries without relying on response headers.
|
|
274
|
-
|
|
275
|
-
```ts
|
|
276
|
-
const res = await fetch(
|
|
277
|
-
`${baseUrl}/functions/vibeusage-usage-summary?from=2025-12-30&to=2025-12-30&debug=1`,
|
|
278
|
-
{
|
|
279
|
-
headers: { Authorization: `Bearer ${userJwt}` }
|
|
280
|
-
}
|
|
281
|
-
);
|
|
282
|
-
const data = await res.json();
|
|
283
|
-
|
|
284
|
-
if (data.debug) {
|
|
285
|
-
console.debug('usage debug', {
|
|
286
|
-
requestId: data.debug.request_id,
|
|
287
|
-
status: data.debug.status,
|
|
288
|
-
queryMs: data.debug.query_ms,
|
|
289
|
-
slowThresholdMs: data.debug.slow_threshold_ms,
|
|
290
|
-
slowQuery: data.debug.slow_query
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Architecture Validation
|
|
296
|
-
|
|
297
|
-
```bash
|
|
298
|
-
# Validate Copy Registry
|
|
299
|
-
npm run validate:copy
|
|
300
|
-
|
|
301
|
-
# Run smoke tests
|
|
302
|
-
npm run smoke
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Architecture Canvas Focus
|
|
306
|
-
|
|
307
|
-
```bash
|
|
308
|
-
# Generate a focused canvas for a top-level module
|
|
309
|
-
node scripts/ops/architecture-canvas.cjs --focus src
|
|
310
|
-
|
|
311
|
-
# Alias: --module
|
|
312
|
-
node scripts/ops/architecture-canvas.cjs --module dashboard
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
## 📜 License
|
|
316
|
-
|
|
317
|
-
This project is licensed under the [MIT License](LICENSE).
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
|
-
<div align="center">
|
|
322
|
-
<b>System_Ready // 2024 VibeUsage OS</b><br/>
|
|
323
|
-
<i>"More Tokens. More Vibe."</i>
|
|
324
|
-
</div>
|