token-rats 0.0.1 → 0.0.3
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 +0 -4
- package/dist/index.js +86 -23
- package/package.json +32 -10
package/README.md
CHANGED
|
@@ -86,7 +86,3 @@ Authentication uses a device-code flow:
|
|
|
86
86
|
Token Rats is open source. The CLI source is in [`packages/cli/`](.) and the parsers are in [`packages/parsers/`](../parsers/). You can inspect exactly what is read from your disk and what is sent to the server.
|
|
87
87
|
|
|
88
88
|
**Privacy posture:** Token Rats reads usage counts only — never prompts or completions. The parser source is in `packages/parsers/`. We literally can't read what you typed.
|
|
89
|
-
|
|
90
|
-
## License
|
|
91
|
-
|
|
92
|
-
MIT
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/commands/install-cursor.ts
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
async function installCursorCommand(opts = {}) {
|
|
6
|
+
const pm = opts.packageManager ?? "npm";
|
|
7
|
+
console.log("\x1B[1mtoken-rats install-cursor\x1B[0m");
|
|
8
|
+
console.log(
|
|
9
|
+
"Installs better-sqlite3 globally for faster Cursor extraction.\nYou don't need this for Cursor support to work \u2014 sql.js (already\nbundled) handles it. This is purely a speed upgrade for large DBs.\n"
|
|
10
|
+
);
|
|
11
|
+
const args = ["install", "-g", "better-sqlite3@^9.4.3"];
|
|
12
|
+
console.log(`\x1B[2m$ ${pm} ${args.join(" ")}\x1B[0m
|
|
13
|
+
`);
|
|
14
|
+
const exitCode = await new Promise((resolve) => {
|
|
15
|
+
const child = spawn(pm, args, { stdio: "inherit" });
|
|
16
|
+
child.on("close", (code) => resolve(code ?? 1));
|
|
17
|
+
child.on("error", (err) => {
|
|
18
|
+
console.error(`\x1B[31mFailed to launch ${pm}: ${err.message}\x1B[0m`);
|
|
19
|
+
resolve(1);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
if (exitCode === 0) {
|
|
23
|
+
console.log(
|
|
24
|
+
"\n\x1B[32m\u2713\x1B[0m Done. Future `token-rats sync` runs will prefer better-sqlite3."
|
|
25
|
+
);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.error(
|
|
29
|
+
`
|
|
30
|
+
\x1B[31mInstall failed (exit ${exitCode}). Cursor still works via sql.js \u2014 no action required.\x1B[0m`
|
|
31
|
+
);
|
|
32
|
+
process.exit(exitCode);
|
|
33
|
+
}
|
|
34
|
+
|
|
3
35
|
// ../../node_modules/.pnpm/zod@3.23.8/node_modules/zod/lib/index.mjs
|
|
4
36
|
var util;
|
|
5
37
|
(function(util2) {
|
|
@@ -4223,8 +4255,6 @@ var ENDPOINTS = {
|
|
|
4223
4255
|
authCliPoll: "/v1/auth/cli/poll",
|
|
4224
4256
|
// Phase 2 Track G+H
|
|
4225
4257
|
meRooms: "/v1/me/rooms",
|
|
4226
|
-
// Referral tracking
|
|
4227
|
-
meReferrals: "/v1/me/referrals",
|
|
4228
4258
|
leaveRoom: (code) => `/v1/rooms/${code}/leave`,
|
|
4229
4259
|
renameRoom: (code) => `/v1/rooms/${code}`,
|
|
4230
4260
|
roomActivity: (code) => `/v1/rooms/${code}/activity`,
|
|
@@ -4307,19 +4337,6 @@ var LiveEvent = z.discriminatedUnion("kind", [
|
|
|
4307
4337
|
})
|
|
4308
4338
|
]);
|
|
4309
4339
|
|
|
4310
|
-
// ../contracts/src/referrals.ts
|
|
4311
|
-
var Referral = z.object({
|
|
4312
|
-
handle: z.string(),
|
|
4313
|
-
avatarUrl: z.string().url().nullable(),
|
|
4314
|
-
/** Unix ms when the referee created their account. */
|
|
4315
|
-
joinedAt: z.number().int().positive()
|
|
4316
|
-
});
|
|
4317
|
-
var GetReferralsResponse = z.object({
|
|
4318
|
-
count: z.number().int().nonnegative(),
|
|
4319
|
-
/** Most-recent first, up to 20. */
|
|
4320
|
-
recent: z.array(Referral)
|
|
4321
|
-
});
|
|
4322
|
-
|
|
4323
4340
|
// src/lib/api.ts
|
|
4324
4341
|
var DEFAULT_API_URL = "https://api.tokenrats.com";
|
|
4325
4342
|
function isTransient(status) {
|
|
@@ -4986,6 +5003,7 @@ function toNonNegInt3(v) {
|
|
|
4986
5003
|
}
|
|
4987
5004
|
|
|
4988
5005
|
// src/lib/cursor-extract.ts
|
|
5006
|
+
import { readFile } from "node:fs/promises";
|
|
4989
5007
|
async function tryNodeSqlite(dbPath) {
|
|
4990
5008
|
let DatabaseConstructor;
|
|
4991
5009
|
try {
|
|
@@ -4997,6 +5015,42 @@ async function tryNodeSqlite(dbPath) {
|
|
|
4997
5015
|
}
|
|
4998
5016
|
return readWithDb(() => new DatabaseConstructor(dbPath, { readOnly: true }));
|
|
4999
5017
|
}
|
|
5018
|
+
async function trySqlJs(dbPath) {
|
|
5019
|
+
let initSqlJs;
|
|
5020
|
+
try {
|
|
5021
|
+
const mod = await import("sql.js");
|
|
5022
|
+
initSqlJs = mod.default ?? mod;
|
|
5023
|
+
} catch {
|
|
5024
|
+
return null;
|
|
5025
|
+
}
|
|
5026
|
+
let SQL;
|
|
5027
|
+
let fileBytes;
|
|
5028
|
+
try {
|
|
5029
|
+
SQL = await initSqlJs();
|
|
5030
|
+
fileBytes = await readFile(dbPath);
|
|
5031
|
+
} catch {
|
|
5032
|
+
return null;
|
|
5033
|
+
}
|
|
5034
|
+
const sqlDb = new SQL.Database(new Uint8Array(fileBytes));
|
|
5035
|
+
const adapter = {
|
|
5036
|
+
prepare: (sql) => ({
|
|
5037
|
+
all: () => {
|
|
5038
|
+
const results = sqlDb.exec(sql);
|
|
5039
|
+
if (results.length === 0) return [];
|
|
5040
|
+
const { columns, values } = results[0];
|
|
5041
|
+
return values.map((row) => {
|
|
5042
|
+
const obj = {};
|
|
5043
|
+
for (let i = 0; i < columns.length; i++) {
|
|
5044
|
+
obj[columns[i]] = row[i];
|
|
5045
|
+
}
|
|
5046
|
+
return obj;
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
}),
|
|
5050
|
+
close: () => sqlDb.close()
|
|
5051
|
+
};
|
|
5052
|
+
return readWithDb(() => adapter);
|
|
5053
|
+
}
|
|
5000
5054
|
async function tryBetterSqlite3(dbPath) {
|
|
5001
5055
|
let Database;
|
|
5002
5056
|
try {
|
|
@@ -5087,13 +5141,17 @@ async function readCursorDb(dbPath) {
|
|
|
5087
5141
|
if (fromNodeSqlite !== null) {
|
|
5088
5142
|
return { rows: fromNodeSqlite, skipped: null };
|
|
5089
5143
|
}
|
|
5144
|
+
const fromSqlJs = await trySqlJs(dbPath);
|
|
5145
|
+
if (fromSqlJs !== null) {
|
|
5146
|
+
return { rows: fromSqlJs, skipped: null };
|
|
5147
|
+
}
|
|
5090
5148
|
const fromBetter = await tryBetterSqlite3(dbPath);
|
|
5091
5149
|
if (fromBetter !== null) {
|
|
5092
5150
|
return { rows: fromBetter, skipped: null };
|
|
5093
5151
|
}
|
|
5094
5152
|
return {
|
|
5095
5153
|
rows: [],
|
|
5096
|
-
skipped: "Could not open Cursor DB (
|
|
5154
|
+
skipped: "Could not open Cursor DB (sqlite drivers unavailable). Run `npx token-rats install-cursor` for native speed, or upgrade to Node \u226522.5."
|
|
5097
5155
|
};
|
|
5098
5156
|
}
|
|
5099
5157
|
|
|
@@ -5565,7 +5623,7 @@ async function whoamiCommand(opts) {
|
|
|
5565
5623
|
|
|
5566
5624
|
// src/index.ts
|
|
5567
5625
|
function getVersion() {
|
|
5568
|
-
return "0.0.
|
|
5626
|
+
return "0.0.3";
|
|
5569
5627
|
}
|
|
5570
5628
|
function printHelp() {
|
|
5571
5629
|
console.log(`
|
|
@@ -5575,12 +5633,14 @@ function printHelp() {
|
|
|
5575
5633
|
token-rats <command> [flags]
|
|
5576
5634
|
|
|
5577
5635
|
\x1B[1mCommands:\x1B[0m
|
|
5578
|
-
login
|
|
5579
|
-
sync
|
|
5580
|
-
watch
|
|
5581
|
-
whoami
|
|
5582
|
-
logout
|
|
5583
|
-
|
|
5636
|
+
login Authenticate with Token Rats (opens browser)
|
|
5637
|
+
sync Read local Claude Code + Cursor logs and upload counts
|
|
5638
|
+
watch Watch logs in real-time; upload new sessions as they appear
|
|
5639
|
+
whoami Show the currently signed-in account
|
|
5640
|
+
logout Clear your stored credentials
|
|
5641
|
+
install-cursor Install better-sqlite3 globally for faster Cursor reads
|
|
5642
|
+
(sql.js works out of the box \u2014 this is opt-in speed-up)
|
|
5643
|
+
help Show this help message
|
|
5584
5644
|
|
|
5585
5645
|
\x1B[1mFlags (all commands):\x1B[0m
|
|
5586
5646
|
--api-url <url> Override API URL (default: https://api.tokenrats.com)
|
|
@@ -5664,6 +5724,9 @@ async function main() {
|
|
|
5664
5724
|
case "logout":
|
|
5665
5725
|
logoutCommand();
|
|
5666
5726
|
break;
|
|
5727
|
+
case "install-cursor":
|
|
5728
|
+
await installCursorCommand();
|
|
5729
|
+
break;
|
|
5667
5730
|
default:
|
|
5668
5731
|
console.error(`\x1B[31mUnknown command: ${command}\x1B[0m`);
|
|
5669
5732
|
console.error(`Run \x1B[1mtoken-rats help\x1B[0m for a list of commands.`);
|
package/package.json
CHANGED
|
@@ -1,36 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "token-rats",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Sync your Claude Code + Cursor token usage to your Token Rats leaderboard.",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"token-rats": "./dist/index.js"
|
|
9
9
|
},
|
|
10
|
-
"files": [
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/hsalberti/token-rats.git",
|
|
17
|
+
"directory": "packages/cli"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://tokenrats.com",
|
|
20
|
+
"keywords": [
|
|
21
|
+
"claude",
|
|
22
|
+
"claude-code",
|
|
23
|
+
"cursor",
|
|
24
|
+
"tokens",
|
|
25
|
+
"leaderboard",
|
|
26
|
+
"ai-usage"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
11
31
|
"scripts": {
|
|
12
32
|
"build": "tsc --noEmit -p tsconfig.json && node build.mjs",
|
|
13
33
|
"typecheck": "tsc --noEmit",
|
|
14
34
|
"dev": "tsx src/index.ts",
|
|
15
|
-
"test": "vitest run"
|
|
16
|
-
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@token-rats/contracts": "workspace:*",
|
|
19
|
-
"@token-rats/parsers": "workspace:*",
|
|
20
|
-
"@token-rats/pricing": "workspace:*"
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"prepublishOnly": "node build.mjs"
|
|
21
37
|
},
|
|
22
38
|
"optionalDependencies": {
|
|
23
|
-
"better-sqlite3": "^9.4.3",
|
|
24
39
|
"chokidar": "^3.6.0",
|
|
25
40
|
"clipboardy": "^4.0.0",
|
|
26
41
|
"open": "^10.1.0"
|
|
27
42
|
},
|
|
28
43
|
"devDependencies": {
|
|
44
|
+
"@token-rats/contracts": "workspace:*",
|
|
45
|
+
"@token-rats/parsers": "workspace:*",
|
|
46
|
+
"@token-rats/pricing": "workspace:*",
|
|
29
47
|
"@types/better-sqlite3": "^7.6.12",
|
|
30
48
|
"@types/node": "22.10.2",
|
|
49
|
+
"@types/sql.js": "^1.4.11",
|
|
31
50
|
"esbuild": "^0.24.2",
|
|
32
51
|
"tsx": "4.19.2",
|
|
33
52
|
"typescript": "5.7.2",
|
|
34
53
|
"vitest": "2.1.8"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"sql.js": "^1.14.1"
|
|
35
57
|
}
|
|
36
58
|
}
|