standout 0.5.38 → 0.6.0

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 +17 -0
  2. package/dist/cli.js +429 -114
  3. package/package.json +6 -1
package/README.md CHANGED
@@ -11,3 +11,20 @@ get matched with roles through [Standout](https://standout.work).
11
11
 
12
12
  Optional: pass a job slug to apply directly (`npx standout <job>`), or `--chat`
13
13
  to build a full profile interactively.
14
+
15
+ ## Runs monthly, automatically
16
+
17
+ After a full run, standout schedules a monthly refresh (1st of each month) so
18
+ your stats never decay — local session logs only cover ~30 days, and the
19
+ refresh keeps your full history intact. Uses launchd on macOS and cron on
20
+ Linux; not available on Windows.
21
+
22
+ ```bash
23
+ npx standout schedule status # is it on? command, log path, last run
24
+ npx standout schedule off # disable (won't be re-added automatically)
25
+ npx standout schedule [job] # re-enable / install manually
26
+ ```
27
+
28
+ Scheduled runs are unattended: they upload your refreshed stats and write the
29
+ wrapped link to the log (`~/Library/Logs/standout.log` on macOS,
30
+ `~/.standout/standout.log` on Linux) instead of opening a browser.
package/dist/cli.js CHANGED
@@ -3,10 +3,10 @@ var __toBinaryNode = Uint8Array.fromBase64 || ((base64) => new Uint8Array(Buffer
3
3
 
4
4
  // src/cli.ts
5
5
  import Anthropic from "@anthropic-ai/sdk";
6
- import chalk2 from "chalk";
7
- import { writeFileSync } from "node:fs";
6
+ import chalk3 from "chalk";
7
+ import { writeFileSync as writeFileSync2 } from "node:fs";
8
8
  import { tmpdir as tmpdir2 } from "node:os";
9
- import { join as join6 } from "node:path";
9
+ import { join as join7 } from "node:path";
10
10
  import { createInterface as createInterface3 } from "readline";
11
11
 
12
12
  // src/sources.ts
@@ -514,8 +514,12 @@ function computeHours(aiUsage) {
514
514
  for (const src of WRAPPED_SOURCES) {
515
515
  const stats = aiUsage[src];
516
516
  if (!stats) continue;
517
- totalHours += num2(stats.total_duration_hours);
518
- totalSessions += num2(stats.total_sessions);
517
+ totalHours += num2(
518
+ stats.all_time?.total_duration_hours ?? stats.total_duration_hours
519
+ );
520
+ totalSessions += num2(
521
+ stats.all_time?.total_sessions ?? stats.total_sessions
522
+ );
519
523
  }
520
524
  return { total_hours: totalHours, total_sessions: totalSessions };
521
525
  }
@@ -5144,6 +5148,305 @@ The JSON should follow this structure:
5144
5148
  - Ask interactive questions ONE AT A TIME.
5145
5149
  - If you receive a pause_turn stop reason, your turn will be continued automatically \u2014 just keep going.`;
5146
5150
 
5151
+ // src/schedule.ts
5152
+ import chalk from "chalk";
5153
+ import { spawnSync as spawnSync2 } from "node:child_process";
5154
+ import {
5155
+ existsSync as existsSync6,
5156
+ mkdirSync as mkdirSync2,
5157
+ readFileSync as readFileSync6,
5158
+ rmSync as rmSync2,
5159
+ statSync as statSync5,
5160
+ writeFileSync
5161
+ } from "node:fs";
5162
+ import { homedir as homedir6 } from "node:os";
5163
+ import { join as join6 } from "node:path";
5164
+ var LAUNCHD_LABEL = "work.standout.monthly";
5165
+ var CRON_MARKER = "# standout-monthly";
5166
+ var ACCENT = "#ad5cff";
5167
+ var SLUG_RE = /^[a-z0-9][a-z0-9_-]*$/i;
5168
+ var FLAG_ALLOWLIST = ["--local", "--no-upload", "--terminal"];
5169
+ function parseScheduleArgs(args) {
5170
+ if (args[0] === "unschedule") return { kind: "remove" };
5171
+ const rest = args.slice(1);
5172
+ if (rest[0] === "off" || rest[0] === "remove") return { kind: "remove" };
5173
+ if (rest[0] === "status") return { kind: "status" };
5174
+ let slug;
5175
+ const flags = [];
5176
+ for (const arg of rest) {
5177
+ if (arg === "--chat") {
5178
+ throw new Error(
5179
+ "--chat needs an interactive terminal and can't be scheduled"
5180
+ );
5181
+ }
5182
+ if (arg.startsWith("-")) {
5183
+ if (!FLAG_ALLOWLIST.includes(arg)) {
5184
+ throw new Error(
5185
+ `unknown flag for schedule: ${arg} (allowed: ${FLAG_ALLOWLIST.join(", ")})`
5186
+ );
5187
+ }
5188
+ if (!flags.includes(arg)) flags.push(arg);
5189
+ continue;
5190
+ }
5191
+ if (slug) throw new Error(`unexpected argument: ${arg}`);
5192
+ if (!SLUG_RE.test(arg)) throw new Error(`invalid job slug: ${arg}`);
5193
+ slug = arg;
5194
+ }
5195
+ return { kind: "install", slug, flags };
5196
+ }
5197
+ function buildRunCommand(slug, flags) {
5198
+ return ["npx", "-y", "standout@latest", ...slug ? [slug] : [], ...flags].join(" ").trim();
5199
+ }
5200
+ function escapeXml(text) {
5201
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5202
+ }
5203
+ function unescapeXml(text) {
5204
+ return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
5205
+ }
5206
+ function buildLaunchdPlist(command, logPath) {
5207
+ return `<?xml version="1.0" encoding="UTF-8"?>
5208
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
5209
+ <plist version="1.0">
5210
+ <dict>
5211
+ <key>Label</key><string>${LAUNCHD_LABEL}</string>
5212
+ <key>ProgramArguments</key>
5213
+ <array>
5214
+ <string>/bin/zsh</string>
5215
+ <string>-lc</string>
5216
+ <string>${escapeXml(command)}</string>
5217
+ </array>
5218
+ <key>StartCalendarInterval</key>
5219
+ <dict>
5220
+ <key>Day</key><integer>1</integer>
5221
+ <key>Hour</key><integer>10</integer>
5222
+ <key>Minute</key><integer>0</integer>
5223
+ </dict>
5224
+ <key>StandardOutPath</key><string>${escapeXml(logPath)}</string>
5225
+ <key>StandardErrorPath</key><string>${escapeXml(logPath)}</string>
5226
+ </dict>
5227
+ </plist>
5228
+ `;
5229
+ }
5230
+ function buildCronLine(command, logPath) {
5231
+ return `0 10 1 * * /bin/bash -lc '${command}' >> "${logPath}" 2>&1 ${CRON_MARKER}`;
5232
+ }
5233
+ function stripCronEntries(crontab) {
5234
+ return crontab.split("\n").filter((line) => !line.includes(CRON_MARKER)).join("\n");
5235
+ }
5236
+ function supportedPlatform() {
5237
+ return process.platform === "darwin" || process.platform === "linux";
5238
+ }
5239
+ function stateDir() {
5240
+ return join6(homedir6(), ".standout");
5241
+ }
5242
+ function optOutPath() {
5243
+ return join6(stateDir(), "no-schedule");
5244
+ }
5245
+ function plistPath() {
5246
+ return join6(homedir6(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
5247
+ }
5248
+ function schedLogPath() {
5249
+ return process.platform === "darwin" ? join6(homedir6(), "Library", "Logs", "standout.log") : join6(stateDir(), "standout.log");
5250
+ }
5251
+ function isOptedOut() {
5252
+ return existsSync6(optOutPath());
5253
+ }
5254
+ function writeOptOut() {
5255
+ mkdirSync2(stateDir(), { recursive: true });
5256
+ writeFileSync(
5257
+ optOutPath(),
5258
+ "created by `standout schedule off` \u2014 delete (or run `npx standout schedule`) to re-enable monthly runs\n"
5259
+ );
5260
+ }
5261
+ function clearOptOut() {
5262
+ rmSync2(optOutPath(), { force: true });
5263
+ }
5264
+ function launchctl(args) {
5265
+ const res = spawnSync2("launchctl", args, { encoding: "utf8" });
5266
+ return {
5267
+ status: res.status,
5268
+ stdout: res.stdout ?? "",
5269
+ stderr: res.stderr ?? ""
5270
+ };
5271
+ }
5272
+ function uid() {
5273
+ return process.getuid?.() ?? 0;
5274
+ }
5275
+ function readCrontab() {
5276
+ const res = spawnSync2("crontab", ["-l"], { encoding: "utf8" });
5277
+ return res.status === 0 ? res.stdout ?? "" : "";
5278
+ }
5279
+ function writeCrontab(content) {
5280
+ const res = spawnSync2("crontab", ["-"], {
5281
+ input: content,
5282
+ encoding: "utf8"
5283
+ });
5284
+ if (res.status !== 0) {
5285
+ throw new Error(`crontab update failed: ${res.stderr?.trim() || "error"}`);
5286
+ }
5287
+ }
5288
+ function installJob(command) {
5289
+ if (process.platform === "darwin") {
5290
+ const path2 = plistPath();
5291
+ mkdirSync2(join6(homedir6(), "Library", "LaunchAgents"), { recursive: true });
5292
+ writeFileSync(path2, buildLaunchdPlist(command, schedLogPath()));
5293
+ launchctl(["bootout", `gui/${uid()}/${LAUNCHD_LABEL}`]);
5294
+ const res = launchctl(["bootstrap", `gui/${uid()}`, path2]);
5295
+ if (res.status !== 0) {
5296
+ throw new Error(
5297
+ `launchctl bootstrap failed (${res.stderr.trim() || res.status}) \u2014 plist written to ${path2}; load it manually with: launchctl bootstrap gui/$(id -u) ${path2}`
5298
+ );
5299
+ }
5300
+ } else {
5301
+ mkdirSync2(stateDir(), { recursive: true });
5302
+ const stripped = stripCronEntries(readCrontab());
5303
+ const base = stripped === "" || stripped.endsWith("\n") ? stripped : stripped + "\n";
5304
+ writeCrontab(base + buildCronLine(command, schedLogPath()) + "\n");
5305
+ }
5306
+ }
5307
+ function installedCommand() {
5308
+ if (process.platform === "darwin") {
5309
+ if (!existsSync6(plistPath())) return null;
5310
+ const xml = readFileSync6(plistPath(), "utf8");
5311
+ const m = xml.match(/<string>-lc<\/string>\s*<string>([^<]*)<\/string>/);
5312
+ return m ? unescapeXml(m[1]) : null;
5313
+ }
5314
+ if (process.platform === "linux") {
5315
+ const line = readCrontab().split("\n").find((l) => l.includes(CRON_MARKER));
5316
+ const m = line?.match(/-lc '([^']*)'/);
5317
+ return m ? m[1] : null;
5318
+ }
5319
+ return null;
5320
+ }
5321
+ async function installSchedule(slug, flags) {
5322
+ if (!supportedPlatform()) {
5323
+ process.stderr.write(
5324
+ "\n scheduling isn't supported on this platform yet \u2014 run `npx standout` manually.\n\n"
5325
+ );
5326
+ process.exit(1);
5327
+ }
5328
+ clearOptOut();
5329
+ const command = buildRunCommand(slug, flags);
5330
+ installJob(command);
5331
+ process.stderr.write(
5332
+ `
5333
+ ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh scheduled")} ${chalk.dim("(1st of each month, 10:00)")}
5334
+ ` + chalk.dim(` runs: ${command}
5335
+ `) + chalk.dim(` log: ${schedLogPath()}
5336
+ `) + chalk.dim(" disable anytime with `npx standout schedule off`\n\n")
5337
+ );
5338
+ }
5339
+ async function removeSchedule() {
5340
+ if (!supportedPlatform()) {
5341
+ process.stderr.write(
5342
+ "\n scheduling isn't supported on this platform \u2014 nothing to remove.\n\n"
5343
+ );
5344
+ return;
5345
+ }
5346
+ writeOptOut();
5347
+ let removed = false;
5348
+ if (process.platform === "darwin") {
5349
+ launchctl(["bootout", `gui/${uid()}/${LAUNCHD_LABEL}`]);
5350
+ if (existsSync6(plistPath())) {
5351
+ rmSync2(plistPath(), { force: true });
5352
+ removed = true;
5353
+ }
5354
+ } else {
5355
+ const current = readCrontab();
5356
+ const stripped = stripCronEntries(current);
5357
+ if (stripped !== current) {
5358
+ writeCrontab(stripped);
5359
+ removed = true;
5360
+ }
5361
+ }
5362
+ process.stderr.write(
5363
+ removed ? `
5364
+ ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh disabled")}
5365
+ ` + chalk.dim(
5366
+ " it won't be scheduled again \u2014 re-enable with `npx standout schedule`\n\n"
5367
+ ) : `
5368
+ ${chalk.dim("no monthly schedule installed \u2014 future runs won't add one (re-enable with `npx standout schedule`)")}
5369
+
5370
+ `
5371
+ );
5372
+ }
5373
+ async function scheduleStatus() {
5374
+ if (!supportedPlatform()) {
5375
+ process.stderr.write(
5376
+ "\n scheduling isn't supported on this platform.\n\n"
5377
+ );
5378
+ return;
5379
+ }
5380
+ const command = installedCommand();
5381
+ if (!command) {
5382
+ process.stderr.write(
5383
+ `
5384
+ ${chalk.white("no monthly schedule installed")}` + (isOptedOut() ? chalk.dim(" (opted out)") : "") + "\n" + chalk.dim(" enable with `npx standout schedule`\n\n")
5385
+ );
5386
+ return;
5387
+ }
5388
+ process.stderr.write(
5389
+ `
5390
+ ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh is on")} ${chalk.dim("(1st of each month, 10:00)")}
5391
+ ` + chalk.dim(` runs: ${command}
5392
+ `) + chalk.dim(` log: ${schedLogPath()}
5393
+ `)
5394
+ );
5395
+ if (process.platform === "darwin") {
5396
+ const res = launchctl(["print", `gui/${uid()}/${LAUNCHD_LABEL}`]);
5397
+ const exitLine = res.stdout.split("\n").find((l) => l.includes("last exit code"));
5398
+ if (res.status !== 0) {
5399
+ process.stderr.write(
5400
+ chalk.dim(
5401
+ " warning: job not loaded in launchd \u2014 re-run `npx standout schedule`\n"
5402
+ )
5403
+ );
5404
+ } else if (exitLine) {
5405
+ process.stderr.write(chalk.dim(` ${exitLine.trim()}
5406
+ `));
5407
+ }
5408
+ }
5409
+ if (existsSync6(schedLogPath())) {
5410
+ const mtime = statSync5(schedLogPath()).mtime;
5411
+ const tail = readFileSync6(schedLogPath(), "utf8").trimEnd().split("\n").slice(-10);
5412
+ process.stderr.write(
5413
+ chalk.dim(` last log activity: ${mtime.toLocaleString()}
5414
+
5415
+ `) + tail.map((l) => chalk.dim(` \u2502 ${l}
5416
+ `)).join("")
5417
+ );
5418
+ }
5419
+ process.stderr.write("\n");
5420
+ }
5421
+ async function maybeAutoInstallSchedule(slug) {
5422
+ try {
5423
+ if (!supportedPlatform() || isOptedOut()) return;
5424
+ const command = buildRunCommand(slug, []);
5425
+ if (installedCommand() === command) {
5426
+ process.stderr.write(
5427
+ chalk.dim(
5428
+ " monthly refresh is on \u2014 `npx standout schedule off` to disable\n\n"
5429
+ )
5430
+ );
5431
+ return;
5432
+ }
5433
+ installJob(command);
5434
+ process.stderr.write(
5435
+ ` ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh scheduled")} ${chalk.dim("(1st of each month) \u2014 disable with `npx standout schedule off`")}
5436
+
5437
+ `
5438
+ );
5439
+ } catch (error) {
5440
+ process.stderr.write(
5441
+ chalk.dim(
5442
+ ` (couldn't schedule the monthly refresh: ${error instanceof Error ? error.message : String(error)})
5443
+
5444
+ `
5445
+ )
5446
+ );
5447
+ }
5448
+ }
5449
+
5147
5450
  // src/tools.ts
5148
5451
  import { execSync as execSync3 } from "child_process";
5149
5452
  import { createInterface as createInterface2 } from "readline";
@@ -6014,7 +6317,7 @@ function computeConversation(aiUsage, line, themes) {
6014
6317
 
6015
6318
  // src/wrapped/render.ts
6016
6319
  import boxen from "boxen";
6017
- import chalk from "chalk";
6320
+ import chalk2 from "chalk";
6018
6321
  import gradient from "gradient-string";
6019
6322
 
6020
6323
  // src/wrapped/chrono-critters.ts
@@ -6191,8 +6494,8 @@ function hasHistogramData(view) {
6191
6494
  return view.hour_histogram.some((v) => v > 0);
6192
6495
  }
6193
6496
  function divider(label) {
6194
- return chalk.dim(`
6195
- ${label.padEnd(48, " ")} ${chalk.dim("[press \u21B5]")}
6497
+ return chalk2.dim(`
6498
+ ${label.padEnd(48, " ")} ${chalk2.dim("[press \u21B5]")}
6196
6499
  `);
6197
6500
  }
6198
6501
  function wrapWords(text, width) {
@@ -6230,7 +6533,7 @@ function centerBlock(art, color) {
6230
6533
  function bar2(value, max, width) {
6231
6534
  if (max === 0) return " ".repeat(width);
6232
6535
  const filled = Math.round(value / max * width);
6233
- return chalk.hex("#ff8a00")("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(width - filled));
6536
+ return chalk2.hex("#ff8a00")("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(width - filled));
6234
6537
  }
6235
6538
  function compactNum(n) {
6236
6539
  const sign = n < 0 ? "-" : "";
@@ -6240,12 +6543,12 @@ function compactNum(n) {
6240
6543
  return `${sign}${abs}`;
6241
6544
  }
6242
6545
  function coloredBar(value, max, width, hex) {
6243
- if (max <= 0) return chalk.gray("\u2591".repeat(width));
6546
+ if (max <= 0) return chalk2.gray("\u2591".repeat(width));
6244
6547
  const filled = Math.max(
6245
6548
  0,
6246
6549
  Math.min(width, Math.round(value / max * width))
6247
6550
  );
6248
- return chalk.hex(hex)("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(width - filled));
6551
+ return chalk2.hex(hex)("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(width - filled));
6249
6552
  }
6250
6553
  function sparkline2(buckets) {
6251
6554
  if (!buckets.length) return "";
@@ -6273,8 +6576,8 @@ function hourlyChart(buckets, critter = null) {
6273
6576
  }
6274
6577
  }
6275
6578
  const left = [
6276
- chalk.hex("#ad5cff")(spark.padEnd(width, " ")),
6277
- chalk.dim(axis.join(""))
6579
+ chalk2.hex("#ad5cff")(spark.padEnd(width, " ")),
6580
+ chalk2.dim(axis.join(""))
6278
6581
  ];
6279
6582
  if (!critter) return left.map((l) => ` ${l}`);
6280
6583
  const critterLines = critter.art.split("\n");
@@ -6316,12 +6619,12 @@ function card1Open(view) {
6316
6619
  const verdict = perDay >= 6 ? "that's a second full-time job. 996 who?" : perDay >= 3 ? "basically a part-time gig with the machines." : perDay >= 1 ? "a daily habit at this point." : "just getting warmed up.";
6317
6620
  const bench = benchmarkInline(view, view.rank_summary.hours_percentile);
6318
6621
  const lines = [
6319
- chalk.dim("YOU MANAGED"),
6622
+ chalk2.dim("YOU MANAGED"),
6320
6623
  "",
6321
6624
  bigNumber(` ${hours} session-hours`) + (bench ? ` ${bench}` : ""),
6322
6625
  "",
6323
- chalk.white(` ${verdict}`),
6324
- chalk.dim(" across parallel agent sessions, last 30 days")
6626
+ chalk2.white(` ${verdict}`),
6627
+ chalk2.dim(" across parallel agent sessions, last 30 days")
6325
6628
  ].join("\n");
6326
6629
  return box(lines, { borderColor: "yellow" });
6327
6630
  }
@@ -6331,7 +6634,7 @@ function cardAllTime(view) {
6331
6634
  const max = Math.max(...months.map((m) => m.duration_hours), 1);
6332
6635
  const rows = months.map((m) => {
6333
6636
  const label = monthYearShort(m.month).padEnd(6);
6334
- return ` ${chalk.dim(label)} ${bar2(m.duration_hours, max, 20)} ${chalk.dim(`${Math.round(m.duration_hours)}h`)}`;
6637
+ return ` ${chalk2.dim(label)} ${bar2(m.duration_hours, max, 20)} ${chalk2.dim(`${Math.round(m.duration_hours)}h`)}`;
6335
6638
  });
6336
6639
  const since = view.all_time.first_session ? new Date(view.all_time.first_session).toISOString().slice(0, 7) : "your first local log";
6337
6640
  const latest = months[months.length - 1];
@@ -6341,14 +6644,14 @@ function cardAllTime(view) {
6341
6644
  )[0];
6342
6645
  const trend = latest && prior && prior.duration_hours > 0 ? `${monthShort(latest.month)}: ${latest.duration_hours >= prior.duration_hours ? "+" : ""}${Math.round((latest.duration_hours - prior.duration_hours) / prior.duration_hours * 100)}% vs previous month` : latest && prior && latest.duration_hours > 0 ? `${monthShort(latest.month)}: active after a quiet month` : null;
6343
6646
  const lines = [
6344
- chalk.dim("YOUR AI CODING YEAR"),
6647
+ chalk2.dim("YOUR AI CODING YEAR"),
6345
6648
  "",
6346
6649
  ` ${bigNumber(`~${Math.round(view.all_time.total_hours).toLocaleString()} hours`)} from local logs`,
6347
- ` ${chalk.white(view.all_time.total_sessions.toLocaleString())} sessions detected since ${since}`,
6348
- ...trend ? [` ${chalk.dim(trend)}`] : [],
6650
+ ` ${chalk2.white(view.all_time.total_sessions.toLocaleString())} sessions detected since ${since}`,
6651
+ ...trend ? [` ${chalk2.dim(trend)}`] : [],
6349
6652
  "",
6350
6653
  ...rows,
6351
- best ? ` ${chalk.dim(`best local-log month: ${monthShort(best.month)} \xB7 ~${Math.round(best.duration_hours)}h`)}` : ""
6654
+ best ? ` ${chalk2.dim(`best local-log month: ${monthShort(best.month)} \xB7 ~${Math.round(best.duration_hours)}h`)}` : ""
6352
6655
  ].join("\n");
6353
6656
  return box(lines, { borderColor: "cyan" });
6354
6657
  }
@@ -6367,25 +6670,25 @@ function cardRhythm(view) {
6367
6670
  const isNightOwl = critter?.key === "night_owl";
6368
6671
  const subhead = isNightOwl ? "while the 9-5ers sleep, you ship." : weekendPct < 10 ? "locked in on weekdays, weekends are yours." : weekendPct >= 35 ? "weekends are just more reps for you." : peak !== null && peak < 9 ? "up before standup. menace." : "you keep your own hours.";
6369
6672
  const lines = [
6370
- chalk.dim("WHEN YOU CODE"),
6673
+ chalk2.dim("WHEN YOU CODE"),
6371
6674
  "",
6372
6675
  ...hourlyChart(
6373
6676
  view.hour_histogram,
6374
- critter ? { art: critter.art, color: chalk.magenta } : null
6677
+ critter ? { art: critter.art, color: chalk2.magenta } : null
6375
6678
  ),
6376
6679
  "",
6377
- ` ${chalk.white(caption)}`,
6680
+ ` ${chalk2.white(caption)}`,
6378
6681
  "",
6379
- ` ${chalk.white("weekdays".padEnd(9))} ${bar2(weekdayPct, 100, 20)} ${chalk.dim(weekdayPct + "%")}`,
6380
- ` ${chalk.white("weekends".padEnd(9))} ${bar2(weekendPct, 100, 20)} ${chalk.dim(weekendPct + "%")}`,
6682
+ ` ${chalk2.white("weekdays".padEnd(9))} ${bar2(weekdayPct, 100, 20)} ${chalk2.dim(weekdayPct + "%")}`,
6683
+ ` ${chalk2.white("weekends".padEnd(9))} ${bar2(weekendPct, 100, 20)} ${chalk2.dim(weekendPct + "%")}`,
6381
6684
  ...weekendBench ? ["", ` ${weekendBench}`] : [],
6382
6685
  ""
6383
6686
  ];
6384
6687
  if (view.rhythm_comment) {
6385
6688
  for (const l of wrapWords(view.rhythm_comment, 47))
6386
- lines.push(chalk.italic.white(" " + l));
6689
+ lines.push(chalk2.italic.white(" " + l));
6387
6690
  } else {
6388
- lines.push(chalk.dim(" " + subhead));
6691
+ lines.push(chalk2.dim(" " + subhead));
6389
6692
  }
6390
6693
  return box(lines.join("\n"), { borderColor });
6391
6694
  }
@@ -6398,10 +6701,10 @@ function cardProjects(view) {
6398
6701
  if (!usageReady(view)) return "";
6399
6702
  const projects = view.top_projects.filter((p) => p.commits > 0 || p.sessions > 0).slice(0, 3);
6400
6703
  if (projects.length === 0) return "";
6401
- const lines = [chalk.dim("YOUR TOP PROJECTS"), ""];
6704
+ const lines = [chalk2.dim("YOUR TOP PROJECTS"), ""];
6402
6705
  const c = view.contributions;
6403
6706
  if (c && c.one_liner) {
6404
- for (const l of wrapWords(c.one_liner, 50)) lines.push(chalk.dim(l));
6707
+ for (const l of wrapWords(c.one_liner, 50)) lines.push(chalk2.dim(l));
6405
6708
  lines.push("");
6406
6709
  }
6407
6710
  projects.forEach((p, i) => {
@@ -6411,14 +6714,14 @@ function cardProjects(view) {
6411
6714
  lines.push(` ${bigNumber(`\u25B8 ${name}`)} ${TITLE_GRADIENT(count)}`);
6412
6715
  if (p.blurb)
6413
6716
  for (const l of wrapWords(p.blurb, 44))
6414
- lines.push(` ${chalk.white(l)}`);
6717
+ lines.push(` ${chalk2.white(l)}`);
6415
6718
  } else {
6416
6719
  const namePart = `\u25B8 ${name}`;
6417
6720
  const pad = " ".repeat(Math.max(2, 24 - namePart.length));
6418
- lines.push(` ${chalk.white(namePart)}${pad}${chalk.dim(count)}`);
6721
+ lines.push(` ${chalk2.white(namePart)}${pad}${chalk2.dim(count)}`);
6419
6722
  if (p.blurb)
6420
6723
  for (const l of wrapWords(p.blurb, 44))
6421
- lines.push(` ${chalk.dim(l)}`);
6724
+ lines.push(` ${chalk2.dim(l)}`);
6422
6725
  }
6423
6726
  lines.push("");
6424
6727
  });
@@ -6434,17 +6737,17 @@ function card7AINative(view) {
6434
6737
  );
6435
6738
  const streak = view.streak_days;
6436
6739
  const lines = [
6437
- chalk.dim("YOU'RE AI-NATIVE"),
6740
+ chalk2.dim("YOU'RE AI-NATIVE"),
6438
6741
  "",
6439
- ` commits since 2024: ${chalk.white(view.total_commits.toLocaleString())}`,
6440
- ` AI co-authored: ${chalk.white(view.ai_assisted_commits.toLocaleString())}`,
6742
+ ` commits since 2024: ${chalk2.white(view.total_commits.toLocaleString())}`,
6743
+ ` AI co-authored: ${chalk2.white(view.ai_assisted_commits.toLocaleString())}`,
6441
6744
  "",
6442
- ` ${bar2(pct, 100, 22)} ${chalk.white(pct + "%")}${bench ? ` ${bench}` : ""}`,
6745
+ ` ${bar2(pct, 100, 22)} ${chalk2.white(pct + "%")}${bench ? ` ${bench}` : ""}`,
6443
6746
  ...streak >= 2 ? [
6444
- ` ${chalk.white(`${streak}-day streak`)}${chalk.dim(", coding without missing a day.")}`
6747
+ ` ${chalk2.white(`${streak}-day streak`)}${chalk2.dim(", coding without missing a day.")}`
6445
6748
  ] : [],
6446
6749
  "",
6447
- chalk.dim(subhead)
6750
+ chalk2.dim(subhead)
6448
6751
  ].join("\n");
6449
6752
  return box(lines, { borderColor: "yellow" });
6450
6753
  }
@@ -6457,7 +6760,7 @@ function benchmarkInline(view, percentile) {
6457
6760
  const top = topPercentNumber(percentile);
6458
6761
  if (top === null) return "";
6459
6762
  const pct = `${top}%`;
6460
- return top < 10 ? chalk.dim("(top ") + TITLE_GRADIENT(pct) + chalk.dim(" of users)") : chalk.dim(`(top ${pct} of users)`);
6763
+ return top < 10 ? chalk2.dim("(top ") + TITLE_GRADIENT(pct) + chalk2.dim(" of users)") : chalk2.dim(`(top ${pct} of users)`);
6461
6764
  }
6462
6765
  function formatTokens(n) {
6463
6766
  if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
@@ -6477,24 +6780,24 @@ function cardTokens(view) {
6477
6780
  const max = Math.max(...t.by_tool.map((x) => x.tokens), 1);
6478
6781
  const toolRows = t.by_tool.length > 0 ? t.by_tool.slice(0, 3).map((x) => {
6479
6782
  const padTool = x.tool.padEnd(13, " ");
6480
- return ` ${chalk.white(padTool)} ${bar2(x.tokens, max, 16)} ${chalk.dim(formatTokens(x.tokens))}`;
6481
- }).join("\n") : chalk.dim(" (no tool breakdown available)");
6482
- const deltaLine = t.multiplier_vs_prior !== null && t.multiplier_vs_prior >= 1.05 ? chalk.hex("#ff8a00")(
6783
+ return ` ${chalk2.white(padTool)} ${bar2(x.tokens, max, 16)} ${chalk2.dim(formatTokens(x.tokens))}`;
6784
+ }).join("\n") : chalk2.dim(" (no tool breakdown available)");
6785
+ const deltaLine = t.multiplier_vs_prior !== null && t.multiplier_vs_prior >= 1.05 ? chalk2.hex("#ff8a00")(
6483
6786
  ` \u2191 ${t.multiplier_vs_prior.toFixed(1)}\xD7 vs last period`
6484
- ) : t.multiplier_vs_prior !== null && t.multiplier_vs_prior < 0.95 ? chalk.dim(
6787
+ ) : t.multiplier_vs_prior !== null && t.multiplier_vs_prior < 0.95 ? chalk2.dim(
6485
6788
  ` \u2193 ${(1 / t.multiplier_vs_prior).toFixed(1)}\xD7 less than last period`
6486
- ) : t.total_prior_30d > 0 ? chalk.dim(` \u2248 same as last period`) : chalk.dim(` rolling 30-day window`);
6789
+ ) : t.total_prior_30d > 0 ? chalk2.dim(` \u2248 same as last period`) : chalk2.dim(` rolling 30-day window`);
6487
6790
  const cost = t.estimated_retail_cost_usd;
6488
- const costLine = cost > 0 ? ` ${chalk.dim("would have cost")} ${TITLE_GRADIENT(`~$${cost.toLocaleString()}`)} ${chalk.dim("at retail API rates")}` : "";
6489
- const cursorNote = t.cursor_estimated ? t.cursor_token_share >= 0.9 ? chalk.dim(
6791
+ const costLine = cost > 0 ? ` ${chalk2.dim("would have cost")} ${TITLE_GRADIENT(`~$${cost.toLocaleString()}`)} ${chalk2.dim("at retail API rates")}` : "";
6792
+ const cursorNote = t.cursor_estimated ? t.cursor_token_share >= 0.9 ? chalk2.dim(
6490
6793
  " \u2248 estimated from time spent in Cursor (no local token data)"
6491
- ) : chalk.dim(
6794
+ ) : chalk2.dim(
6492
6795
  " includes Cursor (tokens + cost estimated from active time)"
6493
6796
  ) : "";
6494
- const cachedNote = t.cache_tokens > t.work_tokens ? chalk.dim(" thankfully, most of them were cached :)") : t.cache_tokens > 0 ? chalk.dim(" (includes cached context, re-read each turn)") : "";
6495
- const generatedLine = t.work_tokens > 0 ? ` ${chalk.white(formatTokens(t.work_tokens))} ${chalk.dim("were actually generated fresh")}` : "";
6797
+ const cachedNote = t.cache_tokens > t.work_tokens ? chalk2.dim(" thankfully, most of them were cached :)") : t.cache_tokens > 0 ? chalk2.dim(" (includes cached context, re-read each turn)") : "";
6798
+ const generatedLine = t.work_tokens > 0 ? ` ${chalk2.white(formatTokens(t.work_tokens))} ${chalk2.dim("were actually generated fresh")}` : "";
6496
6799
  const lines = [
6497
- chalk.dim("YOU BURNED THIS MANY TOKENS"),
6800
+ chalk2.dim("YOU BURNED THIS MANY TOKENS"),
6498
6801
  "",
6499
6802
  ` ${totalLine}${tokensBench ? ` ${tokensBench}` : ""}`,
6500
6803
  "",
@@ -6516,23 +6819,23 @@ function cardToolRelationship(view) {
6516
6819
  if (r.kind === "insufficient") {
6517
6820
  return "";
6518
6821
  }
6519
- const streakLine = view.streak_days >= 2 ? ` ${chalk.white(`${view.streak_days}-day streak, coding without missing a day.`)}` : null;
6822
+ const streakLine = view.streak_days >= 2 ? ` ${chalk2.white(`${view.streak_days}-day streak, coding without missing a day.`)}` : null;
6520
6823
  if (r.kind === "switch") {
6521
6824
  const rows = r.timeline.slice(-6).map((t) => {
6522
6825
  const monthShort2 = t.month.slice(2).replace("-", "/");
6523
6826
  const filled = Math.round(t.share * 10);
6524
- const bar3 = chalk.hex("#ff8a00")("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(10 - filled));
6525
- const label = t.dominant === r.from_tool ? chalk.dim(t.dominant) : chalk.white(t.dominant);
6526
- return ` ${chalk.dim(monthShort2)} ${bar3} ${label}`;
6827
+ const bar3 = chalk2.hex("#ff8a00")("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(10 - filled));
6828
+ const label = t.dominant === r.from_tool ? chalk2.dim(t.dominant) : chalk2.white(t.dominant);
6829
+ return ` ${chalk2.dim(monthShort2)} ${bar3} ${label}`;
6527
6830
  });
6528
6831
  return box(
6529
6832
  [
6530
- chalk.dim("YOU SWITCHED TOOLS"),
6833
+ chalk2.dim("YOU SWITCHED TOOLS"),
6531
6834
  "",
6532
6835
  ...rows,
6533
6836
  "",
6534
- chalk.dim(` joined the "${r.from_tool} \u2192 ${r.to_tool}" club`),
6535
- chalk.dim(` in ${r.switch_month}.`),
6837
+ chalk2.dim(` joined the "${r.from_tool} \u2192 ${r.to_tool}" club`),
6838
+ chalk2.dim(` in ${r.switch_month}.`),
6536
6839
  ...streakLine ? ["", streakLine] : []
6537
6840
  ].join("\n"),
6538
6841
  { borderColor: "cyan" }
@@ -6541,14 +6844,14 @@ function cardToolRelationship(view) {
6541
6844
  if (r.kind === "loyalist") {
6542
6845
  return box(
6543
6846
  [
6544
- chalk.dim("YOU'RE A LOYALIST"),
6847
+ chalk2.dim("YOU'RE A LOYALIST"),
6545
6848
  "",
6546
6849
  ` ${bigNumber(r.tool.toUpperCase())}`,
6547
6850
  "",
6548
- chalk.dim(
6851
+ chalk2.dim(
6549
6852
  ` ${r.sessions_count} sessions across ${r.months_count} month${r.months_count === 1 ? "" : "s"}.`
6550
6853
  ),
6551
- chalk.dim(" no second-guessing. you knew what you wanted."),
6854
+ chalk2.dim(" no second-guessing. you knew what you wanted."),
6552
6855
  ...streakLine ? ["", streakLine] : []
6553
6856
  ].join("\n"),
6554
6857
  { borderColor: "cyan" }
@@ -6557,16 +6860,16 @@ function cardToolRelationship(view) {
6557
6860
  if (r.kind === "polyglot") {
6558
6861
  const rows = r.tools.slice(0, 4).map((t) => {
6559
6862
  const filled = Math.round(t.share * 22);
6560
- const bar3 = chalk.hex("#ff8a00")("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(22 - filled));
6561
- return ` ${chalk.white(t.tool.padEnd(12, " "))} ${bar3} ${chalk.dim(Math.round(t.share * 100) + "%")}`;
6863
+ const bar3 = chalk2.hex("#ff8a00")("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(22 - filled));
6864
+ return ` ${chalk2.white(t.tool.padEnd(12, " "))} ${bar3} ${chalk2.dim(Math.round(t.share * 100) + "%")}`;
6562
6865
  });
6563
6866
  return box(
6564
6867
  [
6565
- chalk.dim("YOU'RE A POLYGLOT"),
6868
+ chalk2.dim("YOU'RE A POLYGLOT"),
6566
6869
  "",
6567
6870
  ...rows,
6568
6871
  "",
6569
- chalk.dim(" you don't pick favorites. respect."),
6872
+ chalk2.dim(" you don't pick favorites. respect."),
6570
6873
  ...streakLine ? ["", streakLine] : []
6571
6874
  ].join("\n"),
6572
6875
  { borderColor: "cyan" }
@@ -6628,17 +6931,17 @@ function cardModelsStack(view) {
6628
6931
  const column = (mm) => {
6629
6932
  if (!mm) return [];
6630
6933
  const c = modelProviderColor(mm.prov);
6631
- const hex = (s) => chalk.hex(c)(s);
6934
+ const hex = (s) => chalk2.hex(c)(s);
6632
6935
  const cap = " " + hex("\u256D" + "\u2500".repeat(8) + "\u256E") + " ";
6633
6936
  const base = " " + hex("\u2570" + "\u2500".repeat(8) + "\u256F") + " ";
6634
6937
  const side = " " + hex("\u2502") + " ".repeat(8) + hex("\u2502") + " ";
6635
- const num3 = " " + hex("\u2502") + chalk.bold.white(center("#" + mm.rank, 8)) + hex("\u2502") + " ";
6938
+ const num3 = " " + hex("\u2502") + chalk2.bold.white(center("#" + mm.rank, 8)) + hex("\u2502") + " ";
6636
6939
  const h = heights[mm.rank];
6637
6940
  const mid = Math.floor((h - 1) / 2);
6638
6941
  const body = [];
6639
6942
  for (let i = 0; i < h; i++) body.push(i === mid ? num3 : side);
6640
- const label = mm.rank === 1 ? bigNumber(center(mm.name)) : chalk.white(center(mm.name));
6641
- return [label, chalk.dim(center(mm.pct + "%")), cap, ...body, base];
6943
+ const label = mm.rank === 1 ? bigNumber(center(mm.name)) : chalk2.white(center(mm.name));
6944
+ return [label, chalk2.dim(center(mm.pct + "%")), cap, ...body, base];
6642
6945
  };
6643
6946
  const cols = [column(second), column(first), column(third)];
6644
6947
  const maxH = Math.max(...cols.map((col) => col.length));
@@ -6646,20 +6949,20 @@ function cardModelsStack(view) {
6646
6949
  (col) => Array(maxH - col.length).fill(blankCol).concat(col)
6647
6950
  );
6648
6951
  const header = ranked.length === 1 ? "YOUR MODEL & STACK" : "YOUR MODELS & STACK";
6649
- const lines = [chalk.dim(header), ""];
6952
+ const lines = [chalk2.dim(header), ""];
6650
6953
  lines.push(
6651
- " " + [blankCol, chalk.hex("#ffd700")(center("\u265B")), blankCol].join(" ")
6954
+ " " + [blankCol, chalk2.hex("#ffd700")(center("\u265B")), blankCol].join(" ")
6652
6955
  );
6653
6956
  for (let r = 0; r < maxH; r++)
6654
6957
  lines.push(" " + [padded[0][r], padded[1][r], padded[2][r]].join(" "));
6655
6958
  lines.push("");
6656
6959
  lines.push(
6657
- ` top pick: ${chalk.white(first.name)} ${chalk.dim(`\u2014 ${first.pct}% of sessions`)}`
6960
+ ` top pick: ${chalk2.white(first.name)} ${chalk2.dim(`\u2014 ${first.pct}% of sessions`)}`
6658
6961
  );
6659
6962
  if (view.stack_comment) {
6660
6963
  lines.push("");
6661
6964
  for (const l of wrapWords(view.stack_comment, 46))
6662
- lines.push(chalk.italic.white(" " + l));
6965
+ lines.push(chalk2.italic.white(" " + l));
6663
6966
  }
6664
6967
  return box(lines.join("\n"), { borderColor: "magenta" });
6665
6968
  }
@@ -6670,25 +6973,25 @@ function cardCodeFootprint(view) {
6670
6973
  const netLabel = `${f.net >= 0 ? "+" : ""}${compactNum(f.net)}`;
6671
6974
  const subhead = f.label === "Cleaner" ? "you delete more than you add. the slop stops with you." : f.label === "Shipper" ? `${f.additive_ratio >= 0 ? Math.round(f.additive_ratio * 100) : 0}% of your churn is brand-new code.` : "you rework as much as you write. nothing ships half-baked.";
6672
6975
  const lines = [
6673
- chalk.dim("YOUR CODE FOOTPRINT"),
6976
+ chalk2.dim("YOUR CODE FOOTPRINT"),
6674
6977
  "",
6675
6978
  ` ${bigNumber(f.label.toUpperCase())}`,
6676
6979
  "",
6677
- ` ${chalk.green("+ " + compactNum(f.lines_added).padEnd(7))} ${coloredBar(f.lines_added, max, 22, "#22c55e")} ${chalk.dim("added")}`,
6678
- ` ${chalk.red("- " + compactNum(f.lines_deleted).padEnd(7))} ${coloredBar(f.lines_deleted, max, 22, "#ef4444")} ${chalk.dim("deleted")}`,
6980
+ ` ${chalk2.green("+ " + compactNum(f.lines_added).padEnd(7))} ${coloredBar(f.lines_added, max, 22, "#22c55e")} ${chalk2.dim("added")}`,
6981
+ ` ${chalk2.red("- " + compactNum(f.lines_deleted).padEnd(7))} ${coloredBar(f.lines_deleted, max, 22, "#ef4444")} ${chalk2.dim("deleted")}`,
6679
6982
  "",
6680
- ` ${chalk.white("net " + netLabel)} ${chalk.dim("lines since 2024")}`
6983
+ ` ${chalk2.white("net " + netLabel)} ${chalk2.dim("lines since 2024")}`
6681
6984
  ];
6682
6985
  if (f.median_commit_size > 0)
6683
6986
  lines.push(
6684
- ` ${chalk.dim(`typical commit ~${compactNum(f.median_commit_size)} lines \xB7 biggest ${compactNum(f.biggest_commit_size)}`)}`
6987
+ ` ${chalk2.dim(`typical commit ~${compactNum(f.median_commit_size)} lines \xB7 biggest ${compactNum(f.biggest_commit_size)}`)}`
6685
6988
  );
6686
6989
  lines.push("");
6687
6990
  if (f.line) {
6688
6991
  for (const l of wrapWords(f.line, 47))
6689
- lines.push(chalk.italic.white(" " + l));
6992
+ lines.push(chalk2.italic.white(" " + l));
6690
6993
  } else {
6691
- lines.push(chalk.dim(" " + subhead));
6994
+ lines.push(chalk2.dim(" " + subhead));
6692
6995
  }
6693
6996
  return box(lines.join("\n"), { borderColor: "green" });
6694
6997
  }
@@ -6699,20 +7002,20 @@ function cardConcurrency(view) {
6699
7002
  const longest = days >= 1.5 ? `${days.toFixed(0)} days` : `${Math.round(c.longest_session_hours)}h`;
6700
7003
  const bench = benchmarkInline(view, view.rank_summary.avg_agents_percentile);
6701
7004
  const lines = [
6702
- chalk.dim("HOW MANY AGENTS YOU JUGGLE"),
7005
+ chalk2.dim("HOW MANY AGENTS YOU JUGGLE"),
6703
7006
  "",
6704
- ` ${bigNumber(`~${c.open_tab_avg}`)} ${chalk.white("agents open at once")}${bench ? ` ${bench}` : ""}`,
7007
+ ` ${bigNumber(`~${c.open_tab_avg}`)} ${chalk2.white("agents open at once")}${bench ? ` ${bench}` : ""}`,
6705
7008
  "",
6706
- ` ${chalk.white("peak".padEnd(14))} ${chalk.dim(`${c.open_tab_peak} at once`)}`,
6707
- ` ${chalk.white("longest tab".padEnd(14))} ${chalk.dim(`${longest} open`)}`,
6708
- ` ${chalk.white("2+ active".padEnd(14))} ${chalk.dim(`${Math.round(c.active_juggle_pct * 100)}% of your coding time`)}`,
7009
+ ` ${chalk2.white("peak".padEnd(14))} ${chalk2.dim(`${c.open_tab_peak} at once`)}`,
7010
+ ` ${chalk2.white("longest tab".padEnd(14))} ${chalk2.dim(`${longest} open`)}`,
7011
+ ` ${chalk2.white("2+ active".padEnd(14))} ${chalk2.dim(`${Math.round(c.active_juggle_pct * 100)}% of your coding time`)}`,
6709
7012
  ""
6710
7013
  ];
6711
7014
  if (c.line) {
6712
7015
  for (const l of wrapWords(c.line, 47))
6713
- lines.push(chalk.italic.white(" " + l));
7016
+ lines.push(chalk2.italic.white(" " + l));
6714
7017
  } else {
6715
- lines.push(chalk.dim(" a one-agent setup could never."));
7018
+ lines.push(chalk2.dim(" a one-agent setup could never."));
6716
7019
  }
6717
7020
  return box(lines.join("\n"), { borderColor: "blue" });
6718
7021
  }
@@ -6729,22 +7032,22 @@ function cardTalk(view) {
6729
7032
  const c = view.conversation;
6730
7033
  const v = view.collaboration;
6731
7034
  if ((!c || c.total_prompts < 10) && !v) return "";
6732
- const lines = [chalk.dim("HOW YOU TALK"), ""];
7035
+ const lines = [chalk2.dim("HOW YOU TALK"), ""];
6733
7036
  if (c?.line) {
6734
7037
  for (const l of wrapWords(c.line, 47))
6735
- lines.push(chalk.italic.white(" " + l));
7038
+ lines.push(chalk2.italic.white(" " + l));
6736
7039
  lines.push("");
6737
7040
  }
6738
7041
  if (v) {
6739
7042
  lines.push(` ${bigNumber(v.style_label)}`);
6740
7043
  if (v.summary)
6741
7044
  for (const l of wrapWords(v.summary, 47))
6742
- lines.push(chalk.white(" " + l));
7045
+ lines.push(chalk2.white(" " + l));
6743
7046
  const sigs = [
6744
7047
  ["reads", v.signals.fact_checking],
6745
7048
  ["drives", v.signals.autonomy]
6746
7049
  ].filter(([, t]) => t).map(
6747
- ([label, t]) => ` ${chalk.dim(label.padEnd(8))} ${chalk.white(briefSignal(t))}`
7050
+ ([label, t]) => ` ${chalk2.dim(label.padEnd(8))} ${chalk2.white(briefSignal(t))}`
6748
7051
  );
6749
7052
  if (sigs.length > 0) {
6750
7053
  lines.push("");
@@ -6754,11 +7057,11 @@ function cardTalk(view) {
6754
7057
  if (c) {
6755
7058
  lines.push("");
6756
7059
  lines.push(
6757
- ` ${chalk.white(c.total_prompts.toLocaleString())} ${chalk.dim("prompts")} \xB7 ${chalk.white(Math.round(c.question_ratio * 100) + "%")} ${chalk.dim("questions")} \xB7 ${chalk.white("~" + c.avg_prompt_chars)} ${chalk.dim("chars")}`
7060
+ ` ${chalk2.white(c.total_prompts.toLocaleString())} ${chalk2.dim("prompts")} \xB7 ${chalk2.white(Math.round(c.question_ratio * 100) + "%")} ${chalk2.dim("questions")} \xB7 ${chalk2.white("~" + c.avg_prompt_chars)} ${chalk2.dim("chars")}`
6758
7061
  );
6759
7062
  if (c.themes.length > 0)
6760
7063
  lines.push(
6761
- ` ${chalk.dim("recurring: " + c.themes.slice(0, 4).join(", "))}`
7064
+ ` ${chalk2.dim("recurring: " + c.themes.slice(0, 4).join(", "))}`
6762
7065
  );
6763
7066
  }
6764
7067
  return box(lines.join("\n"), { borderColor: "magenta" });
@@ -6770,13 +7073,13 @@ function cardProficiency(view) {
6770
7073
  if (!p) {
6771
7074
  return box(
6772
7075
  [
6773
- chalk.dim(" you are\u2026"),
7076
+ chalk2.dim(" you are\u2026"),
6774
7077
  "",
6775
- chalk.hex("#ff8a00")(mascot),
7078
+ chalk2.hex("#ff8a00")(mascot),
6776
7079
  "",
6777
7080
  ` ${archetype}`,
6778
7081
  "",
6779
- ` ${chalk.italic.white(`"${view.zinger}"`)}`
7082
+ ` ${chalk2.italic.white(`"${view.zinger}"`)}`
6780
7083
  ].join("\n"),
6781
7084
  { borderColor: "yellow" }
6782
7085
  );
@@ -6784,27 +7087,27 @@ function cardProficiency(view) {
6784
7087
  const scoreTop = topPercentNumber(p.score_percentile ?? null);
6785
7088
  const sampleSize = view.rank_summary.sample_size;
6786
7089
  const cohort = scoreTop != null && sampleSize > 0 ? `top ${scoreTop}% of ${sampleSize.toLocaleString()} users` : view.cohort_size > 0 ? `among ${view.cohort_size.toLocaleString()} users so far` : "";
6787
- const metricRow = (label, value) => value === null ? null : ` ${chalk.white(label.padEnd(12))} ${bar2(value, 100, 10)} ${chalk.dim(String(value))}`;
7090
+ const metricRow = (label, value) => value === null ? null : ` ${chalk2.white(label.padEnd(12))} ${bar2(value, 100, 10)} ${chalk2.dim(String(value))}`;
6788
7091
  const bars = [
6789
7092
  metricRow("intensity", p.intensity),
6790
7093
  metricRow("consistency", p.consistency),
6791
- p.craft_bonus > 0 ? ` ${chalk.white("craft".padEnd(12))} ${chalk.hex("#ff8a00")(`+${p.craft_bonus}`)} ${chalk.dim("clean prompting")}` : null
7094
+ p.craft_bonus > 0 ? ` ${chalk2.white("craft".padEnd(12))} ${chalk2.hex("#ff8a00")(`+${p.craft_bonus}`)} ${chalk2.dim("clean prompting")}` : null
6792
7095
  ].filter((r) => r !== null);
6793
7096
  const zingerLines = wrapWords(`"${view.zinger}"`, INNER_WIDTH).map(
6794
- (l) => centerText(l, chalk.italic.white)
7097
+ (l) => centerText(l, chalk2.italic.white)
6795
7098
  );
6796
7099
  const commentLines = p.comment ? wrapWords(p.comment, INNER_WIDTH - 4).map(
6797
- (l, i) => i === 0 ? ` ${chalk.hex("#ff8a00")(">")} ${chalk.white(l)}` : ` ${chalk.white(l)}`
7100
+ (l, i) => i === 0 ? ` ${chalk2.hex("#ff8a00")(">")} ${chalk2.white(l)}` : ` ${chalk2.white(l)}`
6798
7101
  ) : [];
6799
7102
  const tier = tierForScore2(p.score);
6800
7103
  const lines = [
6801
- centerBlock(tier.art, chalk.hex("#ff8a00")),
7104
+ centerBlock(tier.art, chalk2.hex("#ff8a00")),
6802
7105
  "",
6803
7106
  centerText(`\u2500\u2500 ${tier.label} \u2500\u2500`, bigNumber),
6804
7107
  centerText(`${p.score} / 100`, bigNumber),
6805
- cohort ? centerText(cohort, chalk.dim) : null,
7108
+ cohort ? centerText(cohort, chalk2.dim) : null,
6806
7109
  "",
6807
- centerText(view.archetype_label, chalk.bold.hex("#ad5cff")),
7110
+ centerText(view.archetype_label, chalk2.bold.hex("#ad5cff")),
6808
7111
  ...zingerLines,
6809
7112
  "",
6810
7113
  ...bars,
@@ -6842,7 +7145,7 @@ async function renderWrappedAll(view) {
6842
7145
  " " + TITLE_GRADIENT.multiline("\u2591\u2592\u2593 YOUR AI WRAPPED \u2593\u2592\u2591") + "\n"
6843
7146
  );
6844
7147
  process.stdout.write(
6845
- chalk.dim(` ${view.name.toLowerCase()} \xB7 last 30 days
7148
+ chalk2.dim(` ${view.name.toLowerCase()} \xB7 last 30 days
6846
7149
 
6847
7150
  `)
6848
7151
  );
@@ -7065,18 +7368,18 @@ var MODE_OPTIONS = [
7065
7368
  function renderModeMenu(selected) {
7066
7369
  const out = [
7067
7370
  "",
7068
- chalk2.white(" How do you want to run Standout?"),
7371
+ chalk3.white(" How do you want to run Standout?"),
7069
7372
  ""
7070
7373
  ];
7071
7374
  MODE_OPTIONS.forEach((opt, i) => {
7072
7375
  const active = i === selected;
7073
- const pointer = active ? chalk2.hex("#ad5cff")("\u276F ") : " ";
7074
- const title = active ? chalk2.bold.white(opt.title) + chalk2.dim(opt.tag) : chalk2.dim(opt.title + opt.tag);
7376
+ const pointer = active ? chalk3.hex("#ad5cff")("\u276F ") : " ";
7377
+ const title = active ? chalk3.bold.white(opt.title) + chalk3.dim(opt.tag) : chalk3.dim(opt.title + opt.tag);
7075
7378
  out.push(`${pointer}${title}`);
7076
- for (const line of opt.lines) out.push(chalk2.dim(` ${line}`));
7379
+ for (const line of opt.lines) out.push(chalk3.dim(` ${line}`));
7077
7380
  out.push("");
7078
7381
  });
7079
- out.push(chalk2.dim(" \u2191/\u2193 to move \xB7 enter to select"));
7382
+ out.push(chalk3.dim(" \u2191/\u2193 to move \xB7 enter to select"));
7080
7383
  return out.join("\n");
7081
7384
  }
7082
7385
  async function chooseMode() {
@@ -7179,8 +7482,8 @@ function startLoadingLine(label) {
7179
7482
  let frame = 0;
7180
7483
  const render = () => {
7181
7484
  const dots = frames[frame % frames.length];
7182
- const accent = chalk2.hex("#ad5cff")(dots);
7183
- const text = chalk2.white(label);
7485
+ const accent = chalk3.hex("#ad5cff")(dots);
7486
+ const text = chalk3.white(label);
7184
7487
  process.stderr.write(`\r\x1B[2K ${accent} ${text}`);
7185
7488
  frame += 1;
7186
7489
  };
@@ -7212,7 +7515,7 @@ async function maybeShareWrapped(wrapped) {
7212
7515
  return;
7213
7516
  }
7214
7517
  const ans = await askLine(
7215
- chalk2.white(" press enter to see your ai wrapped ")
7518
+ chalk3.white(" press enter to see your ai wrapped ")
7216
7519
  );
7217
7520
  process.stderr.write("\n");
7218
7521
  const shared = !ans || ans.toLowerCase() !== "n";
@@ -7308,8 +7611,8 @@ async function runLocal() {
7308
7611
  );
7309
7612
  return;
7310
7613
  }
7311
- const file = join6(tmpdir2(), `standout-wrapped-${Date.now()}.png`);
7312
- writeFileSync(file, png);
7614
+ const file = join7(tmpdir2(), `standout-wrapped-${Date.now()}.png`);
7615
+ writeFileSync2(file, png);
7313
7616
  process.stderr.write("\n");
7314
7617
  const shown = showImageInline(png);
7315
7618
  if (!shown) {
@@ -7533,6 +7836,17 @@ async function runAgent(jobId) {
7533
7836
  async function main() {
7534
7837
  ensureHeapHeadroom();
7535
7838
  const args = process.argv.slice(2);
7839
+ if (args[0] === "schedule" || args[0] === "unschedule") {
7840
+ const action = parseScheduleArgs(args);
7841
+ if (action.kind === "install") {
7842
+ await installSchedule(action.slug, action.flags);
7843
+ } else if (action.kind === "remove") {
7844
+ await removeSchedule();
7845
+ } else {
7846
+ await scheduleStatus();
7847
+ }
7848
+ return;
7849
+ }
7536
7850
  const proxy = configureProxyFromEnv();
7537
7851
  if (proxy) process.stderr.write(` (using proxy ${proxy})
7538
7852
  `);
@@ -7558,6 +7872,7 @@ async function main() {
7558
7872
  } else {
7559
7873
  if (jobId) process.env.STANDOUT_JOB_ID = jobId;
7560
7874
  await runAgent(jobId);
7875
+ await maybeAutoInstallSchedule(jobId);
7561
7876
  }
7562
7877
  }
7563
7878
  main().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "standout",
3
- "version": "0.5.38",
3
+ "version": "0.6.0",
4
4
  "description": "Build your developer profile with AI. One command, zero friction.",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -63,5 +63,10 @@
63
63
  "license": "MIT",
64
64
  "optionalDependencies": {
65
65
  "better-sqlite3": "^12.9.0"
66
+ },
67
+ "allowScripts": {
68
+ "better-sqlite3": true,
69
+ "esbuild": true,
70
+ "fsevents": true
66
71
  }
67
72
  }