ccclub 0.2.78 → 0.2.80

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 (2) hide show
  1. package/dist/index.js +55 -18
  2. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -206,9 +206,9 @@ function isHookInstalled() {
206
206
 
207
207
  // src/commands/sync.ts
208
208
  import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
209
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
210
- import { join as join4 } from "path";
211
- import { homedir as homedir4 } from "os";
209
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
210
+ import { join as join5 } from "path";
211
+ import { homedir as homedir5 } from "os";
212
212
  import chalk2 from "chalk";
213
213
  import ora from "ora";
214
214
 
@@ -394,11 +394,30 @@ function formatFetchError(err) {
394
394
  // src/usage-limits.ts
395
395
  import { execSync as execSync2, exec } from "child_process";
396
396
  import { promisify } from "util";
397
- import { userInfo as userInfo2 } from "os";
397
+ import { userInfo as userInfo2, homedir as homedir4 } from "os";
398
+ import { join as join4 } from "path";
399
+ import { readFileSync as readFileSync2, writeFileSync } from "fs";
398
400
  var execAsync = promisify(exec);
399
401
  var debug = (...args) => {
400
402
  if (process.env.CCCLUB_DEBUG) console.error("[usage-debug]", ...args);
401
403
  };
404
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
405
+ var CACHE_PATH = join4(homedir4(), CCCLUB_CONFIG_DIR, "usage-cache.json");
406
+ function readCache(allowStale = false) {
407
+ try {
408
+ const raw = readFileSync2(CACHE_PATH, "utf-8");
409
+ const { snapshot, fetchedAt } = JSON.parse(raw);
410
+ if (allowStale || Date.now() - fetchedAt < CACHE_TTL_MS) return snapshot;
411
+ } catch {
412
+ }
413
+ return null;
414
+ }
415
+ function writeCache(snapshot) {
416
+ try {
417
+ writeFileSync(CACHE_PATH, JSON.stringify({ snapshot, fetchedAt: Date.now() }));
418
+ } catch {
419
+ }
420
+ }
402
421
  function parseUtilization(value) {
403
422
  if (typeof value === "number") return Math.round(value * 100) / 100;
404
423
  if (typeof value === "string") {
@@ -408,6 +427,11 @@ function parseUtilization(value) {
408
427
  return 0;
409
428
  }
410
429
  async function fetchUsageLimits() {
430
+ const cached = readCache();
431
+ if (cached) {
432
+ debug("returning cached snapshot:", cached.fiveHour, cached.sevenDay);
433
+ return cached;
434
+ }
411
435
  try {
412
436
  const username = process.env.USER || process.env.USERNAME || userInfo2().username;
413
437
  debug("username:", username);
@@ -428,7 +452,7 @@ async function fetchUsageLimits() {
428
452
  debug("returning null: token expired at", expiresAt);
429
453
  return null;
430
454
  }
431
- const curlCmd = `curl -sf --max-time 8 --noproxy '*' "https://api.anthropic.com/api/oauth/usage" -H "Authorization: Bearer ${accessToken}" -H "anthropic-beta: oauth-2025-04-20" -H "User-Agent: claude-code/2.1.5"`;
455
+ const curlCmd = `curl -sf --max-time 8 "https://api.anthropic.com/api/oauth/usage" -H "Authorization: Bearer ${accessToken}" -H "anthropic-beta: oauth-2025-04-20" -H "User-Agent: claude-code/2.1.5"`;
432
456
  debug("running curl...");
433
457
  const { stdout: stdout5 } = await execAsync(curlCmd, { timeout: 9e3 });
434
458
  debug("curl stdout length:", stdout5.length, "first 100:", stdout5.slice(0, 100));
@@ -449,23 +473,36 @@ async function fetchUsageLimits() {
449
473
  snapshotAt: (/* @__PURE__ */ new Date()).toISOString()
450
474
  };
451
475
  debug("returning snapshot:", result.fiveHour, result.sevenDay);
476
+ writeCache(result);
452
477
  return result;
453
478
  } catch (err) {
454
479
  debug("caught error:", err instanceof Error ? err.message : String(err));
455
- return null;
480
+ try {
481
+ const tmp = JSON.parse(readFileSync2("/tmp/sl-claude-usage", "utf-8"));
482
+ if (typeof tmp.fiveHour === "number" && typeof tmp.sevenDay === "number") {
483
+ const result = { fiveHour: tmp.fiveHour, sevenDay: tmp.sevenDay, snapshotAt: (/* @__PURE__ */ new Date()).toISOString() };
484
+ debug("returning cc-costline cache fallback:", result.fiveHour, result.sevenDay);
485
+ writeCache(result);
486
+ return result;
487
+ }
488
+ } catch {
489
+ }
490
+ const stale = readCache(true);
491
+ if (stale) debug("returning stale cache as fallback:", stale.fiveHour, stale.sevenDay);
492
+ return stale;
456
493
  }
457
494
  }
458
495
 
459
496
  // src/commands/sync.ts
460
497
  var SYNC_FORMAT_VERSION = "6";
461
498
  function getSyncVersionPath() {
462
- return join4(homedir4(), CCCLUB_CONFIG_DIR, "sync-version");
499
+ return join5(homedir5(), CCCLUB_CONFIG_DIR, "sync-version");
463
500
  }
464
501
  function needsFullSync() {
465
502
  const path = getSyncVersionPath();
466
503
  if (!existsSync3(path)) return true;
467
504
  try {
468
- const stored = readFileSync2(path, "utf-8").trim();
505
+ const stored = readFileSync3(path, "utf-8").trim();
469
506
  return stored !== SYNC_FORMAT_VERSION;
470
507
  } catch {
471
508
  return true;
@@ -477,13 +514,13 @@ async function syncCommand(options) {
477
514
  if (options.silent && !options.full) {
478
515
  if (existsSync3(timePath)) {
479
516
  try {
480
- const ts = parseInt(readFileSync2(timePath, "utf-8").trim(), 10);
517
+ const ts = parseInt(readFileSync3(timePath, "utf-8").trim(), 10);
481
518
  if (Date.now() - ts < THROTTLE_MS) return;
482
519
  } catch {
483
520
  }
484
521
  }
485
522
  try {
486
- writeFileSync(timePath, String(Date.now()));
523
+ writeFileSync2(timePath, String(Date.now()));
487
524
  } catch {
488
525
  }
489
526
  }
@@ -492,7 +529,7 @@ async function syncCommand(options) {
492
529
  } catch {
493
530
  if (options.silent) {
494
531
  try {
495
- writeFileSync(timePath, "0");
532
+ writeFileSync2(timePath, "0");
496
533
  } catch {
497
534
  }
498
535
  }
@@ -780,17 +817,17 @@ import Table from "cli-table3";
780
817
  import ora4 from "ora";
781
818
 
782
819
  // src/update-check.ts
783
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
784
- import { join as join5 } from "path";
785
- import { homedir as homedir5 } from "os";
820
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4 } from "fs";
821
+ import { join as join6 } from "path";
822
+ import { homedir as homedir6 } from "os";
786
823
  var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
787
- var CHECK_FILE = join5(homedir5(), CCCLUB_CONFIG_DIR, "last-update-check");
824
+ var CHECK_FILE = join6(homedir6(), CCCLUB_CONFIG_DIR, "last-update-check");
788
825
  var pendingCheck = null;
789
826
  function startUpdateCheck(currentVersion) {
790
827
  if (process.argv.includes("--silent") || process.argv.includes("-s")) return;
791
828
  try {
792
829
  if (existsSync4(CHECK_FILE)) {
793
- const ts = parseInt(readFileSync3(CHECK_FILE, "utf-8").trim(), 10);
830
+ const ts = parseInt(readFileSync4(CHECK_FILE, "utf-8").trim(), 10);
794
831
  if (Date.now() - ts < CHECK_INTERVAL_MS) return;
795
832
  }
796
833
  } catch {
@@ -806,7 +843,7 @@ function startUpdateCheck(currentVersion) {
806
843
  return { latest: data.version, current: currentVersion };
807
844
  }
808
845
  try {
809
- writeFileSync2(CHECK_FILE, String(Date.now()));
846
+ writeFileSync3(CHECK_FILE, String(Date.now()));
810
847
  } catch {
811
848
  }
812
849
  return null;
@@ -1360,7 +1397,7 @@ async function hookCommand() {
1360
1397
  }
1361
1398
 
1362
1399
  // src/index.ts
1363
- var VERSION = "0.2.78";
1400
+ var VERSION = "0.2.80";
1364
1401
  startUpdateCheck(VERSION);
1365
1402
  var program = new Command();
1366
1403
  program.name("ccclub").description("Claude Code leaderboard among friends").version(VERSION, "-v, -V, --version");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccclub",
3
- "version": "0.2.78",
3
+ "version": "0.2.80",
4
4
  "type": "module",
5
5
  "description": "Claude Code leaderboard among friends",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "build": "tsup src/index.ts --format esm --dts --clean",
15
+ "prepublishOnly": "npm run build",
15
16
  "postinstall": "node scripts/postinstall.cjs",
16
17
  "dev": "tsx src/index.ts",
17
18
  "test": "vitest run"