ccclub 0.2.37 → 0.2.39

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 +39 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -380,8 +380,8 @@ function needsFullSync() {
380
380
  }
381
381
  var THROTTLE_MS = 5 * 60 * 1e3;
382
382
  async function syncCommand(options) {
383
+ const timePath = getLastSyncTimePath();
383
384
  if (options.silent && !options.full) {
384
- const timePath = getLastSyncTimePath();
385
385
  if (existsSync3(timePath)) {
386
386
  try {
387
387
  const ts = parseInt(readFileSync2(timePath, "utf-8").trim(), 10);
@@ -394,10 +394,20 @@ async function syncCommand(options) {
394
394
  } catch {
395
395
  }
396
396
  }
397
- await doSync(options.full || false, options.silent);
397
+ try {
398
+ await doSync(options.full || false, options.silent);
399
+ } catch {
400
+ if (options.silent) {
401
+ try {
402
+ writeFileSync(timePath, "0");
403
+ } catch {
404
+ }
405
+ }
406
+ }
398
407
  }
399
408
  async function doSync(firstSync = false, silent = false) {
400
- const config = await requireConfig();
409
+ const config = silent ? await loadConfig() : await requireConfig();
410
+ if (!config) return;
401
411
  if (!firstSync && needsFullSync()) {
402
412
  firstSync = true;
403
413
  }
@@ -440,8 +450,9 @@ async function doSync(firstSync = false, silent = false) {
440
450
  signal: AbortSignal.timeout(3e4)
441
451
  });
442
452
  if (!res.ok) {
443
- const err = await res.json().catch(() => ({ error: res.statusText }));
444
- if (spinner) spinner.fail(`Sync failed: ${err.error}`);
453
+ const errBody = await res.json().catch(() => ({ error: res.statusText }));
454
+ if (spinner) spinner.fail(`Sync failed: ${errBody.error}`);
455
+ if (silent) throw new Error(`sync failed: ${res.status}`);
445
456
  return;
446
457
  }
447
458
  const data = await res.json();
@@ -457,6 +468,7 @@ async function doSync(firstSync = false, silent = false) {
457
468
  }
458
469
  } catch (err) {
459
470
  if (spinner) spinner.fail(`Sync error: ${err instanceof Error ? err.message : err}`);
471
+ if (silent) throw err;
460
472
  }
461
473
  }
462
474
 
@@ -782,8 +794,8 @@ function printGroup(data, code, period, config, showCache = false) {
782
794
  const head = ["#", "Name", "Tokens", "Cost"];
783
795
  const widths = [5, 20, 10, 12];
784
796
  if (hasPlan) {
785
- head.push("ROI");
786
- widths.push(13);
797
+ head.push("Monthly ROI");
798
+ widths.push(15);
787
799
  }
788
800
  head.push("Chats");
789
801
  widths.push(8);
@@ -824,6 +836,12 @@ function printGroup(data, code, period, config, showCache = false) {
824
836
  }
825
837
  console.log(table.toString());
826
838
  console.log(chalk5.dim(` Dashboard: ${config.apiUrl}/g/${code}`));
839
+ if (hasPlan) {
840
+ const me = data.rankings.find((r) => r.userId === config.userId);
841
+ if (me && !me.plan) {
842
+ console.log(chalk5.dim(" Set your plan: ") + chalk5.white("ccclub profile --plan pro|max100|max200|api"));
843
+ }
844
+ }
827
845
  }
828
846
  var SPARK_CHARS = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
829
847
  async function printActivity(apiUrl, code, range) {
@@ -915,12 +933,23 @@ async function profileCommand(options) {
915
933
  }
916
934
  return;
917
935
  }
936
+ const validPlans = ["pro", "max100", "max200", "api"];
937
+ if (options.plan !== void 0) {
938
+ const p = options.plan.toLowerCase();
939
+ if (p && p !== "none" && !validPlans.includes(p)) {
940
+ console.log(chalk6.red(`
941
+ Invalid plan: "${options.plan}"`));
942
+ console.log(chalk6.dim(" Valid options: ") + chalk6.white("pro") + chalk6.dim(" ($20), ") + chalk6.white("max100") + chalk6.dim(" ($100), ") + chalk6.white("max200") + chalk6.dim(" ($200), ") + chalk6.white("api"));
943
+ console.log(chalk6.dim(" To clear: ") + chalk6.white("ccclub profile --plan none"));
944
+ return;
945
+ }
946
+ }
918
947
  const body = {};
919
948
  if (options.name !== void 0) body.displayName = options.name;
920
949
  if (options.avatar !== void 0) body.avatar = options.avatar;
921
950
  if (options.public) body.visibility = "public";
922
951
  if (options.private) body.visibility = "private";
923
- if (options.plan !== void 0) body.plan = options.plan;
952
+ if (options.plan !== void 0) body.plan = options.plan === "none" ? "" : options.plan;
924
953
  const spinner = ora5("Updating profile...").start();
925
954
  try {
926
955
  const res = await fetch(`${config.apiUrl}/api/profile`, {
@@ -1052,7 +1081,7 @@ async function hookCommand() {
1052
1081
  }
1053
1082
 
1054
1083
  // src/index.ts
1055
- var VERSION = "0.2.37";
1084
+ var VERSION = "0.2.39";
1056
1085
  startUpdateCheck(VERSION);
1057
1086
  var program = new Command();
1058
1087
  program.name("ccclub").description("CCClub - Compare Claude Code usage with friends").version(VERSION);
@@ -1061,7 +1090,7 @@ program.command("join").description("Join a friend's group").argument("<invite-c
1061
1090
  program.command("sync").description("Sync local usage data to server").option("-s, --silent", "No output (used by auto-sync hook)").option("-f, --full", "Force full re-sync of all data").action(syncCommand);
1062
1091
  program.command("rank", { isDefault: true, hidden: true }).description("Show leaderboard").option("-p, --period <period>", "daily | weekly | monthly | all-time", "daily").option("-g, --group <code>", "Group invite code").option("--global", "Show global public ranking").option("--cache", "Include cache tokens in count").action(rankCommand);
1063
1092
  program.command("-p weekly|monthly|all-time", { hidden: false }).description("Switch period (default: daily)");
1064
- program.command("profile").description("View or update your profile").option("-n, --name <name>", "Set display name").option("--avatar <url>", "Set avatar URL (empty string to reset)").option("--public", "Set profile visibility to public").option("--private", "Set profile visibility to private").option("--plan <plan>", "Set subscription plan (pro, max100, max200, api, or empty to clear)").action(profileCommand);
1093
+ program.command("profile").description("View or update your profile").option("-n, --name <name>", "Set display name").option("--avatar <url>", "Set avatar URL (empty string to reset)").option("--public", "Set profile visibility to public").option("--private", "Set profile visibility to private").option("--plan <plan>", "Set plan: pro ($20), max100 ($100), max200 ($200), api, or none to clear").action(profileCommand);
1065
1094
  program.command("create").description("Create a new group").action(createGroupCommand);
1066
1095
  program.command("show-data").description("Show exactly what data CCClub uploads (privacy audit)").action(showDataCommand);
1067
1096
  program.command("hook").description("Set up Claude Code hook for auto-sync on session end").action(hookCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccclub",
3
- "version": "0.2.37",
3
+ "version": "0.2.39",
4
4
  "type": "module",
5
5
  "description": "See how much Claude Code you and your friends are using",
6
6
  "bin": {