token-rats 0.0.2 → 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.
Files changed (3) hide show
  1. package/README.md +0 -4
  2. package/dist/index.js +86 -8
  3. package/package.json +18 -5
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) {
@@ -4971,6 +5003,7 @@ function toNonNegInt3(v) {
4971
5003
  }
4972
5004
 
4973
5005
  // src/lib/cursor-extract.ts
5006
+ import { readFile } from "node:fs/promises";
4974
5007
  async function tryNodeSqlite(dbPath) {
4975
5008
  let DatabaseConstructor;
4976
5009
  try {
@@ -4982,6 +5015,42 @@ async function tryNodeSqlite(dbPath) {
4982
5015
  }
4983
5016
  return readWithDb(() => new DatabaseConstructor(dbPath, { readOnly: true }));
4984
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
+ }
4985
5054
  async function tryBetterSqlite3(dbPath) {
4986
5055
  let Database;
4987
5056
  try {
@@ -5072,13 +5141,17 @@ async function readCursorDb(dbPath) {
5072
5141
  if (fromNodeSqlite !== null) {
5073
5142
  return { rows: fromNodeSqlite, skipped: null };
5074
5143
  }
5144
+ const fromSqlJs = await trySqlJs(dbPath);
5145
+ if (fromSqlJs !== null) {
5146
+ return { rows: fromSqlJs, skipped: null };
5147
+ }
5075
5148
  const fromBetter = await tryBetterSqlite3(dbPath);
5076
5149
  if (fromBetter !== null) {
5077
5150
  return { rows: fromBetter, skipped: null };
5078
5151
  }
5079
5152
  return {
5080
5153
  rows: [],
5081
- skipped: "Could not open Cursor DB (no sqlite driver available). Skipping Cursor source."
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."
5082
5155
  };
5083
5156
  }
5084
5157
 
@@ -5550,7 +5623,7 @@ async function whoamiCommand(opts) {
5550
5623
 
5551
5624
  // src/index.ts
5552
5625
  function getVersion() {
5553
- return "0.0.1";
5626
+ return "0.0.3";
5554
5627
  }
5555
5628
  function printHelp() {
5556
5629
  console.log(`
@@ -5560,12 +5633,14 @@ function printHelp() {
5560
5633
  token-rats <command> [flags]
5561
5634
 
5562
5635
  \x1B[1mCommands:\x1B[0m
5563
- login Authenticate with Token Rats (opens browser)
5564
- sync Read local Claude Code + Cursor logs and upload counts
5565
- watch Watch logs in real-time; upload new sessions as they appear
5566
- whoami Show the currently signed-in account
5567
- logout Clear your stored credentials
5568
- help Show this help message
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
5569
5644
 
5570
5645
  \x1B[1mFlags (all commands):\x1B[0m
5571
5646
  --api-url <url> Override API URL (default: https://api.tokenrats.com)
@@ -5649,6 +5724,9 @@ async function main() {
5649
5724
  case "logout":
5650
5725
  logoutCommand();
5651
5726
  break;
5727
+ case "install-cursor":
5728
+ await installCursorCommand();
5729
+ break;
5652
5730
  default:
5653
5731
  console.error(`\x1B[31mUnknown command: ${command}\x1B[0m`);
5654
5732
  console.error(`Run \x1B[1mtoken-rats help\x1B[0m for a list of commands.`);
package/package.json CHANGED
@@ -1,20 +1,30 @@
1
1
  {
2
2
  "name": "token-rats",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Sync your Claude Code + Cursor token usage to your Token Rats leaderboard.",
5
- "license": "MIT",
5
+ "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "token-rats": "./dist/index.js"
9
9
  },
10
- "files": ["dist", "README.md"],
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
11
14
  "repository": {
12
15
  "type": "git",
13
16
  "url": "git+https://github.com/hsalberti/token-rats.git",
14
17
  "directory": "packages/cli"
15
18
  },
16
19
  "homepage": "https://tokenrats.com",
17
- "keywords": ["claude", "claude-code", "cursor", "tokens", "leaderboard", "ai-usage"],
20
+ "keywords": [
21
+ "claude",
22
+ "claude-code",
23
+ "cursor",
24
+ "tokens",
25
+ "leaderboard",
26
+ "ai-usage"
27
+ ],
18
28
  "publishConfig": {
19
29
  "access": "public"
20
30
  },
@@ -26,7 +36,6 @@
26
36
  "prepublishOnly": "node build.mjs"
27
37
  },
28
38
  "optionalDependencies": {
29
- "better-sqlite3": "^9.4.3",
30
39
  "chokidar": "^3.6.0",
31
40
  "clipboardy": "^4.0.0",
32
41
  "open": "^10.1.0"
@@ -37,9 +46,13 @@
37
46
  "@token-rats/pricing": "workspace:*",
38
47
  "@types/better-sqlite3": "^7.6.12",
39
48
  "@types/node": "22.10.2",
49
+ "@types/sql.js": "^1.4.11",
40
50
  "esbuild": "^0.24.2",
41
51
  "tsx": "4.19.2",
42
52
  "typescript": "5.7.2",
43
53
  "vitest": "2.1.8"
54
+ },
55
+ "dependencies": {
56
+ "sql.js": "^1.14.1"
44
57
  }
45
58
  }