ccclub 0.2.39 → 0.2.41

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 +34 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18,8 +18,8 @@ import { randomBytes } from "crypto";
18
18
  import { execSync } from "child_process";
19
19
 
20
20
  // ../shared/dist/constants.js
21
- var BLOCK_DURATION_HOURS = 1;
22
- var BLOCK_DURATION_MS = BLOCK_DURATION_HOURS * 60 * 60 * 1e3;
21
+ var BLOCK_DURATION_MIN = 30;
22
+ var BLOCK_DURATION_MS = BLOCK_DURATION_MIN * 60 * 1e3;
23
23
  var DEFAULT_API_URL = "https://ccclub.dev";
24
24
  var CLAUDE_PROJECTS_DIR = ".claude/projects";
25
25
  var CCCLUB_CONFIG_DIR = ".ccclub";
@@ -282,16 +282,17 @@ async function collectUsageEntries() {
282
282
  }
283
283
 
284
284
  // src/aggregator.ts
285
- function floorToHour(date) {
285
+ function floorToBlock(date) {
286
286
  const floored = new Date(date);
287
- floored.setUTCMinutes(0, 0, 0);
287
+ const min = floored.getUTCMinutes();
288
+ floored.setUTCMinutes(min - min % 30, 0, 0);
288
289
  return floored;
289
290
  }
290
291
  function aggregateToBlocks(entries, humanTurns = []) {
291
292
  if (entries.length === 0) return [];
292
293
  const humanTurnMs = humanTurns.map((t) => new Date(t).getTime());
293
294
  const blocks = [];
294
- let blockStart = floorToHour(new Date(entries[0].timestamp));
295
+ let blockStart = floorToBlock(new Date(entries[0].timestamp));
295
296
  let blockEnd = new Date(blockStart.getTime() + BLOCK_DURATION_MS);
296
297
  let currentBlock = [];
297
298
  let humanIdx = 0;
@@ -364,7 +365,7 @@ function aggregateToBlocks(entries, humanTurns = []) {
364
365
  }
365
366
 
366
367
  // src/commands/sync.ts
367
- var SYNC_FORMAT_VERSION = "5";
368
+ var SYNC_FORMAT_VERSION = "6";
368
369
  function getSyncVersionPath() {
369
370
  return join4(homedir4(), CCCLUB_CONFIG_DIR, "sync-version");
370
371
  }
@@ -843,7 +844,7 @@ function printGroup(data, code, period, config, showCache = false) {
843
844
  }
844
845
  }
845
846
  }
846
- var SPARK_CHARS = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
847
+ var SPARK_CHARS = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587";
847
848
  async function printActivity(apiUrl, code, range) {
848
849
  try {
849
850
  const tz = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
@@ -854,7 +855,7 @@ async function printActivity(apiUrl, code, range) {
854
855
  if (active.length === 0) return;
855
856
  const startMs = new Date(data.start).getTime();
856
857
  const endMs = new Date(data.end).getTime();
857
- const bucketCount = range === "24h" ? 24 : range === "7d" ? 28 : 30;
858
+ const bucketCount = range === "24h" ? 48 : range === "7d" ? 28 : 30;
858
859
  const bucketMs = (endMs - startMs) / bucketCount;
859
860
  const allBuckets = [];
860
861
  for (const user of active) {
@@ -878,6 +879,7 @@ async function printActivity(apiUrl, code, range) {
878
879
  const user = active[i];
879
880
  const buckets = allBuckets[i];
880
881
  const spark = buckets.map((v) => {
882
+ if (v === 0) return " ";
881
883
  const idx = Math.min(Math.floor(v / globalMax * SPARK_CHARS.length), SPARK_CHARS.length - 1);
882
884
  return SPARK_CHARS[idx];
883
885
  }).join("");
@@ -899,6 +901,28 @@ async function printActivity(apiUrl, code, range) {
899
901
  const pad = " ".repeat(Math.max(0, maxWidth - displayWidth));
900
902
  console.log(` ${chalk5.dim(name + pad)} ${spark} ${chalk5.dim("$" + total.toFixed(2))}`);
901
903
  }
904
+ const axisArr = new Array(bucketCount).fill(" ");
905
+ if (range === "24h") {
906
+ for (let b = 0; b < bucketCount; b += 12) {
907
+ const t = new Date(startMs + b * bucketMs);
908
+ const label = `${t.getHours()}h`;
909
+ for (let c = 0; c < label.length && b + c < bucketCount; c++) axisArr[b + c] = label[c];
910
+ }
911
+ } else if (range === "7d") {
912
+ const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
913
+ for (let b = 0; b < bucketCount; b += 4) {
914
+ const t = new Date(startMs + b * bucketMs);
915
+ const label = dayNames[t.getDay()];
916
+ for (let c = 0; c < label.length && b + c < bucketCount; c++) axisArr[b + c] = label[c];
917
+ }
918
+ } else {
919
+ for (let b = 0; b < bucketCount; b += 7) {
920
+ const t = new Date(startMs + b * bucketMs);
921
+ const label = `${t.getMonth() + 1}/${t.getDate()}`;
922
+ for (let c = 0; c < label.length && b + c < bucketCount; c++) axisArr[b + c] = label[c];
923
+ }
924
+ }
925
+ console.log(chalk5.dim(" " + " ".repeat(12) + " " + axisArr.join("")));
902
926
  } catch {
903
927
  }
904
928
  }
@@ -986,7 +1010,7 @@ async function profileCommand(options) {
986
1010
  import chalk7 from "chalk";
987
1011
  async function showDataCommand() {
988
1012
  console.log(chalk7.bold("\n What CCClub uploads:\n"));
989
- console.log(chalk7.dim(" Only aggregated 1-hour block summaries. No conversation content,"));
1013
+ console.log(chalk7.dim(" Only aggregated 30-minute block summaries. No conversation content,"));
990
1014
  console.log(chalk7.dim(" no file paths, no project names, no session details.\n"));
991
1015
  const { entries, humanTurns } = await collectUsageEntries();
992
1016
  const blocks = aggregateToBlocks(entries, humanTurns);
@@ -1081,7 +1105,7 @@ async function hookCommand() {
1081
1105
  }
1082
1106
 
1083
1107
  // src/index.ts
1084
- var VERSION = "0.2.39";
1108
+ var VERSION = "0.2.41";
1085
1109
  startUpdateCheck(VERSION);
1086
1110
  var program = new Command();
1087
1111
  program.name("ccclub").description("CCClub - Compare Claude Code usage with friends").version(VERSION);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccclub",
3
- "version": "0.2.39",
3
+ "version": "0.2.41",
4
4
  "type": "module",
5
5
  "description": "See how much Claude Code you and your friends are using",
6
6
  "bin": {