ccclub 0.3.7 → 0.3.8

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 +99 -75
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command, Option } from "commander";
6
6
  // src/commands/init.ts
7
7
  import { createInterface as createInterface2 } from "readline/promises";
8
8
  import { stdin, stdout } from "process";
9
- import chalk4 from "chalk";
9
+ import chalk5 from "chalk";
10
10
  import ora2 from "ora";
11
11
 
12
12
  // src/config.ts
@@ -1355,7 +1355,32 @@ function getLatestBlockStartBySource(blocks) {
1355
1355
 
1356
1356
  // src/global-install.ts
1357
1357
  import { exec as exec2 } from "child_process";
1358
+ import chalk4 from "chalk";
1359
+
1360
+ // src/theme.ts
1358
1361
  import chalk3 from "chalk";
1362
+ var theme = {
1363
+ title: chalk3.hex("#F1EDE7").bold,
1364
+ text: chalk3.hex("#E8E4DE"),
1365
+ muted: chalk3.hex("#8A8480"),
1366
+ faint: chalk3.hex("#5A5550"),
1367
+ brand: chalk3.hex("#D4935E"),
1368
+ link: chalk3.hex("#7AB7C6").underline,
1369
+ linkText: chalk3.hex("#7AB7C6"),
1370
+ success: chalk3.hex("#63B486"),
1371
+ successBold: chalk3.hex("#63B486").bold,
1372
+ gold: chalk3.hex("#D6B56D"),
1373
+ goldBold: chalk3.hex("#D6B56D").bold,
1374
+ silver: chalk3.hex("#AEB7BF"),
1375
+ silverBold: chalk3.hex("#AEB7BF").bold,
1376
+ bronze: chalk3.hex("#C58A61"),
1377
+ bronzeBold: chalk3.hex("#C58A61"),
1378
+ warning: chalk3.hex("#D4A85C"),
1379
+ warningBold: chalk3.hex("#D4A85C").bold,
1380
+ danger: chalk3.hex("#D26A6A")
1381
+ };
1382
+
1383
+ // src/global-install.ts
1359
1384
  function run(cmd) {
1360
1385
  return new Promise((resolve2) => {
1361
1386
  exec2(cmd, (err, stdout5) => resolve2(err ? "" : stdout5.trim()));
@@ -1364,13 +1389,13 @@ function run(cmd) {
1364
1389
  async function ensureGlobalInstall() {
1365
1390
  const globalList = await run("npm list -g ccclub --depth=0");
1366
1391
  if (globalList.includes("ccclub@")) return;
1367
- console.log(chalk3.dim("\n Installing ccclub globally so you can run it directly..."));
1392
+ console.log(chalk4.dim("\n Installing ccclub globally so you can run it directly..."));
1368
1393
  const result = await run("npm install -g ccclub");
1369
1394
  if (result) {
1370
- console.log(chalk3.green(" Done!") + chalk3.dim(" You can now use ") + chalk3.white("ccclub") + chalk3.dim(" directly."));
1395
+ console.log(theme.success(" Done!") + chalk4.dim(" You can now use ") + theme.text("ccclub") + chalk4.dim(" directly."));
1371
1396
  } else {
1372
- console.log(chalk3.dim(" Could not auto-install. Run manually:"));
1373
- console.log(chalk3.white(" npm install -g ccclub"));
1397
+ console.log(chalk4.dim(" Could not auto-install. Run manually:"));
1398
+ console.log(theme.text(" npm install -g ccclub"));
1374
1399
  }
1375
1400
  }
1376
1401
 
@@ -1378,28 +1403,28 @@ async function ensureGlobalInstall() {
1378
1403
  async function initCommand() {
1379
1404
  const existing = await loadConfig();
1380
1405
  if (existing) {
1381
- console.log(chalk4.yellow("Already initialized!"));
1406
+ console.log(chalk5.yellow("Already initialized!"));
1382
1407
  console.log(` User: ${existing.displayName}`);
1383
1408
  console.log(` Groups: ${existing.groups.join(", ") || "(none)"}`);
1384
1409
  if (!isHookInstalled()) {
1385
1410
  const hookOk = await installHook();
1386
- if (hookOk) console.log(chalk4.green(" Auto-sync hook installed!"));
1411
+ if (hookOk) console.log(chalk5.green(" Auto-sync hook installed!"));
1387
1412
  }
1388
1413
  if (!isHeartbeatInstalled()) {
1389
1414
  const heartbeatOk = await installHeartbeat();
1390
- if (heartbeatOk) console.log(chalk4.green(" Background sync installed!"));
1415
+ if (heartbeatOk) console.log(chalk5.green(" Background sync installed!"));
1391
1416
  }
1392
- console.log(chalk4.dim('\n Run "ccclub" to see the leaderboard'));
1417
+ console.log(chalk5.dim('\n Run "ccclub" to see the leaderboard'));
1393
1418
  return;
1394
1419
  }
1395
1420
  const rl = createInterface2({ input: stdin, output: stdout });
1396
1421
  try {
1397
1422
  const defaultName = getDefaultDisplayName();
1398
- const prompt = defaultName ? chalk4.bold(`Your display name (${defaultName}): `) : chalk4.bold("Your display name: ");
1423
+ const prompt = defaultName ? chalk5.bold(`Your display name (${defaultName}): `) : chalk5.bold("Your display name: ");
1399
1424
  const input = await rl.question(prompt);
1400
1425
  const displayName = input.trim() || defaultName || "";
1401
1426
  if (!displayName) {
1402
- console.error(chalk4.red("Name cannot be empty"));
1427
+ console.error(chalk5.red("Name cannot be empty"));
1403
1428
  return;
1404
1429
  }
1405
1430
  const spinner = ora2("Setting up...").start();
@@ -1436,17 +1461,17 @@ async function initCommand() {
1436
1461
  ]);
1437
1462
  spinner.succeed("ccclub initialized!");
1438
1463
  if (!hookOk) {
1439
- console.log(chalk4.dim(' Tip: run "ccclub hook" to set up auto-sync'));
1464
+ console.log(chalk5.dim(' Tip: run "ccclub hook" to set up auto-sync'));
1440
1465
  }
1441
1466
  if (!heartbeatOk) {
1442
- console.log(chalk4.dim(' Tip: run "ccclub sync" manually to refresh non-Claude agent usage'));
1467
+ console.log(chalk5.dim(' Tip: run "ccclub sync" manually to refresh non-Claude agent usage'));
1443
1468
  }
1444
1469
  console.log("");
1445
- console.log(chalk4.bold(" Invite friends to compete:"));
1470
+ console.log(chalk5.bold(" Invite friends to compete:"));
1446
1471
  console.log("");
1447
- console.log(` ${chalk4.cyan.underline(`${apiUrl}/invite/${data.groupCode}`)}`);
1472
+ console.log(` ${theme.link(`${apiUrl}/invite/${data.groupCode}`)}`);
1448
1473
  console.log("");
1449
- console.log(chalk4.dim(` or: npx ccclub join ${data.groupCode}`));
1474
+ console.log(chalk5.dim(` or: npx ccclub join ${data.groupCode}`));
1450
1475
  console.log("");
1451
1476
  await doSync(true);
1452
1477
  await ensureGlobalInstall();
@@ -1457,14 +1482,14 @@ async function initCommand() {
1457
1482
  }
1458
1483
  function printQuickStart() {
1459
1484
  console.log("");
1460
- console.log(chalk4.dim(" Run ") + chalk4.white("ccclub") + chalk4.dim(" to see the leaderboard. ") + chalk4.white("ccclub -h") + chalk4.dim(" for all commands."));
1485
+ console.log(chalk5.dim(" Run ") + theme.text("ccclub") + chalk5.dim(" to see the leaderboard. ") + theme.text("ccclub -h") + chalk5.dim(" for all commands."));
1461
1486
  console.log("");
1462
1487
  }
1463
1488
 
1464
1489
  // src/commands/join.ts
1465
1490
  import { createInterface as createInterface3 } from "readline/promises";
1466
1491
  import { stdin as stdin2, stdout as stdout2 } from "process";
1467
- import chalk5 from "chalk";
1492
+ import chalk6 from "chalk";
1468
1493
  import ora3 from "ora";
1469
1494
  async function joinCommand(inviteCode) {
1470
1495
  let config = await loadConfig();
@@ -1478,11 +1503,11 @@ async function joinCommand(inviteCode) {
1478
1503
  const rl = createInterface3({ input: stdin2, output: stdout2 });
1479
1504
  try {
1480
1505
  const defaultName = getDefaultDisplayName();
1481
- const prompt = defaultName ? chalk5.bold(`Your display name (${defaultName}): `) : chalk5.bold("Your display name: ");
1506
+ const prompt = defaultName ? chalk6.bold(`Your display name (${defaultName}): `) : chalk6.bold("Your display name: ");
1482
1507
  const input = await rl.question(prompt);
1483
1508
  displayName = input.trim() || defaultName || "";
1484
1509
  if (!displayName) {
1485
- console.error(chalk5.red("Name cannot be empty"));
1510
+ console.error(chalk6.red("Name cannot be empty"));
1486
1511
  return;
1487
1512
  }
1488
1513
  } finally {
@@ -1531,12 +1556,11 @@ async function joinCommand(inviteCode) {
1531
1556
  await ensureGlobalInstall();
1532
1557
  }
1533
1558
  console.log("");
1534
- console.log(chalk5.dim(" Run ") + chalk5.white("ccclub") + chalk5.dim(" to see the leaderboard. ") + chalk5.white("ccclub -h") + chalk5.dim(" for all commands."));
1559
+ console.log(chalk6.dim(" Run ") + chalk6.white("ccclub") + chalk6.dim(" to see the leaderboard. ") + chalk6.white("ccclub -h") + chalk6.dim(" for all commands."));
1535
1560
  console.log("");
1536
1561
  }
1537
1562
 
1538
1563
  // src/commands/rank.ts
1539
- import chalk6 from "chalk";
1540
1564
  import Table from "cli-table3";
1541
1565
  import ora4 from "ora";
1542
1566
 
@@ -1595,11 +1619,11 @@ async function rankCommand(options) {
1595
1619
  Usage: ccclub -d <period>
1596
1620
 
1597
1621
  Options:
1598
- ${chalk6.white("ccclub -d 1")} Yesterday
1599
- ${chalk6.white("ccclub -d 7")} Last 7 days
1600
- ${chalk6.white("ccclub -d 30")} Last 30 days
1601
- ${chalk6.white("ccclub -d all")} All time
1602
- ${chalk6.white("ccclub")} Today (default)
1622
+ ${theme.text("ccclub -d 1")} Yesterday
1623
+ ${theme.text("ccclub -d 7")} Last 7 days
1624
+ ${theme.text("ccclub -d 30")} Last 30 days
1625
+ ${theme.text("ccclub -d all")} All time
1626
+ ${theme.text("ccclub")} Today (default)
1603
1627
  `;
1604
1628
  if (options.days) {
1605
1629
  if (options.days === true) {
@@ -1609,7 +1633,7 @@ async function rankCommand(options) {
1609
1633
  const DAYS_MAP = { "1": "yesterday", "7": "weekly", "30": "monthly", "all": "all-time" };
1610
1634
  const mapped = DAYS_MAP[options.days];
1611
1635
  if (!mapped) {
1612
- console.log(chalk6.red(`
1636
+ console.log(theme.danger(`
1613
1637
  Unknown value: -d ${options.days}`));
1614
1638
  console.log(DAYS_HINT);
1615
1639
  return;
@@ -1633,7 +1657,7 @@ async function rankCommand(options) {
1633
1657
  codes = config.groups.length > 0 ? config.groups : [];
1634
1658
  }
1635
1659
  if (codes.length === 0) {
1636
- console.log(chalk6.red("No group found. Run 'ccclub init' or 'ccclub join <code>' first."));
1660
+ console.log(theme.danger("No group found. Run 'ccclub init' or 'ccclub join <code>' first."));
1637
1661
  return;
1638
1662
  }
1639
1663
  const localUsagePromise = fetchUsageLimits().catch(() => null);
@@ -1671,7 +1695,7 @@ async function rankCommand(options) {
1671
1695
  for (let i = 0; i < groupResults.length; i++) {
1672
1696
  const { code, rankData, activityData, range } = groupResults[i];
1673
1697
  if (!rankData) {
1674
- console.log(chalk6.red(`
1698
+ console.log(theme.danger(`
1675
1699
  Couldn't load leaderboard for ${code}`));
1676
1700
  continue;
1677
1701
  }
@@ -1683,10 +1707,10 @@ async function rankCommand(options) {
1683
1707
  if (activityData) renderActivity(activityData, range);
1684
1708
  if (i < groupResults.length - 1) console.log("");
1685
1709
  }
1686
- console.log(chalk6.dim("\n Tokens = input + output + reasoning ") + chalk6.yellow("(cache excluded)") + chalk6.dim(". Use ") + chalk6.white("--cache") + chalk6.dim(" to include cache tokens."));
1710
+ console.log(theme.muted("\n Tokens = input + output + reasoning ") + theme.warning("(cache excluded)") + theme.muted(". Use ") + theme.text("--cache") + theme.muted(" to include cache tokens."));
1687
1711
  const update = await getUpdateResult();
1688
1712
  if (update) {
1689
- console.log(chalk6.yellow("\n Update available") + chalk6.dim(`: ${update.current} \u2192 ${update.latest} Run `) + chalk6.cyan("npm i -g ccclub@latest"));
1713
+ console.log(theme.warningBold("\n Update available") + theme.muted(`: ${update.current} \u2192 ${update.latest} Run `) + theme.linkText("npm i -g ccclub@latest"));
1690
1714
  }
1691
1715
  } catch (err) {
1692
1716
  spinner.fail(`Error: ${formatFetchError(err)}`);
@@ -1709,20 +1733,20 @@ function formatTokens(n) {
1709
1733
  }
1710
1734
  function printGroup(data, code, period, config, showCache = false, showAll = false) {
1711
1735
  if (data.rankings.length === 0) {
1712
- console.log(chalk6.bold(`
1736
+ console.log(theme.title(`
1713
1737
  ${data.group.name}`));
1714
- console.log(chalk6.yellow(" No data for this period yet"));
1715
- console.log(chalk6.dim(" Sync your data first: ccclub sync"));
1738
+ console.log(theme.warning(" No data for this period yet"));
1739
+ console.log(theme.muted(" Sync your data first: ccclub sync"));
1716
1740
  return;
1717
1741
  }
1718
- console.log(chalk6.bold(`
1742
+ console.log(theme.title(`
1719
1743
  ${data.group.name}`));
1720
1744
  const periodLabel = { daily: "TODAY", yesterday: "YESTERDAY", weekly: "7 DAYS", monthly: "30 DAYS", "all-time": "ALL TIME" };
1721
1745
  const now = Date.now();
1722
1746
  const activeCount = data.rankings.filter((r) => r.lastSync && now - new Date(r.lastSync).getTime() < ACTIVE_THRESHOLD_MS).length;
1723
- console.log(chalk6.dim(` ${periodLabel[period] || period.toUpperCase()} \xB7 ${data.start.slice(0, 10)} \u2192 ${data.end.slice(0, 10)} \xB7 ${data.group.memberCount} members`));
1747
+ console.log(theme.muted(` ${periodLabel[period] || period.toUpperCase()} \xB7 ${data.start.slice(0, 10)} \u2192 ${data.end.slice(0, 10)} \xB7 ${data.group.memberCount} members`));
1724
1748
  if (activeCount > 0) {
1725
- console.log(chalk6.green(` ${activeCount} active`));
1749
+ console.log(theme.success(` ${activeCount} active`));
1726
1750
  }
1727
1751
  console.log("");
1728
1752
  const activeRankings = showAll || data.rankings.length <= 15 ? data.rankings : data.rankings.filter((r) => r.costUSD > 0 || r.userId === config.userId);
@@ -1769,53 +1793,65 @@ function printGroup(data, code, period, config, showCache = false, showAll = fal
1769
1793
  columnWidth("$/Turn", plainRows.map((r) => r.perTurn), 6, 7)
1770
1794
  );
1771
1795
  const table = new Table({
1772
- head: head.map((h) => chalk6.cyan(h)),
1773
- style: { head: [], border: [] },
1796
+ head: head.map((h) => theme.linkText(h)),
1797
+ style: { head: [], border: ["gray"] },
1774
1798
  colWidths: widths
1775
1799
  });
1776
1800
  for (const plain of plainRows) {
1777
1801
  const { entry } = plain;
1778
1802
  const isMe = entry.userId === config.userId;
1779
- const marker = isMe ? chalk6.green("\u2192") : " ";
1780
- const id = (s) => s;
1781
- const c = isMe ? chalk6.green : entry.rank === 1 ? chalk6.yellow : id;
1782
- const nameC = isMe ? chalk6.green.bold : entry.rank === 1 ? chalk6.yellow.bold : id;
1803
+ const rowStyle = isMe ? theme.success : podiumStyle(entry.rank);
1804
+ const nameStyle = isMe ? theme.successBold : podiumNameStyle(entry.rank);
1805
+ const rankStyle = podiumNameStyle(entry.rank);
1806
+ const marker = isMe ? theme.success("\u2192") : " ";
1783
1807
  const nameWidth = Math.max(widths[1] - 2, 4);
1784
- const displayName = plain.isActive ? `${chalk6.green("\u25CF")} ${nameC(truncateDisplay(entry.displayName, Math.max(nameWidth - 2, 1)))}` : nameC(truncateDisplay(entry.displayName, nameWidth));
1808
+ const displayName = plain.isActive ? `${theme.success("\u25CF")} ${nameStyle(truncateDisplay(entry.displayName, Math.max(nameWidth - 2, 1)))}` : nameStyle(truncateDisplay(entry.displayName, nameWidth));
1785
1809
  const row = [
1786
- `${marker}${c(String(entry.rank))}`,
1810
+ `${marker}${rankStyle(String(entry.rank))}`,
1787
1811
  displayName
1788
1812
  ];
1789
1813
  if (hasAgents) {
1790
1814
  const agentWidth = Math.max(widths[2] - 2, 4);
1791
- row.push(c(truncateDisplay(plain.agents, agentWidth)));
1815
+ row.push(rowStyle(truncateDisplay(plain.agents, agentWidth)));
1792
1816
  }
1793
- row.push(c(plain.cost), c(plain.tokens));
1817
+ row.push(rowStyle(plain.cost), rowStyle(plain.tokens));
1794
1818
  if (hasPlan) {
1795
1819
  row.push(colorRoi(plain.roi, entry));
1796
1820
  }
1797
- row.push(c(plain.turns));
1798
- row.push(entry.chatCount > 0 ? c(plain.perTurn) : chalk6.dim("\u2014"));
1821
+ row.push(rowStyle(plain.turns));
1822
+ row.push(entry.chatCount > 0 ? rowStyle(plain.perTurn) : theme.faint("\u2014"));
1799
1823
  table.push(row);
1800
1824
  }
1801
1825
  console.log(table.toString());
1802
1826
  if (hiddenCount > 0) {
1803
- console.log(chalk6.dim(` ${hiddenCount} inactive member${hiddenCount > 1 ? "s" : ""} hidden \xB7 ccclub --all to show`));
1827
+ console.log(theme.muted(` ${hiddenCount} inactive member${hiddenCount > 1 ? "s" : ""} hidden \xB7 ccclub --all to show`));
1804
1828
  }
1805
- console.log(chalk6.dim(" Dashboard: ") + chalk6.green(`${config.apiUrl}/g/${code}`));
1829
+ console.log(theme.muted(" Dashboard: ") + theme.link(`${config.apiUrl}/g/${code}`));
1806
1830
  if (code !== "global") {
1807
- console.log(chalk6.dim(" Invite: ") + chalk6.hex("#d4935e").underline(`${config.apiUrl}/invite/${code}`));
1831
+ console.log(theme.muted(" Invite: ") + theme.link(`${config.apiUrl}/invite/${code}`));
1808
1832
  }
1809
1833
  if (hasPlan) {
1810
1834
  const me = data.rankings.find((r) => r.userId === config.userId);
1811
1835
  if (me && !me.plan) {
1812
- console.log(chalk6.dim(" Set your plan: ") + chalk6.white("ccclub profile --plan pro|max100|max200|api"));
1836
+ console.log(theme.muted(" Set your plan: ") + theme.text("ccclub profile --plan pro|max100|max200|api"));
1813
1837
  }
1814
1838
  }
1815
1839
  }
1816
1840
  function isEntryActive(entry, now) {
1817
1841
  return Boolean(entry.lastSync && now - new Date(entry.lastSync).getTime() < ACTIVE_THRESHOLD_MS);
1818
1842
  }
1843
+ function podiumStyle(rank) {
1844
+ if (rank === 1) return theme.gold;
1845
+ if (rank === 2) return theme.silver;
1846
+ if (rank === 3) return theme.bronze;
1847
+ return theme.text;
1848
+ }
1849
+ function podiumNameStyle(rank) {
1850
+ if (rank === 1) return theme.goldBold;
1851
+ if (rank === 2) return theme.silverBold;
1852
+ if (rank === 3) return theme.bronzeBold;
1853
+ return theme.text;
1854
+ }
1819
1855
  function formatRoi(entry, hasPlan) {
1820
1856
  if (!hasPlan) return "";
1821
1857
  if (entry.plan && entry.plan !== "api") {
@@ -1832,9 +1868,9 @@ function colorRoi(roiStr, entry) {
1832
1868
  const price = PLAN_PRICES[entry.plan];
1833
1869
  const monthly = entry.monthlyCostUSD || 0;
1834
1870
  const roi = price > 0 ? Math.round(monthly / price * 100) : 0;
1835
- return roi >= 100 ? chalk6.green.bold(roiStr) : roi >= 50 ? chalk6.yellow(roiStr) : chalk6.dim(roiStr);
1871
+ return roi >= 100 ? theme.successBold(roiStr) : roi >= 50 ? theme.warning(roiStr) : theme.faint(roiStr);
1836
1872
  }
1837
- return chalk6.dim(roiStr);
1873
+ return theme.faint(roiStr);
1838
1874
  }
1839
1875
  function formatAgents(entry) {
1840
1876
  if (entry.agentBreakdown && entry.agentBreakdown.length > 0) {
@@ -1908,7 +1944,7 @@ function renderActivity(data, range) {
1908
1944
  }
1909
1945
  }
1910
1946
  if (globalMax === 0) globalMax = 1;
1911
- console.log(chalk6.dim(`
1947
+ console.log(theme.muted(`
1912
1948
  Activity (${range})`));
1913
1949
  for (let i = 0; i < active.length; i++) {
1914
1950
  const user = active[i];
@@ -1920,22 +1956,10 @@ function renderActivity(data, range) {
1920
1956
  return SPARK_CHARS[idx];
1921
1957
  }).join("");
1922
1958
  const total = user.blocks.reduce((s, b) => s + b.cost, 0);
1923
- const displayWidth = [...user.displayName].reduce((w, ch) => w + (ch.charCodeAt(0) > 127 ? 2 : 1), 0);
1924
1959
  const maxWidth = 12;
1925
- let name = user.displayName;
1926
- if (displayWidth > maxWidth) {
1927
- let w = 0;
1928
- let cut = 0;
1929
- for (const ch of name) {
1930
- const cw = ch.charCodeAt(0) > 127 ? 2 : 1;
1931
- if (w + cw > maxWidth) break;
1932
- w += cw;
1933
- cut++;
1934
- }
1935
- name = [...name].slice(0, cut).join("");
1936
- }
1937
- const pad = " ".repeat(Math.max(0, maxWidth - displayWidth));
1938
- console.log(` ${chalk6.dim(name + pad)} ${spark} ${chalk6.dim("$" + total.toFixed(2))}`);
1960
+ const name = truncateDisplay(user.displayName, maxWidth);
1961
+ const pad = " ".repeat(Math.max(0, maxWidth - visualWidth(name)));
1962
+ console.log(` ${theme.muted(name + pad)} ${theme.brand(spark)} ${theme.muted("$" + total.toFixed(2))}`);
1939
1963
  }
1940
1964
  const axisArr = new Array(bucketCount).fill(" ");
1941
1965
  if (range === "24h" || range === "yesterday") {
@@ -1958,7 +1982,7 @@ function renderActivity(data, range) {
1958
1982
  for (let c = 0; c < label.length && b + c < bucketCount; c++) axisArr[b + c] = label[c];
1959
1983
  }
1960
1984
  }
1961
- console.log(chalk6.dim(" " + " ".repeat(12) + " " + axisArr.join("")));
1985
+ console.log(theme.faint(" " + " ".repeat(12) + " " + axisArr.join("")));
1962
1986
  }
1963
1987
 
1964
1988
  // src/commands/profile.ts
@@ -2128,7 +2152,7 @@ async function createGroupCommand() {
2128
2152
  }
2129
2153
  spinner.succeed(`Created "${data.groupName}"`);
2130
2154
  console.log("");
2131
- console.log(` ${chalk9.cyan.underline(`${config.apiUrl}/invite/${data.groupCode}`)}`);
2155
+ console.log(` ${theme.link(`${config.apiUrl}/invite/${data.groupCode}`)}`);
2132
2156
  console.log("");
2133
2157
  console.log(chalk9.dim(` or: npx ccclub join ${data.groupCode}`));
2134
2158
  } finally {
@@ -2228,7 +2252,7 @@ async function hookCommand() {
2228
2252
  }
2229
2253
 
2230
2254
  // src/index.ts
2231
- var VERSION = "0.3.7";
2255
+ var VERSION = "0.3.8";
2232
2256
  startUpdateCheck(VERSION);
2233
2257
  var program = new Command();
2234
2258
  if (process.argv.slice(2).includes("-v")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccclub",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "type": "module",
5
5
  "description": "Claude Code and Codex leaderboard among friends for coding agent tokens and costs",
6
6
  "bin": {