ccsidekick 1.0.0 → 1.2.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.
@@ -1023,7 +1023,13 @@ var SEP_GLYPH = "│", sanitizePackText = (s) => s.replace(/\x1b\[[0-9;?]*[ -/]*
1023
1023
  if (f.id === "model" && f.segments.length >= 2 && tail !== undefined) {
1024
1024
  const tailText = sanitizePackText(tail.text);
1025
1025
  const headText = f.segments.slice(0, -1).map((s) => sanitizePackText(s.text)).filter((t) => t !== "").join(" ");
1026
- const headBudget = Math.max(1, budget - displayWidth(tailText) - 1);
1026
+ const headBudget = budget - displayWidth(tailText) - 1;
1027
+ if (headBudget < 1) {
1028
+ return {
1029
+ id: f.id,
1030
+ segments: [{ role: "value", text: truncToWidth(fieldPlain(f), budget) }]
1031
+ };
1032
+ }
1027
1033
  return {
1028
1034
  id: f.id,
1029
1035
  segments: [
@@ -1033,6 +1039,20 @@ var SEP_GLYPH = "│", sanitizePackText = (s) => s.replace(/\x1b\[[0-9;?]*[ -/]*
1033
1039
  };
1034
1040
  }
1035
1041
  return { id: f.id, segments: [{ role: "value", text: truncToWidth(fieldPlain(f), budget) }] };
1042
+ }, fitCells = (cells, avail, sepGlyph) => {
1043
+ if (cells.length === 0 || rowPlainWidth(cells, sepGlyph) <= avail)
1044
+ return [...cells];
1045
+ const last = cells[cells.length - 1];
1046
+ if (last === undefined)
1047
+ return [...cells];
1048
+ const head = cells.slice(0, -1);
1049
+ const sepWidth = displayWidth(` ${sepGlyph} `);
1050
+ const headWidth = head.length > 0 ? displayWidth(head.map(fieldPlain).join(` ${sepGlyph} `)) : 0;
1051
+ const budget = avail - headWidth - (head.length > 0 ? sepWidth : 0);
1052
+ if (budget >= 1)
1053
+ return [...head, truncateField(last, budget)];
1054
+ const headFitted = fitCells(head, Math.max(1, avail - sepWidth - 1), sepGlyph);
1055
+ return [...headFitted, truncateField(last, 1)];
1036
1056
  }, fitRow = (row, cells, avail, sepGlyph) => {
1037
1057
  const present = [...cells];
1038
1058
  for (const id of dropOrder(row)) {
@@ -1044,15 +1064,7 @@ var SEP_GLYPH = "│", sanitizePackText = (s) => s.replace(/\x1b\[[0-9;?]*[ -/]*
1044
1064
  if (idx >= 0)
1045
1065
  present.splice(idx, 1);
1046
1066
  }
1047
- if (rowPlainWidth(present, sepGlyph) <= avail)
1048
- return present;
1049
- const last = present[present.length - 1];
1050
- if (last === undefined)
1051
- return present;
1052
- const head = present.slice(0, -1);
1053
- const headWidth = head.length > 0 ? displayWidth(head.map(fieldPlain).join(` ${sepGlyph} `)) + displayWidth(` ${sepGlyph} `) : 0;
1054
- const budget = Math.max(1, avail - headWidth);
1055
- return [...head, truncateField(last, budget)];
1067
+ return fitCells(present, avail, sepGlyph);
1056
1068
  }, colorCell = (field, lineIdx, cellIdx, input, term) => {
1057
1069
  const { theme, moodShift, mood } = input;
1058
1070
  const s = theme.statusline;
@@ -2362,22 +2374,22 @@ var init_catalog = __esm(() => {
2362
2374
  render: (i) => `Large diff: +${i.git?.insertions ?? 0}/-${i.git?.deletions ?? 0}. Review in chunks.`
2363
2375
  },
2364
2376
  {
2365
- id: "behind_upstream",
2377
+ id: "diverged",
2366
2378
  severity: "medium",
2367
2379
  category: "git",
2368
2380
  momentary: false,
2369
- template: "{behind} behind upstream. Pull before your next commit knots the merge.",
2370
- test: (i) => behind(i.git) > 0,
2371
- render: (i) => `${behind(i.git)} behind upstream. Pull before your next commit knots the merge.`
2381
+ template: "Diverged {ahead}↑ {behind}↓. `git pull --rebase` keeps history linear.",
2382
+ test: (i) => ahead(i.git) > 0 && behind(i.git) > 0,
2383
+ render: (i) => `Diverged ${ahead(i.git)}↑ ${behind(i.git)}↓. \`git pull --rebase\` keeps history linear.`
2372
2384
  },
2373
2385
  {
2374
- id: "diverged",
2386
+ id: "behind_upstream",
2375
2387
  severity: "medium",
2376
2388
  category: "git",
2377
2389
  momentary: false,
2378
- template: "Diverged {ahead}↑ {behind}↓. `git pull --rebase` keeps history linear.",
2379
- test: (i) => ahead(i.git) > 0 && behind(i.git) > 0,
2380
- render: (i) => `Diverged ${ahead(i.git)}↑ ${behind(i.git)}↓. \`git pull --rebase\` keeps history linear.`
2390
+ template: "{behind} behind upstream. Pull before your next commit knots the merge.",
2391
+ test: (i) => behind(i.git) > 0,
2392
+ render: (i) => `${behind(i.git)} behind upstream. Pull before your next commit knots the merge.`
2381
2393
  },
2382
2394
  {
2383
2395
  id: "dirty_default_branch",
@@ -3564,15 +3576,19 @@ function candidateSet(config, installed) {
3564
3576
  return ["batman"];
3565
3577
  }
3566
3578
  function derivePersona(config, state, session, installed) {
3567
- if (state.character !== undefined && state.character !== "")
3568
- return state.character;
3579
+ const candidates = candidateSet(config, installed);
3580
+ const sticky = state.character;
3581
+ if (sticky !== undefined && sticky !== "" && stickyValid(config, candidates, sticky))
3582
+ return sticky;
3569
3583
  if (config.character.mode === "fixed")
3570
3584
  return config.character.name;
3571
- const candidates = candidateSet(config, installed);
3572
3585
  const hash = createHash2("sha1").update(session).digest("hex");
3573
3586
  const idx = parseInt(hash.slice(0, 8), 16) % candidates.length;
3574
3587
  return candidates[idx] ?? "batman";
3575
3588
  }
3589
+ function stickyValid(config, candidates, sticky) {
3590
+ return config.character.mode === "fixed" ? sticky === config.character.name : candidates.includes(sticky);
3591
+ }
3576
3592
  var init_persona = () => {};
3577
3593
 
3578
3594
  // src/derived/project.ts
@@ -4007,22 +4023,24 @@ var init_load = __esm(() => {
4007
4023
  });
4008
4024
 
4009
4025
  // src/packs/registry.ts
4010
- var FIRST_PARTY_PACKS, BUNDLED_PACK = "batman";
4026
+ var PACKS;
4011
4027
  var init_registry = __esm(() => {
4012
- FIRST_PARTY_PACKS = [
4028
+ PACKS = [
4013
4029
  "barbie",
4014
4030
  "batman",
4031
+ "deadpool",
4015
4032
  "harry-potter",
4016
4033
  "hello-kitty",
4017
- "spiderman",
4018
4034
  "james-bond",
4019
- "deadpool"
4035
+ "joker",
4036
+ "pikachu",
4037
+ "sherlock-holmes",
4038
+ "spiderman"
4020
4039
  ];
4021
4040
  });
4022
4041
 
4023
4042
  // src/packs/index.ts
4024
4043
  var init_packs = __esm(() => {
4025
- init_allowlist();
4026
4044
  init_load();
4027
4045
  init_registry();
4028
4046
  });
@@ -4033,13 +4051,6 @@ import { join } from "node:path";
4033
4051
  var ccsidekickRoot = (env = process.env) => join(env["CLAUDE_CONFIG_DIR"] ?? join(homedir(), ".claude"), "ccsidekick"), sessionDir = (root, id) => join(root, "sessions", id), cacheDir = (root) => join(root, "cache"), analyticsDir = (root) => join(root, "analytics");
4034
4052
  var init_configDir = () => {};
4035
4053
 
4036
- // src/sources/storage/engineRoot.ts
4037
- import { fileURLToPath as fileURLToPath2 } from "node:url";
4038
- function engineRoot(moduleUrl) {
4039
- return fileURLToPath2(new URL("../", moduleUrl));
4040
- }
4041
- var init_engineRoot = () => {};
4042
-
4043
4054
  // src/sources/storage/atomicWrite.ts
4044
4055
  import { mkdirSync, renameSync, writeFileSync } from "node:fs";
4045
4056
  import { dirname } from "node:path";
@@ -4126,7 +4137,6 @@ var init_singleFlight = () => {};
4126
4137
  // src/sources/storage/index.ts
4127
4138
  var init_storage = __esm(() => {
4128
4139
  init_configDir();
4129
- init_engineRoot();
4130
4140
  init_atomicWrite();
4131
4141
  init_readJson();
4132
4142
  init_withLock();
@@ -5452,10 +5462,9 @@ function loadConfig(globalToml = "", projectToml = "") {
5452
5462
  const p = safeParse(projectToml);
5453
5463
  const character = section(g, p, "character");
5454
5464
  const comments = section(g, p, "comments");
5455
- const helpful = section(g, p, "helpful");
5456
- const line = section(g, p, "line");
5457
5465
  const theme = section(g, p, "theme");
5458
5466
  const network = section(g, p, "network");
5467
+ const statusline = section(g, p, "statusline");
5459
5468
  const d = DEFAULT_CONFIG;
5460
5469
  return {
5461
5470
  schema_version: numv(p["schema_version"] ?? g["schema_version"], d.schema_version),
@@ -5465,21 +5474,6 @@ function loadConfig(globalToml = "", projectToml = "") {
5465
5474
  name: str(character["name"], d.character.name),
5466
5475
  roster: stringArray(character["roster"], d.character.roster)
5467
5476
  },
5468
- comments: {
5469
- enabled: bool(comments["enabled"], d.comments.enabled)
5470
- },
5471
- helpful: {
5472
- enabled: bool(helpful["enabled"], d.helpful.enabled),
5473
- min_severity: oneOf(helpful["min_severity"], ["low", "medium", "high", "critical"], d.helpful.min_severity)
5474
- },
5475
- line: {
5476
- currency: str(line["currency"], d.line.currency),
5477
- ...typeof line["budget"] === "number" ? { budget: line["budget"] } : {},
5478
- widgets: mergeWidgets({
5479
- ...obj(obj(g["line"])["widgets"]),
5480
- ...obj(obj(p["line"])["widgets"])
5481
- })
5482
- },
5483
5477
  theme: {
5484
5478
  name: str(theme["name"], d.theme.name),
5485
5479
  ...typeof theme["statusline"] === "string" ? { statusline: theme["statusline"] } : {},
@@ -5492,10 +5486,23 @@ function loadConfig(globalToml = "", projectToml = "") {
5492
5486
  ...obj(obj(p["theme"])["icons"])
5493
5487
  })
5494
5488
  },
5489
+ comments: {
5490
+ character: bool(comments["character"], d.comments.character),
5491
+ helpful: bool(comments["helpful"], d.comments.helpful),
5492
+ min_severity: oneOf(comments["min_severity"], ["low", "medium", "high", "critical"], d.comments.min_severity)
5493
+ },
5495
5494
  network: {
5496
5495
  fx_refresh: bool(network["fx_refresh"], d.network.fx_refresh),
5497
5496
  usage_fetch: bool(network["usage_fetch"], d.network.usage_fetch),
5498
5497
  balance_path: str(network["balance_path"], d.network.balance_path)
5498
+ },
5499
+ statusline: {
5500
+ currency: str(statusline["currency"], d.statusline.currency),
5501
+ ...typeof statusline["budget"] === "number" ? { budget: statusline["budget"] } : {},
5502
+ widgets: mergeWidgets({
5503
+ ...obj(obj(g["statusline"])["widgets"]),
5504
+ ...obj(obj(p["statusline"])["widgets"])
5505
+ })
5499
5506
  }
5500
5507
  };
5501
5508
  }
@@ -5544,11 +5551,10 @@ var init_config = __esm(() => {
5544
5551
  DEFAULT_CONFIG = {
5545
5552
  schema_version: 1,
5546
5553
  character: { enabled: true, mode: "random", name: "batman", roster: [] },
5547
- comments: { enabled: true },
5548
- helpful: { enabled: true, min_severity: "low" },
5549
- line: { currency: defaultCurrency(), widgets: DEFAULT_WIDGETS },
5550
- theme: { name: "houston", banding: "solid", mood_shift: false, icons: {} },
5551
- network: { fx_refresh: true, usage_fetch: true, balance_path: "" }
5554
+ theme: { name: "character", banding: "solid", mood_shift: false, icons: {} },
5555
+ comments: { character: true, helpful: true, min_severity: "low" },
5556
+ network: { fx_refresh: true, usage_fetch: true, balance_path: "" },
5557
+ statusline: { currency: defaultCurrency(), widgets: DEFAULT_WIDGETS }
5552
5558
  };
5553
5559
  });
5554
5560
 
@@ -6569,49 +6575,14 @@ function readHelpfulEnv(cwd) {
6569
6575
  var opt3 = (key, value) => value !== undefined ? { [key]: value } : {};
6570
6576
  var init_helpfulEnv = () => {};
6571
6577
 
6572
- // src/sources/installed.ts
6573
- import { readdirSync, statSync as statSync3 } from "node:fs";
6574
- import { join as join10 } from "node:path";
6575
- function listInstalledPacks(engineDir) {
6576
- const scope = join10(engineDir, "node_modules", "@ccsidekick");
6577
- let entries;
6578
- try {
6579
- entries = readdirSync(scope, { withFileTypes: true });
6580
- } catch {
6581
- return [];
6582
- }
6583
- const ids = [];
6584
- for (const entry of entries) {
6585
- if (!entry.name.startsWith(PREFIX2) || entry.name.length <= PREFIX2.length)
6586
- continue;
6587
- if (!isDir(entry, join10(scope, entry.name)))
6588
- continue;
6589
- ids.push(entry.name.slice(PREFIX2.length));
6590
- }
6591
- return ids.sort();
6592
- }
6593
- function isDir(entry, path) {
6594
- if (entry.isDirectory())
6595
- return true;
6596
- if (!entry.isSymbolicLink())
6597
- return false;
6598
- try {
6599
- return statSync3(path).isDirectory();
6600
- } catch {
6601
- return false;
6602
- }
6603
- }
6604
- var PREFIX2 = "pack-";
6605
- var init_installed = () => {};
6606
-
6607
6578
  // src/sources/markers.ts
6608
- import { readdirSync as readdirSync2 } from "node:fs";
6579
+ import { readdirSync } from "node:fs";
6609
6580
  import { dirname as dirname4, resolve as resolve2 } from "node:path";
6610
6581
  function scanDir(dir, stacks) {
6611
6582
  let entries;
6612
6583
  let isRepoRoot = false;
6613
6584
  try {
6614
- entries = readdirSync2(dir);
6585
+ entries = readdirSync(dir);
6615
6586
  } catch {
6616
6587
  return false;
6617
6588
  }
@@ -6704,7 +6675,7 @@ var init_markers = __esm(() => {
6704
6675
  });
6705
6676
 
6706
6677
  // src/sources/modelNames.ts
6707
- import { join as join11 } from "node:path";
6678
+ import { join as join10 } from "node:path";
6708
6679
  function readModelNames(root) {
6709
6680
  return readJson(cachePath(root), {});
6710
6681
  }
@@ -6713,7 +6684,7 @@ function learnModelName(root, current, id, name) {
6713
6684
  return;
6714
6685
  atomicWrite(cachePath(root), JSON.stringify({ ...current, [id]: name }));
6715
6686
  }
6716
- var cachePath = (root) => join11(cacheDir(root), "model-names.json");
6687
+ var cachePath = (root) => join10(cacheDir(root), "model-names.json");
6717
6688
  var init_modelNames = __esm(() => {
6718
6689
  init_storage();
6719
6690
  });
@@ -6823,7 +6794,7 @@ function parsePayload(raw) {
6823
6794
  var str2 = (v) => typeof v === "string" ? v : undefined, num = (v) => typeof v === "number" ? v : undefined, bool2 = (v) => typeof v === "boolean" ? v : undefined, obj2 = (v) => v !== null && typeof v === "object" ? v : {}, opt4 = (key, value) => value !== undefined ? { [key]: value } : {};
6824
6795
 
6825
6796
  // src/sources/state.ts
6826
- import { join as join12 } from "node:path";
6797
+ import { join as join11 } from "node:path";
6827
6798
  function isObject5(v) {
6828
6799
  return typeof v === "object" && v !== null && !Array.isArray(v);
6829
6800
  }
@@ -6846,7 +6817,7 @@ function asHelpful(v) {
6846
6817
  return out;
6847
6818
  }
6848
6819
  function readState(sessionDir2) {
6849
- const raw = readJson(join12(sessionDir2, STATE_FILE), undefined);
6820
+ const raw = readJson(join11(sessionDir2, STATE_FILE), undefined);
6850
6821
  if (!isObject5(raw))
6851
6822
  return EMPTY2;
6852
6823
  const character = raw["character"];
@@ -6876,7 +6847,7 @@ function mergeState(disk, next) {
6876
6847
  };
6877
6848
  }
6878
6849
  function writeState(sessionDir2, s) {
6879
- const path = join12(sessionDir2, STATE_FILE);
6850
+ const path = join11(sessionDir2, STATE_FILE);
6880
6851
  withLock(`${path}.lock`, () => {
6881
6852
  atomicWrite(path, JSON.stringify(mergeState(readState(sessionDir2), s)));
6882
6853
  }, () => {});
@@ -6888,8 +6859,8 @@ var init_state = __esm(() => {
6888
6859
  });
6889
6860
 
6890
6861
  // src/sources/transcript.ts
6891
- import { readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
6892
- import { basename as basename2, dirname as dirname5, join as join13 } from "node:path";
6862
+ import { readFileSync as readFileSync8, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
6863
+ import { basename as basename2, dirname as dirname5, join as join12 } from "node:path";
6893
6864
  function parseTs(s) {
6894
6865
  if (s === undefined)
6895
6866
  return;
@@ -7110,7 +7081,7 @@ function reconstructTodos(lines) {
7110
7081
  }
7111
7082
  function statSafe(p) {
7112
7083
  try {
7113
- const s = statSync4(p);
7084
+ const s = statSync3(p);
7114
7085
  return { mtimeMs: s.mtimeMs, size: s.size };
7115
7086
  } catch {
7116
7087
  return null;
@@ -7197,7 +7168,7 @@ function repoRootForCwd(cwd) {
7197
7168
  let result = cwd;
7198
7169
  while (dir !== "" && dir !== dirname5(dir)) {
7199
7170
  try {
7200
- if (statSync4(join13(dir, ".git")).isDirectory()) {
7171
+ if (statSync3(join12(dir, ".git")).isDirectory()) {
7201
7172
  result = dir;
7202
7173
  break;
7203
7174
  }
@@ -7210,15 +7181,15 @@ function repoRootForCwd(cwd) {
7210
7181
  function* walkTree(dir, encodedDir) {
7211
7182
  let entries;
7212
7183
  try {
7213
- entries = readdirSync3(dir);
7184
+ entries = readdirSync2(dir);
7214
7185
  } catch {
7215
7186
  return;
7216
7187
  }
7217
7188
  for (const name of entries) {
7218
- const full = join13(dir, name);
7189
+ const full = join12(dir, name);
7219
7190
  let st;
7220
7191
  try {
7221
- st = statSync4(full);
7192
+ st = statSync3(full);
7222
7193
  } catch {
7223
7194
  continue;
7224
7195
  }
@@ -7232,12 +7203,12 @@ function* walkTree(dir, encodedDir) {
7232
7203
  function* walkJsonl(root) {
7233
7204
  let dirs;
7234
7205
  try {
7235
- dirs = readdirSync3(root);
7206
+ dirs = readdirSync2(root);
7236
7207
  } catch {
7237
7208
  return;
7238
7209
  }
7239
7210
  for (const encodedDir of dirs) {
7240
- yield* walkTree(join13(root, encodedDir), encodedDir);
7211
+ yield* walkTree(join12(root, encodedDir), encodedDir);
7241
7212
  }
7242
7213
  }
7243
7214
  function scanBounds(lines) {
@@ -7392,7 +7363,6 @@ var init_sources = __esm(() => {
7392
7363
  init_fx();
7393
7364
  init_git();
7394
7365
  init_helpfulEnv();
7395
- init_installed();
7396
7366
  init_markers();
7397
7367
  init_modelNames();
7398
7368
  init_oauthUsage();
@@ -7402,15 +7372,15 @@ var init_sources = __esm(() => {
7402
7372
  });
7403
7373
 
7404
7374
  // src/cli/gc.ts
7405
- import { existsSync as existsSync2, readdirSync as readdirSync4, rmSync, statSync as statSync5 } from "node:fs";
7406
- import { join as join14 } from "node:path";
7375
+ import { existsSync as existsSync2, readdirSync as readdirSync3, rmSync, statSync as statSync4 } from "node:fs";
7376
+ import { join as join13 } from "node:path";
7407
7377
  function newestMtime(dir) {
7408
7378
  let newest = 0;
7409
7379
  try {
7410
- newest = statSync5(dir).mtimeMs;
7411
- for (const name of readdirSync4(dir)) {
7380
+ newest = statSync4(dir).mtimeMs;
7381
+ for (const name of readdirSync3(dir)) {
7412
7382
  try {
7413
- const m = statSync5(join14(dir, name)).mtimeMs;
7383
+ const m = statSync4(join13(dir, name)).mtimeMs;
7414
7384
  if (m > newest)
7415
7385
  newest = m;
7416
7386
  } catch {}
@@ -7419,18 +7389,18 @@ function newestMtime(dir) {
7419
7389
  return newest;
7420
7390
  }
7421
7391
  function pruneSessions(root, now) {
7422
- const sessions = join14(root, "sessions");
7392
+ const sessions = join13(root, "sessions");
7423
7393
  let names;
7424
7394
  try {
7425
- names = readdirSync4(sessions);
7395
+ names = readdirSync3(sessions);
7426
7396
  } catch {
7427
7397
  return;
7428
7398
  }
7429
7399
  const cutoff = now - SESSION_TTL_DAYS * DAY_MS;
7430
7400
  for (const name of names) {
7431
- const dir = join14(sessions, name);
7401
+ const dir = join13(sessions, name);
7432
7402
  try {
7433
- if (!statSync5(dir).isDirectory())
7403
+ if (!statSync4(dir).isDirectory())
7434
7404
  continue;
7435
7405
  } catch {
7436
7406
  continue;
@@ -7469,7 +7439,7 @@ var init_gc = __esm(() => {
7469
7439
 
7470
7440
  // src/cli/render.ts
7471
7441
  import { readFileSync as readFileSync9 } from "node:fs";
7472
- import { dirname as dirname6, join as join15 } from "node:path";
7442
+ import { dirname as dirname6, join as join14 } from "node:path";
7473
7443
  function readTextSafe(path) {
7474
7444
  try {
7475
7445
  return readFileSync9(path, "utf8");
@@ -7506,13 +7476,12 @@ function applyThemeIcons(fields, theme, config) {
7506
7476
  };
7507
7477
  });
7508
7478
  }
7509
- function readGated(overrides, envInputs, config, root, dir, markers, sessionState, clock) {
7479
+ function readGated(overrides, envInputs, config, root, dir, markers, clock) {
7510
7480
  const creds = overrides?.creds !== undefined ? overrides.creds : envInputs.hasApiKey || config.network.usage_fetch ? readCreds() : null;
7511
7481
  const usage = overrides?.usage !== undefined ? overrides.usage : config.network.usage_fetch ? readUsageCached(root) : null;
7512
7482
  const balance = overrides?.balance !== undefined ? overrides.balance : config.network.balance_path !== "" ? readBalance(config.network.balance_path, clock) : null;
7513
7483
  const helpfulEnv = needsHelpfulEnv(markers) ? readHelpfulEnv(dir) : EMPTY_HELPFUL_ENV;
7514
- const installed = sessionState.character === undefined && config.character.mode === "random" && config.character.roster.length === 0 ? listInstalledPacks(engineRoot(import.meta.url)) : [];
7515
- return { creds, usage, balance, helpfulEnv, installed };
7484
+ return { creds, usage, balance, helpfulEnv };
7516
7485
  }
7517
7486
  function lookupPackTheme(name) {
7518
7487
  const loaded = loadPack(name);
@@ -7539,10 +7508,10 @@ function build(stdin, env, term, clock, overrides) {
7539
7508
  return { line: "", persist: NOOP };
7540
7509
  const root = ccsidekickRoot(env);
7541
7510
  const base = dirname6(root);
7542
- const projectsRoot = join15(base, "projects");
7511
+ const projectsRoot = join14(base, "projects");
7543
7512
  const dir = payload.workspace.current_dir ?? payload.cwd ?? process.cwd();
7544
- const globalToml = readTextSafe(join15(root, "config.toml"));
7545
- const projectToml = readTextSafe(join15(dir, ".ccsidekick", "config.toml"));
7513
+ const globalToml = readTextSafe(join14(root, "config.toml"));
7514
+ const projectToml = readTextSafe(join14(dir, ".ccsidekick", "config.toml"));
7546
7515
  const config = loadConfig(globalToml, projectToml);
7547
7516
  const envInputs = readEnv(env);
7548
7517
  const aliases = readModelAliases(env);
@@ -7557,8 +7526,8 @@ function build(stdin, env, term, clock, overrides) {
7557
7526
  const attribution = readAttribution(root);
7558
7527
  const costCache = readCostCache(root);
7559
7528
  const fxTable = readFxCached(root);
7560
- const { creds, usage, balance, helpfulEnv, installed } = readGated(overrides, envInputs, config, root, dir, markers, sessionState, clock);
7561
- const persona = derivePersona(config, sessionState, session, installed);
7529
+ const { creds, usage, balance, helpfulEnv } = readGated(overrides, envInputs, config, root, dir, markers, clock);
7530
+ const persona = derivePersona(config, sessionState, session, PACKS);
7562
7531
  const loaded = loadPack(persona);
7563
7532
  const pack = loaded.ok ? loaded.pack : null;
7564
7533
  const project = deriveProject(git, payload);
@@ -7592,8 +7561,11 @@ function build(stdin, env, term, clock, overrides) {
7592
7561
  git,
7593
7562
  payload,
7594
7563
  scan,
7595
- widgets: config.line.widgets,
7596
- currency: { code: config.line.currency, rate: fxTable[config.line.currency] ?? 0 },
7564
+ widgets: config.statusline.widgets,
7565
+ currency: {
7566
+ code: config.statusline.currency,
7567
+ rate: fxTable[config.statusline.currency] ?? 0
7568
+ },
7597
7569
  homeDir: env["HOME"] ?? ""
7598
7570
  };
7599
7571
  const composed = composeStatusline(composeInputs);
@@ -7611,7 +7583,7 @@ function build(stdin, env, term, clock, overrides) {
7611
7583
  creds,
7612
7584
  balance
7613
7585
  };
7614
- const helpfulResult = config.helpful.enabled ? resolveHelpful(helpfulInputs, sessionState, clock, config.helpful.min_severity) : { comment: null, nextHelpful: sessionState.helpful };
7586
+ const helpfulResult = config.comments.helpful ? resolveHelpful(helpfulInputs, sessionState, clock, config.comments.min_severity) : { comment: null, nextHelpful: sessionState.helpful };
7615
7587
  const helpful = helpfulResult.comment;
7616
7588
  const pending = pendingMilestones(familiarity, clock);
7617
7589
  const charBase = {
@@ -7632,7 +7604,7 @@ function build(stdin, env, term, clock, overrides) {
7632
7604
  state: sessionState,
7633
7605
  clock,
7634
7606
  session,
7635
- config: { enabled: config.comments.enabled }
7607
+ config: { enabled: config.comments.character }
7636
7608
  });
7637
7609
  } catch {
7638
7610
  charResult = { comment: null, nextState: charBase };
@@ -7728,8 +7700,8 @@ var init_render2 = __esm(() => {
7728
7700
  });
7729
7701
 
7730
7702
  // src/cli/settings.ts
7731
- import { existsSync as existsSync3, readFileSync as readFileSync10, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
7732
- import { basename as basename3, dirname as dirname7, join as join16 } from "node:path";
7703
+ import { existsSync as existsSync3, readFileSync as readFileSync10, readdirSync as readdirSync4, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
7704
+ import { basename as basename3, dirname as dirname7, join as join15 } from "node:path";
7733
7705
  function asRecord(v) {
7734
7706
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
7735
7707
  }
@@ -7753,9 +7725,9 @@ function isOurClassifyEntry(entry, classifyCmd) {
7753
7725
  function pruneBackups(settingsPath) {
7754
7726
  const dir = dirname7(settingsPath);
7755
7727
  const prefix = backupPrefix(settingsPath);
7756
- const baks = readdirSync5(dir).filter((f) => f.startsWith(prefix)).map((f) => ({ name: f, epoch: Number(f.slice(prefix.length)) })).filter((b) => Number.isFinite(b.epoch)).sort((a, b) => a.epoch - b.epoch);
7728
+ const baks = readdirSync4(dir).filter((f) => f.startsWith(prefix)).map((f) => ({ name: f, epoch: Number(f.slice(prefix.length)) })).filter((b) => Number.isFinite(b.epoch)).sort((a, b) => a.epoch - b.epoch);
7757
7729
  for (const b of baks.slice(1, -1))
7758
- rmSync2(join16(dir, b.name), { force: true });
7730
+ rmSync2(join15(dir, b.name), { force: true });
7759
7731
  }
7760
7732
  function safeWriteJson(path, text, restoreText) {
7761
7733
  const tmp = `${path}.tmp.${String(process.pid)}.${Math.random().toString(36).slice(2)}`;
@@ -7810,7 +7782,7 @@ function installSettings(opts) {
7810
7782
  `, originalText);
7811
7783
  }
7812
7784
  function writeConfigToml(root, config) {
7813
- atomicWrite(join16(root, "config.toml"), stringify(config));
7785
+ atomicWrite(join15(root, "config.toml"), stringify(config));
7814
7786
  }
7815
7787
  var MATCHER = "Bash|Edit|Write|NotebookEdit|Read|Grep|Glob|WebFetch|WebSearch|Agent|TaskCreate|TaskUpdate|Task|Skill|TodoWrite", HOOK_EVENTS, backupPrefix = (settingsPath) => `${basename3(settingsPath)}.ccsidekick-bak.`;
7816
7788
  var init_settings = __esm(() => {
@@ -7820,8 +7792,260 @@ var init_settings = __esm(() => {
7820
7792
  HOOK_EVENTS = ["PostToolUse", "PostToolUseFailure", "PostToolBatch"];
7821
7793
  });
7822
7794
 
7795
+ // src/cli/setup.ts
7796
+ import { readFileSync as readFileSync11 } from "node:fs";
7797
+ import { join as join16 } from "node:path";
7798
+ function themeNames() {
7799
+ return [CHARACTER_THEME, ...Object.keys(THEMES), ...PACKS];
7800
+ }
7801
+ function listValues(kind) {
7802
+ if (kind === "characters")
7803
+ return PACKS;
7804
+ if (kind === "themes")
7805
+ return themeNames();
7806
+ if (kind === "widgets")
7807
+ return WIDGET_IDS;
7808
+ return null;
7809
+ }
7810
+ function tokenize2(argv) {
7811
+ const pairs = new Map;
7812
+ const bools = new Set;
7813
+ const errors = [];
7814
+ for (let i = 0;i < argv.length; i++) {
7815
+ const tok = argv[i] ?? "";
7816
+ if (!tok.startsWith("--")) {
7817
+ errors.push(`ccsidekick: unexpected argument "${tok}"`);
7818
+ continue;
7819
+ }
7820
+ const body = tok.slice(2);
7821
+ const eq = body.indexOf("=");
7822
+ const key = eq >= 0 ? body.slice(0, eq) : body;
7823
+ if (BOOL_FLAGS.has(key)) {
7824
+ bools.add(key);
7825
+ continue;
7826
+ }
7827
+ if (!VALUE_FLAGS.has(key)) {
7828
+ errors.push(`ccsidekick: unknown flag "--${key}"`);
7829
+ continue;
7830
+ }
7831
+ if (eq >= 0) {
7832
+ pairs.set(key, body.slice(eq + 1));
7833
+ continue;
7834
+ }
7835
+ const next = argv[i + 1];
7836
+ if (next === undefined || next.startsWith("--")) {
7837
+ errors.push(`ccsidekick: --${key} needs a value`);
7838
+ continue;
7839
+ }
7840
+ pairs.set(key, next);
7841
+ i++;
7842
+ }
7843
+ return { pairs, bools, errors };
7844
+ }
7845
+ function enumInto(value, valid, flag, errors, set) {
7846
+ if (memberOf(value, valid))
7847
+ set(value);
7848
+ else
7849
+ errors.push(invalid(flag, value, valid));
7850
+ }
7851
+ function listInto(value, valid, flag, errors, set) {
7852
+ const list = splitList(value);
7853
+ const bad = list.filter((x) => !memberOf(x, valid));
7854
+ if (bad.length > 0)
7855
+ errors.push(invalid(flag, bad.join(","), valid));
7856
+ else
7857
+ set(list);
7858
+ }
7859
+ function parseSetup(argv, homeDir, env) {
7860
+ const { pairs, bools, errors } = tokenize2(argv);
7861
+ const flags = {};
7862
+ for (const [key, value] of pairs)
7863
+ VALIDATORS[key]?.(value, flags, errors);
7864
+ if (bools.has("global") && bools.has("local"))
7865
+ errors.push("ccsidekick: pass only one of --global / --local");
7866
+ const scope = bools.has("local") ? "local" : "global";
7867
+ const dir = pairs.get("config-dir") ?? env["CLAUDE_CONFIG_DIR"] ?? join16(homeDir, ".claude");
7868
+ return { flags, target: { scope, dir }, errors };
7869
+ }
7870
+ function applySetup(base, flags) {
7871
+ const mode = flags.mode ?? (flags.character !== undefined ? "fixed" : base.character.mode);
7872
+ const character = {
7873
+ ...base.character,
7874
+ mode,
7875
+ ...flags.character !== undefined ? { name: flags.character } : {},
7876
+ ...flags.roster !== undefined ? { roster: flags.roster } : {}
7877
+ };
7878
+ const statusline = {
7879
+ ...base.statusline,
7880
+ ...flags.currency !== undefined ? { currency: flags.currency } : {},
7881
+ ...flags.budget !== undefined ? { budget: flags.budget } : {},
7882
+ ...flags.widgets !== undefined ? {
7883
+ widgets: Object.fromEntries(WIDGET_IDS.map((id) => [id, flags.widgets?.includes(id) ?? false]))
7884
+ } : {}
7885
+ };
7886
+ return {
7887
+ ...base,
7888
+ character,
7889
+ statusline,
7890
+ comments: {
7891
+ ...base.comments,
7892
+ ...flags.comments !== undefined ? { character: flags.comments } : {},
7893
+ ...flags.helpful !== undefined ? { helpful: flags.helpful } : {},
7894
+ ...flags.minSeverity !== undefined ? { min_severity: flags.minSeverity } : {}
7895
+ },
7896
+ theme: flags.theme !== undefined ? { ...base.theme, name: flags.theme } : base.theme
7897
+ };
7898
+ }
7899
+ function existingConfigPath(target, cwd) {
7900
+ return target.scope === "global" ? join16(target.dir, "ccsidekick", "config.toml") : join16(cwd, ".ccsidekick", "config.toml");
7901
+ }
7902
+ function runSetup(argv, deps) {
7903
+ const parsed = parseSetup(argv, deps.homeDir, deps.env);
7904
+ if (parsed.errors.length > 0) {
7905
+ for (const e of parsed.errors)
7906
+ deps.err(`${e}
7907
+ `);
7908
+ return 1;
7909
+ }
7910
+ const existingText = deps.readConfig(existingConfigPath(parsed.target, deps.cwd));
7911
+ const base = existingText !== null ? loadConfig(existingText) : DEFAULT_CONFIG;
7912
+ const config = applySetup(base, parsed.flags);
7913
+ try {
7914
+ deps.save(config, parsed.target.scope, parsed.target.dir, deps.renderBin, {
7915
+ cwd: deps.cwd,
7916
+ wireLocalSettings: parsed.target.scope === "local"
7917
+ });
7918
+ } catch (e) {
7919
+ deps.err(`ccsidekick: ${e instanceof Error ? e.message : String(e)}
7920
+ `);
7921
+ return 1;
7922
+ }
7923
+ deps.out(`ccsidekick: configured ${config.character.name} (${config.character.mode}), theme ${config.theme.name}. ` + `Wired ${parsed.target.scope} at ${parsed.target.dir}.
7924
+ `);
7925
+ return 0;
7926
+ }
7927
+ function runList(kind, out, err) {
7928
+ const values = kind === undefined ? null : listValues(kind);
7929
+ if (values === null) {
7930
+ err(`ccsidekick: list expects one of: characters, themes, widgets
7931
+ `);
7932
+ return 1;
7933
+ }
7934
+ out(`${values.join(`
7935
+ `)}
7936
+ `);
7937
+ return 0;
7938
+ }
7939
+ function setupHelp() {
7940
+ return [
7941
+ "ccsidekick setup — configure and wire ccsidekick without the TUI",
7942
+ "",
7943
+ "Usage: ccsidekick setup [flags]",
7944
+ "",
7945
+ "Flags (only the ones you pass are applied):",
7946
+ ` --character <name> ${PACKS.join(", ")}`,
7947
+ ` --mode <mode> ${MODES.join(", ")}`,
7948
+ " --roster <a,b,c> characters for random mode (from --character's list)",
7949
+ ` --theme <name> ${themeNames().join(", ")}`,
7950
+ " --currency <code> e.g. USD, EUR, INR",
7951
+ " --budget <usd> monthly budget, a number >= 0",
7952
+ " --comments <on|off> the character's own comment line",
7953
+ " --helpful <on|off> the helpful-tip line",
7954
+ ` --min-severity <sev> ${SEVERITIES.join(", ")}`,
7955
+ " --widgets <a,b,c> statusline widgets to enable (others are turned off)",
7956
+ " --global | --local save target (default: global)",
7957
+ " --config-dir <path> Claude config dir (default: $CLAUDE_CONFIG_DIR or ~/.claude)",
7958
+ "",
7959
+ "List valid values for scripting: ccsidekick list characters|themes|widgets",
7960
+ ""
7961
+ ].join(`
7962
+ `);
7963
+ }
7964
+ function defaultReadConfig(path) {
7965
+ try {
7966
+ return readFileSync11(path, "utf8");
7967
+ } catch {
7968
+ return null;
7969
+ }
7970
+ }
7971
+ var WIDGET_IDS, MODES, SEVERITIES, VALUE_FLAGS, BOOL_FLAGS, splitList = (raw) => raw.split(",").map((s) => s.trim()).filter((s) => s !== ""), invalid = (flag, value, valid) => `ccsidekick: invalid --${flag} "${value}". Valid: ${valid.join(", ")}`, parseOnOff = (flag, value, errors) => {
7972
+ if (value === "on")
7973
+ return true;
7974
+ if (value === "off")
7975
+ return false;
7976
+ errors.push(invalid(flag, value, ["on", "off"]));
7977
+ return;
7978
+ }, memberOf = (value, valid) => valid.includes(value), VALIDATORS;
7979
+ var init_setup = __esm(() => {
7980
+ init_data();
7981
+ init_packs();
7982
+ init_render();
7983
+ init_sources();
7984
+ WIDGET_IDS = Object.keys(DEFAULT_CONFIG.statusline.widgets);
7985
+ MODES = ["fixed", "random"];
7986
+ SEVERITIES = ["low", "medium", "high", "critical"];
7987
+ VALUE_FLAGS = new Set([
7988
+ "character",
7989
+ "mode",
7990
+ "roster",
7991
+ "theme",
7992
+ "currency",
7993
+ "budget",
7994
+ "comments",
7995
+ "helpful",
7996
+ "min-severity",
7997
+ "widgets",
7998
+ "config-dir"
7999
+ ]);
8000
+ BOOL_FLAGS = new Set(["global", "local"]);
8001
+ VALIDATORS = {
8002
+ character: (v, f, e) => {
8003
+ enumInto(v, PACKS, "character", e, (x) => f.character = x);
8004
+ },
8005
+ mode: (v, f, e) => {
8006
+ enumInto(v, MODES, "mode", e, (x) => f.mode = x);
8007
+ },
8008
+ roster: (v, f, e) => {
8009
+ listInto(v, PACKS, "roster", e, (x) => f.roster = x);
8010
+ },
8011
+ theme: (v, f, e) => {
8012
+ enumInto(v, themeNames(), "theme", e, (x) => f.theme = x);
8013
+ },
8014
+ currency: (v, f, e) => {
8015
+ const u = v.trim().toUpperCase();
8016
+ if (u === "")
8017
+ e.push("ccsidekick: --currency needs a code");
8018
+ else
8019
+ f.currency = u;
8020
+ },
8021
+ budget: (v, f, e) => {
8022
+ const n = Number(v);
8023
+ if (Number.isFinite(n) && n >= 0)
8024
+ f.budget = n;
8025
+ else
8026
+ e.push(`ccsidekick: invalid --budget "${v}" (want a number >= 0)`);
8027
+ },
8028
+ comments: (v, f, e) => {
8029
+ const b = parseOnOff("comments", v, e);
8030
+ if (b !== undefined)
8031
+ f.comments = b;
8032
+ },
8033
+ helpful: (v, f, e) => {
8034
+ const b = parseOnOff("helpful", v, e);
8035
+ if (b !== undefined)
8036
+ f.helpful = b;
8037
+ },
8038
+ "min-severity": (v, f, e) => {
8039
+ enumInto(v, SEVERITIES, "min-severity", e, (x) => f.minSeverity = x);
8040
+ },
8041
+ widgets: (v, f, e) => {
8042
+ listInto(v, WIDGET_IDS, "widgets", e, (x) => f.widgets = x);
8043
+ }
8044
+ };
8045
+ });
8046
+
7823
8047
  // src/cli/uninstall.ts
7824
- import { existsSync as existsSync4, readFileSync as readFileSync11, readdirSync as readdirSync6 } from "node:fs";
8048
+ import { existsSync as existsSync4, readFileSync as readFileSync12, readdirSync as readdirSync5 } from "node:fs";
7825
8049
  import { basename as basename4, dirname as dirname8, join as join17 } from "node:path";
7826
8050
  function asRecord2(v) {
7827
8051
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
@@ -7857,7 +8081,7 @@ function restoreNewestBackup(settingsPath) {
7857
8081
  const dir = dirname8(settingsPath);
7858
8082
  const prefix = `${basename4(settingsPath)}.ccsidekick-bak.`;
7859
8083
  let newest;
7860
- for (const f of readdirSync6(dir)) {
8084
+ for (const f of readdirSync5(dir)) {
7861
8085
  if (!f.startsWith(prefix))
7862
8086
  continue;
7863
8087
  const epoch = Number(f.slice(prefix.length));
@@ -7868,7 +8092,7 @@ function restoreNewestBackup(settingsPath) {
7868
8092
  }
7869
8093
  if (newest === undefined)
7870
8094
  return null;
7871
- atomicWrite(settingsPath, readFileSync11(join17(dir, newest.name), "utf8"));
8095
+ atomicWrite(settingsPath, readFileSync12(join17(dir, newest.name), "utf8"));
7872
8096
  return newest.name;
7873
8097
  }
7874
8098
  function runRestore(settingsPath, emit) {
@@ -7922,7 +8146,7 @@ function runUninstall(opts) {
7922
8146
  return;
7923
8147
  }
7924
8148
  if (existsSync4(settingsPath)) {
7925
- const parsed = parseJsonObject2(readFileSync11(settingsPath, "utf8"));
8149
+ const parsed = parseJsonObject2(readFileSync12(settingsPath, "utf8"));
7926
8150
  if (parsed === null) {
7927
8151
  throw new Error(`ccsidekick: refusing to modify unparseable settings at ${settingsPath}`);
7928
8152
  }
@@ -7945,17 +8169,18 @@ var init_uninstall = __esm(() => {
7945
8169
  var init_cli = __esm(() => {
7946
8170
  init_render2();
7947
8171
  init_settings();
8172
+ init_setup();
7948
8173
  init_uninstall();
7949
8174
  });
7950
8175
 
7951
8176
  // src/tui/configDirs.ts
7952
- import { existsSync as existsSync5, readdirSync as readdirSync7 } from "node:fs";
8177
+ import { existsSync as existsSync5, readdirSync as readdirSync6 } from "node:fs";
7953
8178
  import { join as join18 } from "node:path";
7954
8179
  function discoverConfigDirs(homeDir, suggested) {
7955
8180
  const home = join18(homeDir, ".claude");
7956
8181
  const set = new Set([home]);
7957
8182
  try {
7958
- for (const entry of readdirSync7(homeDir, { withFileTypes: true })) {
8183
+ for (const entry of readdirSync6(homeDir, { withFileTypes: true })) {
7959
8184
  if (entry.isDirectory() && entry.name.startsWith(".claude")) {
7960
8185
  set.add(join18(homeDir, entry.name));
7961
8186
  }
@@ -8009,13 +8234,6 @@ function defaultResolveVerbs(name) {
8009
8234
  const loaded = loadPack(name);
8010
8235
  return loaded.ok ? loaded.pack.spinnerVerbs : [];
8011
8236
  }
8012
- function defaultInstalled() {
8013
- try {
8014
- return listInstalledPacks(engineRoot(import.meta.url));
8015
- } catch {
8016
- return [];
8017
- }
8018
- }
8019
8237
  function spinnerVerbUnion(config, resolveVerbs, installed) {
8020
8238
  const candidates = config.character.mode === "fixed" ? [config.character.name] : config.character.roster.length > 0 ? [...config.character.roster] : [...installed];
8021
8239
  const seen = new Set;
@@ -8035,7 +8253,7 @@ function normalize(config) {
8035
8253
  }
8036
8254
  function save(config, scope, dir, renderBin, opts = {}) {
8037
8255
  const resolveVerbs = opts.resolveVerbs ?? defaultResolveVerbs;
8038
- const installed = opts.installed ?? defaultInstalled();
8256
+ const installed = opts.installed ?? PACKS;
8039
8257
  const cwd = opts.cwd ?? process.cwd();
8040
8258
  const normalized = normalize(config);
8041
8259
  const spinnerVerbs = spinnerVerbUnion(normalized, resolveVerbs, installed);
@@ -8089,13 +8307,14 @@ var init_keymap_data = __esm(() => {
8089
8307
  KEYMAP = [
8090
8308
  { keys: "w a s d", label: "move (also ↑↓←→, h j k l)", group: "Navigate" },
8091
8309
  { keys: "tab", label: "sidebar / content", group: "Navigate" },
8092
- { keys: "1-8", label: "jump to a section", group: "Navigate" },
8310
+ { keys: "1-7", label: "jump to a section", group: "Navigate" },
8093
8311
  { keys: "↵", label: "open, select, toggle", group: "Navigate" },
8094
8312
  { keys: "esc", label: "back, close, quit", group: "Navigate" },
8095
8313
  { keys: "/", label: "find", group: "Find & preview" },
8096
8314
  { keys: "?", label: "help", group: "Find & preview" },
8097
8315
  { keys: "ctrl+p", label: "preview", group: "Find & preview" },
8098
8316
  { keys: "ctrl+s", label: "save & install", group: "Actions" },
8317
+ { keys: "ctrl+w", label: "switch to wizard", group: "Actions" },
8099
8318
  { keys: "q", label: "quit", group: "Actions" }
8100
8319
  ];
8101
8320
  });
@@ -8145,7 +8364,7 @@ function dispatchCommand(state, ev, dirty2) {
8145
8364
  if (key.tab === true) {
8146
8365
  return stay({ ...state, zone: state.zone === "sidebar" ? "content" : "sidebar" });
8147
8366
  }
8148
- if (/^[1-8]$/.test(input)) {
8367
+ if (/^[1-7]$/.test(input)) {
8149
8368
  return stay({ ...state, section: Number(input) - 1, zone: "sidebar" });
8150
8369
  }
8151
8370
  return null;
@@ -8212,6 +8431,7 @@ function hintsFor(state) {
8212
8431
  { key: "/", label: "find" },
8213
8432
  { key: "^p", label: "preview" },
8214
8433
  { key: "^s", label: "save" },
8434
+ { key: "^w", label: "wizard" },
8215
8435
  { key: "?", label: "help" },
8216
8436
  { key: "q", label: "quit" }
8217
8437
  ];
@@ -8222,6 +8442,7 @@ function hintsFor(state) {
8222
8442
  { key: "/", label: "find" },
8223
8443
  { key: "^p", label: "preview" },
8224
8444
  { key: "^s", label: "save" },
8445
+ { key: "^w", label: "wizard" },
8225
8446
  { key: "?", label: "help" },
8226
8447
  { key: "q", label: "quit" }
8227
8448
  ];
@@ -8231,8 +8452,7 @@ var init_keymap = __esm(() => {
8231
8452
  SECTIONS = [
8232
8453
  "Character",
8233
8454
  "Theme",
8234
- "Voice",
8235
- "Tips",
8455
+ "Comments",
8236
8456
  "Network",
8237
8457
  "Statusline",
8238
8458
  "Statistics",
@@ -8314,15 +8534,6 @@ var init_glyphs = __esm(() => {
8314
8534
  };
8315
8535
  });
8316
8536
 
8317
- // src/tui/theme/motion.ts
8318
- function detectReducedMotion(env) {
8319
- if (env["NO_COLOR"] !== undefined)
8320
- return true;
8321
- if (env["CCSIDEKICK_REDUCE_MOTION"] !== undefined)
8322
- return true;
8323
- return false;
8324
- }
8325
-
8326
8537
  // src/tui/theme/tokens.ts
8327
8538
  function hexForXterm(index) {
8328
8539
  const [r, g, b] = xtermToRgb(index);
@@ -9800,1830 +10011,95 @@ var init_select = __esm(() => {
9800
10011
  init_use_select();
9801
10012
  });
9802
10013
 
9803
- // ../../node_modules/.bun/cli-spinners@3.4.0/node_modules/cli-spinners/spinners.json
9804
- var spinners_default;
9805
- var init_spinners = __esm(() => {
9806
- spinners_default = {
9807
- dots: {
9808
- interval: 80,
9809
- frames: [
9810
- "⠋",
9811
- "⠙",
9812
- "⠹",
9813
- "⠸",
9814
- "⠼",
9815
- "⠴",
9816
- "⠦",
9817
- "⠧",
9818
- "⠇",
9819
- "⠏"
9820
- ]
9821
- },
9822
- dots2: {
9823
- interval: 80,
9824
- frames: [
9825
- "⣾",
9826
- "⣽",
9827
- "⣻",
9828
- "⢿",
9829
- "⡿",
9830
- "⣟",
9831
- "⣯",
9832
- "⣷"
9833
- ]
9834
- },
9835
- dots3: {
9836
- interval: 80,
9837
- frames: [
9838
- "⠋",
9839
- "⠙",
9840
- "⠚",
9841
- "⠞",
9842
- "⠖",
9843
- "⠦",
9844
- "⠴",
9845
- "⠲",
9846
- "⠳",
9847
- "⠓"
9848
- ]
9849
- },
9850
- dots4: {
9851
- interval: 80,
9852
- frames: [
9853
- "⠄",
9854
- "⠆",
9855
- "⠇",
9856
- "⠋",
9857
- "⠙",
9858
- "⠸",
9859
- "⠰",
9860
- "⠠",
9861
- "⠰",
9862
- "⠸",
9863
- "⠙",
9864
- "⠋",
9865
- "⠇",
9866
- "⠆"
9867
- ]
10014
+ // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/spinner/use-spinner.js
10015
+ import { useEffect as useEffect4, useState as useState5 } from "react";
10016
+ var init_use_spinner = () => {};
10017
+
10018
+ // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/spinner/spinner.js
10019
+ import React11 from "react";
10020
+ import { Box as Box13, Text as Text16 } from "ink";
10021
+ var init_spinner = __esm(() => {
10022
+ init_theme16();
10023
+ init_use_spinner();
10024
+ });
10025
+
10026
+ // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/spinner/index.js
10027
+ var init_spinner2 = __esm(() => {
10028
+ init_spinner();
10029
+ init_use_spinner();
10030
+ });
10031
+
10032
+ // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/text-input/use-text-input-state.js
10033
+ import { useReducer as useReducer3, useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo4 } from "react";
10034
+ var init_use_text_input_state = () => {};
10035
+
10036
+ // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
10037
+ function assembleStyles() {
10038
+ const codes = new Map;
10039
+ for (const [groupName, group] of Object.entries(styles)) {
10040
+ for (const [styleName, style] of Object.entries(group)) {
10041
+ styles[styleName] = {
10042
+ open: `\x1B[${style[0]}m`,
10043
+ close: `\x1B[${style[1]}m`
10044
+ };
10045
+ group[styleName] = styles[styleName];
10046
+ codes.set(style[0], style[1]);
10047
+ }
10048
+ Object.defineProperty(styles, groupName, {
10049
+ value: group,
10050
+ enumerable: false
10051
+ });
10052
+ }
10053
+ Object.defineProperty(styles, "codes", {
10054
+ value: codes,
10055
+ enumerable: false
10056
+ });
10057
+ styles.color.close = "\x1B[39m";
10058
+ styles.bgColor.close = "\x1B[49m";
10059
+ styles.color.ansi = wrapAnsi16();
10060
+ styles.color.ansi256 = wrapAnsi256();
10061
+ styles.color.ansi16m = wrapAnsi16m();
10062
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
10063
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
10064
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
10065
+ Object.defineProperties(styles, {
10066
+ rgbToAnsi256: {
10067
+ value(red, green, blue) {
10068
+ if (red === green && green === blue) {
10069
+ if (red < 8) {
10070
+ return 16;
10071
+ }
10072
+ if (red > 248) {
10073
+ return 231;
10074
+ }
10075
+ return Math.round((red - 8) / 247 * 24) + 232;
10076
+ }
10077
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
10078
+ },
10079
+ enumerable: false
9868
10080
  },
9869
- dots5: {
9870
- interval: 80,
9871
- frames: [
9872
- "⠋",
9873
- "⠙",
9874
- "⠚",
9875
- "⠒",
9876
- "⠂",
9877
- "⠂",
9878
- "⠒",
9879
- "⠲",
9880
- "⠴",
9881
- "⠦",
9882
- "⠖",
9883
- "⠒",
9884
- "⠐",
9885
- "⠐",
9886
- "⠒",
9887
- "⠓",
9888
- "⠋"
9889
- ]
10081
+ hexToRgb: {
10082
+ value(hex) {
10083
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
10084
+ if (!matches) {
10085
+ return [0, 0, 0];
10086
+ }
10087
+ let [colorString] = matches;
10088
+ if (colorString.length === 3) {
10089
+ colorString = [...colorString].map((character) => character + character).join("");
10090
+ }
10091
+ const integer = Number.parseInt(colorString, 16);
10092
+ return [
10093
+ integer >> 16 & 255,
10094
+ integer >> 8 & 255,
10095
+ integer & 255
10096
+ ];
10097
+ },
10098
+ enumerable: false
9890
10099
  },
9891
- dots6: {
9892
- interval: 80,
9893
- frames: [
9894
- "⠁",
9895
- "⠉",
9896
- "⠙",
9897
- "⠚",
9898
- "⠒",
9899
- "⠂",
9900
- "⠂",
9901
- "⠒",
9902
- "⠲",
9903
- "⠴",
9904
- "⠤",
9905
- "⠄",
9906
- "⠄",
9907
- "⠤",
9908
- "⠴",
9909
- "⠲",
9910
- "⠒",
9911
- "⠂",
9912
- "⠂",
9913
- "⠒",
9914
- "⠚",
9915
- "⠙",
9916
- "⠉",
9917
- "⠁"
9918
- ]
9919
- },
9920
- dots7: {
9921
- interval: 80,
9922
- frames: [
9923
- "⠈",
9924
- "⠉",
9925
- "⠋",
9926
- "⠓",
9927
- "⠒",
9928
- "⠐",
9929
- "⠐",
9930
- "⠒",
9931
- "⠖",
9932
- "⠦",
9933
- "⠤",
9934
- "⠠",
9935
- "⠠",
9936
- "⠤",
9937
- "⠦",
9938
- "⠖",
9939
- "⠒",
9940
- "⠐",
9941
- "⠐",
9942
- "⠒",
9943
- "⠓",
9944
- "⠋",
9945
- "⠉",
9946
- "⠈"
9947
- ]
9948
- },
9949
- dots8: {
9950
- interval: 80,
9951
- frames: [
9952
- "⠁",
9953
- "⠁",
9954
- "⠉",
9955
- "⠙",
9956
- "⠚",
9957
- "⠒",
9958
- "⠂",
9959
- "⠂",
9960
- "⠒",
9961
- "⠲",
9962
- "⠴",
9963
- "⠤",
9964
- "⠄",
9965
- "⠄",
9966
- "⠤",
9967
- "⠠",
9968
- "⠠",
9969
- "⠤",
9970
- "⠦",
9971
- "⠖",
9972
- "⠒",
9973
- "⠐",
9974
- "⠐",
9975
- "⠒",
9976
- "⠓",
9977
- "⠋",
9978
- "⠉",
9979
- "⠈",
9980
- "⠈"
9981
- ]
9982
- },
9983
- dots9: {
9984
- interval: 80,
9985
- frames: [
9986
- "⢹",
9987
- "⢺",
9988
- "⢼",
9989
- "⣸",
9990
- "⣇",
9991
- "⡧",
9992
- "⡗",
9993
- "⡏"
9994
- ]
9995
- },
9996
- dots10: {
9997
- interval: 80,
9998
- frames: [
9999
- "⢄",
10000
- "⢂",
10001
- "⢁",
10002
- "⡁",
10003
- "⡈",
10004
- "⡐",
10005
- "⡠"
10006
- ]
10007
- },
10008
- dots11: {
10009
- interval: 100,
10010
- frames: [
10011
- "⠁",
10012
- "⠂",
10013
- "⠄",
10014
- "⡀",
10015
- "⢀",
10016
- "⠠",
10017
- "⠐",
10018
- "⠈"
10019
- ]
10020
- },
10021
- dots12: {
10022
- interval: 80,
10023
- frames: [
10024
- "⢀⠀",
10025
- "⡀⠀",
10026
- "⠄⠀",
10027
- "⢂⠀",
10028
- "⡂⠀",
10029
- "⠅⠀",
10030
- "⢃⠀",
10031
- "⡃⠀",
10032
- "⠍⠀",
10033
- "⢋⠀",
10034
- "⡋⠀",
10035
- "⠍⠁",
10036
- "⢋⠁",
10037
- "⡋⠁",
10038
- "⠍⠉",
10039
- "⠋⠉",
10040
- "⠋⠉",
10041
- "⠉⠙",
10042
- "⠉⠙",
10043
- "⠉⠩",
10044
- "⠈⢙",
10045
- "⠈⡙",
10046
- "⢈⠩",
10047
- "⡀⢙",
10048
- "⠄⡙",
10049
- "⢂⠩",
10050
- "⡂⢘",
10051
- "⠅⡘",
10052
- "⢃⠨",
10053
- "⡃⢐",
10054
- "⠍⡐",
10055
- "⢋⠠",
10056
- "⡋⢀",
10057
- "⠍⡁",
10058
- "⢋⠁",
10059
- "⡋⠁",
10060
- "⠍⠉",
10061
- "⠋⠉",
10062
- "⠋⠉",
10063
- "⠉⠙",
10064
- "⠉⠙",
10065
- "⠉⠩",
10066
- "⠈⢙",
10067
- "⠈⡙",
10068
- "⠈⠩",
10069
- "⠀⢙",
10070
- "⠀⡙",
10071
- "⠀⠩",
10072
- "⠀⢘",
10073
- "⠀⡘",
10074
- "⠀⠨",
10075
- "⠀⢐",
10076
- "⠀⡐",
10077
- "⠀⠠",
10078
- "⠀⢀",
10079
- "⠀⡀"
10080
- ]
10081
- },
10082
- dots13: {
10083
- interval: 80,
10084
- frames: [
10085
- "⣼",
10086
- "⣹",
10087
- "⢻",
10088
- "⠿",
10089
- "⡟",
10090
- "⣏",
10091
- "⣧",
10092
- "⣶"
10093
- ]
10094
- },
10095
- dots14: {
10096
- interval: 80,
10097
- frames: [
10098
- "⠉⠉",
10099
- "⠈⠙",
10100
- "⠀⠹",
10101
- "⠀⢸",
10102
- "⠀⣰",
10103
- "⢀⣠",
10104
- "⣀⣀",
10105
- "⣄⡀",
10106
- "⣆⠀",
10107
- "⡇⠀",
10108
- "⠏⠀",
10109
- "⠋⠁"
10110
- ]
10111
- },
10112
- dots8Bit: {
10113
- interval: 80,
10114
- frames: [
10115
- "⠀",
10116
- "⠁",
10117
- "⠂",
10118
- "⠃",
10119
- "⠄",
10120
- "⠅",
10121
- "⠆",
10122
- "⠇",
10123
- "⡀",
10124
- "⡁",
10125
- "⡂",
10126
- "⡃",
10127
- "⡄",
10128
- "⡅",
10129
- "⡆",
10130
- "⡇",
10131
- "⠈",
10132
- "⠉",
10133
- "⠊",
10134
- "⠋",
10135
- "⠌",
10136
- "⠍",
10137
- "⠎",
10138
- "⠏",
10139
- "⡈",
10140
- "⡉",
10141
- "⡊",
10142
- "⡋",
10143
- "⡌",
10144
- "⡍",
10145
- "⡎",
10146
- "⡏",
10147
- "⠐",
10148
- "⠑",
10149
- "⠒",
10150
- "⠓",
10151
- "⠔",
10152
- "⠕",
10153
- "⠖",
10154
- "⠗",
10155
- "⡐",
10156
- "⡑",
10157
- "⡒",
10158
- "⡓",
10159
- "⡔",
10160
- "⡕",
10161
- "⡖",
10162
- "⡗",
10163
- "⠘",
10164
- "⠙",
10165
- "⠚",
10166
- "⠛",
10167
- "⠜",
10168
- "⠝",
10169
- "⠞",
10170
- "⠟",
10171
- "⡘",
10172
- "⡙",
10173
- "⡚",
10174
- "⡛",
10175
- "⡜",
10176
- "⡝",
10177
- "⡞",
10178
- "⡟",
10179
- "⠠",
10180
- "⠡",
10181
- "⠢",
10182
- "⠣",
10183
- "⠤",
10184
- "⠥",
10185
- "⠦",
10186
- "⠧",
10187
- "⡠",
10188
- "⡡",
10189
- "⡢",
10190
- "⡣",
10191
- "⡤",
10192
- "⡥",
10193
- "⡦",
10194
- "⡧",
10195
- "⠨",
10196
- "⠩",
10197
- "⠪",
10198
- "⠫",
10199
- "⠬",
10200
- "⠭",
10201
- "⠮",
10202
- "⠯",
10203
- "⡨",
10204
- "⡩",
10205
- "⡪",
10206
- "⡫",
10207
- "⡬",
10208
- "⡭",
10209
- "⡮",
10210
- "⡯",
10211
- "⠰",
10212
- "⠱",
10213
- "⠲",
10214
- "⠳",
10215
- "⠴",
10216
- "⠵",
10217
- "⠶",
10218
- "⠷",
10219
- "⡰",
10220
- "⡱",
10221
- "⡲",
10222
- "⡳",
10223
- "⡴",
10224
- "⡵",
10225
- "⡶",
10226
- "⡷",
10227
- "⠸",
10228
- "⠹",
10229
- "⠺",
10230
- "⠻",
10231
- "⠼",
10232
- "⠽",
10233
- "⠾",
10234
- "⠿",
10235
- "⡸",
10236
- "⡹",
10237
- "⡺",
10238
- "⡻",
10239
- "⡼",
10240
- "⡽",
10241
- "⡾",
10242
- "⡿",
10243
- "⢀",
10244
- "⢁",
10245
- "⢂",
10246
- "⢃",
10247
- "⢄",
10248
- "⢅",
10249
- "⢆",
10250
- "⢇",
10251
- "⣀",
10252
- "⣁",
10253
- "⣂",
10254
- "⣃",
10255
- "⣄",
10256
- "⣅",
10257
- "⣆",
10258
- "⣇",
10259
- "⢈",
10260
- "⢉",
10261
- "⢊",
10262
- "⢋",
10263
- "⢌",
10264
- "⢍",
10265
- "⢎",
10266
- "⢏",
10267
- "⣈",
10268
- "⣉",
10269
- "⣊",
10270
- "⣋",
10271
- "⣌",
10272
- "⣍",
10273
- "⣎",
10274
- "⣏",
10275
- "⢐",
10276
- "⢑",
10277
- "⢒",
10278
- "⢓",
10279
- "⢔",
10280
- "⢕",
10281
- "⢖",
10282
- "⢗",
10283
- "⣐",
10284
- "⣑",
10285
- "⣒",
10286
- "⣓",
10287
- "⣔",
10288
- "⣕",
10289
- "⣖",
10290
- "⣗",
10291
- "⢘",
10292
- "⢙",
10293
- "⢚",
10294
- "⢛",
10295
- "⢜",
10296
- "⢝",
10297
- "⢞",
10298
- "⢟",
10299
- "⣘",
10300
- "⣙",
10301
- "⣚",
10302
- "⣛",
10303
- "⣜",
10304
- "⣝",
10305
- "⣞",
10306
- "⣟",
10307
- "⢠",
10308
- "⢡",
10309
- "⢢",
10310
- "⢣",
10311
- "⢤",
10312
- "⢥",
10313
- "⢦",
10314
- "⢧",
10315
- "⣠",
10316
- "⣡",
10317
- "⣢",
10318
- "⣣",
10319
- "⣤",
10320
- "⣥",
10321
- "⣦",
10322
- "⣧",
10323
- "⢨",
10324
- "⢩",
10325
- "⢪",
10326
- "⢫",
10327
- "⢬",
10328
- "⢭",
10329
- "⢮",
10330
- "⢯",
10331
- "⣨",
10332
- "⣩",
10333
- "⣪",
10334
- "⣫",
10335
- "⣬",
10336
- "⣭",
10337
- "⣮",
10338
- "⣯",
10339
- "⢰",
10340
- "⢱",
10341
- "⢲",
10342
- "⢳",
10343
- "⢴",
10344
- "⢵",
10345
- "⢶",
10346
- "⢷",
10347
- "⣰",
10348
- "⣱",
10349
- "⣲",
10350
- "⣳",
10351
- "⣴",
10352
- "⣵",
10353
- "⣶",
10354
- "⣷",
10355
- "⢸",
10356
- "⢹",
10357
- "⢺",
10358
- "⢻",
10359
- "⢼",
10360
- "⢽",
10361
- "⢾",
10362
- "⢿",
10363
- "⣸",
10364
- "⣹",
10365
- "⣺",
10366
- "⣻",
10367
- "⣼",
10368
- "⣽",
10369
- "⣾",
10370
- "⣿"
10371
- ]
10372
- },
10373
- dotsCircle: {
10374
- interval: 80,
10375
- frames: [
10376
- "⢎ ",
10377
- "⠎⠁",
10378
- "⠊⠑",
10379
- "⠈⠱",
10380
- " ⡱",
10381
- "⢀⡰",
10382
- "⢄⡠",
10383
- "⢆⡀"
10384
- ]
10385
- },
10386
- sand: {
10387
- interval: 80,
10388
- frames: [
10389
- "⠁",
10390
- "⠂",
10391
- "⠄",
10392
- "⡀",
10393
- "⡈",
10394
- "⡐",
10395
- "⡠",
10396
- "⣀",
10397
- "⣁",
10398
- "⣂",
10399
- "⣄",
10400
- "⣌",
10401
- "⣔",
10402
- "⣤",
10403
- "⣥",
10404
- "⣦",
10405
- "⣮",
10406
- "⣶",
10407
- "⣷",
10408
- "⣿",
10409
- "⡿",
10410
- "⠿",
10411
- "⢟",
10412
- "⠟",
10413
- "⡛",
10414
- "⠛",
10415
- "⠫",
10416
- "⢋",
10417
- "⠋",
10418
- "⠍",
10419
- "⡉",
10420
- "⠉",
10421
- "⠑",
10422
- "⠡",
10423
- "⢁"
10424
- ]
10425
- },
10426
- line: {
10427
- interval: 130,
10428
- frames: [
10429
- "-",
10430
- "\\",
10431
- "|",
10432
- "/"
10433
- ]
10434
- },
10435
- line2: {
10436
- interval: 100,
10437
- frames: [
10438
- "⠂",
10439
- "-",
10440
- "–",
10441
- "—",
10442
- "–",
10443
- "-"
10444
- ]
10445
- },
10446
- rollingLine: {
10447
- interval: 80,
10448
- frames: [
10449
- "/ ",
10450
- " - ",
10451
- " \\ ",
10452
- " |",
10453
- " |",
10454
- " \\ ",
10455
- " - ",
10456
- "/ "
10457
- ]
10458
- },
10459
- pipe: {
10460
- interval: 100,
10461
- frames: [
10462
- "┤",
10463
- "┘",
10464
- "┴",
10465
- "└",
10466
- "├",
10467
- "┌",
10468
- "┬",
10469
- "┐"
10470
- ]
10471
- },
10472
- simpleDots: {
10473
- interval: 400,
10474
- frames: [
10475
- ". ",
10476
- ".. ",
10477
- "...",
10478
- " "
10479
- ]
10480
- },
10481
- simpleDotsScrolling: {
10482
- interval: 200,
10483
- frames: [
10484
- ". ",
10485
- ".. ",
10486
- "...",
10487
- " ..",
10488
- " .",
10489
- " "
10490
- ]
10491
- },
10492
- star: {
10493
- interval: 70,
10494
- frames: [
10495
- "✶",
10496
- "✸",
10497
- "✹",
10498
- "✺",
10499
- "✹",
10500
- "✷"
10501
- ]
10502
- },
10503
- star2: {
10504
- interval: 80,
10505
- frames: [
10506
- "+",
10507
- "x",
10508
- "*"
10509
- ]
10510
- },
10511
- flip: {
10512
- interval: 70,
10513
- frames: [
10514
- "_",
10515
- "_",
10516
- "_",
10517
- "-",
10518
- "`",
10519
- "`",
10520
- "'",
10521
- "´",
10522
- "-",
10523
- "_",
10524
- "_",
10525
- "_"
10526
- ]
10527
- },
10528
- hamburger: {
10529
- interval: 100,
10530
- frames: [
10531
- "☱",
10532
- "☲",
10533
- "☴"
10534
- ]
10535
- },
10536
- growVertical: {
10537
- interval: 120,
10538
- frames: [
10539
- "▁",
10540
- "▃",
10541
- "▄",
10542
- "▅",
10543
- "▆",
10544
- "▇",
10545
- "▆",
10546
- "▅",
10547
- "▄",
10548
- "▃"
10549
- ]
10550
- },
10551
- growHorizontal: {
10552
- interval: 120,
10553
- frames: [
10554
- "▏",
10555
- "▎",
10556
- "▍",
10557
- "▌",
10558
- "▋",
10559
- "▊",
10560
- "▉",
10561
- "▊",
10562
- "▋",
10563
- "▌",
10564
- "▍",
10565
- "▎"
10566
- ]
10567
- },
10568
- balloon: {
10569
- interval: 140,
10570
- frames: [
10571
- " ",
10572
- ".",
10573
- "o",
10574
- "O",
10575
- "@",
10576
- "*",
10577
- " "
10578
- ]
10579
- },
10580
- balloon2: {
10581
- interval: 120,
10582
- frames: [
10583
- ".",
10584
- "o",
10585
- "O",
10586
- "°",
10587
- "O",
10588
- "o",
10589
- "."
10590
- ]
10591
- },
10592
- noise: {
10593
- interval: 100,
10594
- frames: [
10595
- "▓",
10596
- "▒",
10597
- "░"
10598
- ]
10599
- },
10600
- bounce: {
10601
- interval: 120,
10602
- frames: [
10603
- "⠁",
10604
- "⠂",
10605
- "⠄",
10606
- "⠂"
10607
- ]
10608
- },
10609
- boxBounce: {
10610
- interval: 120,
10611
- frames: [
10612
- "▖",
10613
- "▘",
10614
- "▝",
10615
- "▗"
10616
- ]
10617
- },
10618
- boxBounce2: {
10619
- interval: 100,
10620
- frames: [
10621
- "▌",
10622
- "▀",
10623
- "▐",
10624
- "▄"
10625
- ]
10626
- },
10627
- triangle: {
10628
- interval: 50,
10629
- frames: [
10630
- "◢",
10631
- "◣",
10632
- "◤",
10633
- "◥"
10634
- ]
10635
- },
10636
- binary: {
10637
- interval: 80,
10638
- frames: [
10639
- "010010",
10640
- "001100",
10641
- "100101",
10642
- "111010",
10643
- "111101",
10644
- "010111",
10645
- "101011",
10646
- "111000",
10647
- "110011",
10648
- "110101"
10649
- ]
10650
- },
10651
- arc: {
10652
- interval: 100,
10653
- frames: [
10654
- "◜",
10655
- "◠",
10656
- "◝",
10657
- "◞",
10658
- "◡",
10659
- "◟"
10660
- ]
10661
- },
10662
- circle: {
10663
- interval: 120,
10664
- frames: [
10665
- "◡",
10666
- "⊙",
10667
- "◠"
10668
- ]
10669
- },
10670
- squareCorners: {
10671
- interval: 180,
10672
- frames: [
10673
- "◰",
10674
- "◳",
10675
- "◲",
10676
- "◱"
10677
- ]
10678
- },
10679
- circleQuarters: {
10680
- interval: 120,
10681
- frames: [
10682
- "◴",
10683
- "◷",
10684
- "◶",
10685
- "◵"
10686
- ]
10687
- },
10688
- circleHalves: {
10689
- interval: 50,
10690
- frames: [
10691
- "◐",
10692
- "◓",
10693
- "◑",
10694
- "◒"
10695
- ]
10696
- },
10697
- squish: {
10698
- interval: 100,
10699
- frames: [
10700
- "╫",
10701
- "╪"
10702
- ]
10703
- },
10704
- toggle: {
10705
- interval: 250,
10706
- frames: [
10707
- "⊶",
10708
- "⊷"
10709
- ]
10710
- },
10711
- toggle2: {
10712
- interval: 80,
10713
- frames: [
10714
- "▫",
10715
- "▪"
10716
- ]
10717
- },
10718
- toggle3: {
10719
- interval: 120,
10720
- frames: [
10721
- "□",
10722
- "■"
10723
- ]
10724
- },
10725
- toggle4: {
10726
- interval: 100,
10727
- frames: [
10728
- "■",
10729
- "□",
10730
- "▪",
10731
- "▫"
10732
- ]
10733
- },
10734
- toggle5: {
10735
- interval: 100,
10736
- frames: [
10737
- "▮",
10738
- "▯"
10739
- ]
10740
- },
10741
- toggle6: {
10742
- interval: 300,
10743
- frames: [
10744
- "ဝ",
10745
- "၀"
10746
- ]
10747
- },
10748
- toggle7: {
10749
- interval: 80,
10750
- frames: [
10751
- "⦾",
10752
- "⦿"
10753
- ]
10754
- },
10755
- toggle8: {
10756
- interval: 100,
10757
- frames: [
10758
- "◍",
10759
- "◌"
10760
- ]
10761
- },
10762
- toggle9: {
10763
- interval: 100,
10764
- frames: [
10765
- "◉",
10766
- "◎"
10767
- ]
10768
- },
10769
- toggle10: {
10770
- interval: 100,
10771
- frames: [
10772
- "㊂",
10773
- "㊀",
10774
- "㊁"
10775
- ]
10776
- },
10777
- toggle11: {
10778
- interval: 50,
10779
- frames: [
10780
- "⧇",
10781
- "⧆"
10782
- ]
10783
- },
10784
- toggle12: {
10785
- interval: 120,
10786
- frames: [
10787
- "☗",
10788
- "☖"
10789
- ]
10790
- },
10791
- toggle13: {
10792
- interval: 80,
10793
- frames: [
10794
- "=",
10795
- "*",
10796
- "-"
10797
- ]
10798
- },
10799
- arrow: {
10800
- interval: 100,
10801
- frames: [
10802
- "←",
10803
- "↖",
10804
- "↑",
10805
- "↗",
10806
- "→",
10807
- "↘",
10808
- "↓",
10809
- "↙"
10810
- ]
10811
- },
10812
- arrow2: {
10813
- interval: 80,
10814
- frames: [
10815
- "⬆️ ",
10816
- "↗️ ",
10817
- "➡️ ",
10818
- "↘️ ",
10819
- "⬇️ ",
10820
- "↙️ ",
10821
- "⬅️ ",
10822
- "↖️ "
10823
- ]
10824
- },
10825
- arrow3: {
10826
- interval: 120,
10827
- frames: [
10828
- "▹▹▹▹▹",
10829
- "▸▹▹▹▹",
10830
- "▹▸▹▹▹",
10831
- "▹▹▸▹▹",
10832
- "▹▹▹▸▹",
10833
- "▹▹▹▹▸"
10834
- ]
10835
- },
10836
- bouncingBar: {
10837
- interval: 80,
10838
- frames: [
10839
- "[ ]",
10840
- "[= ]",
10841
- "[== ]",
10842
- "[=== ]",
10843
- "[====]",
10844
- "[ ===]",
10845
- "[ ==]",
10846
- "[ =]",
10847
- "[ ]",
10848
- "[ =]",
10849
- "[ ==]",
10850
- "[ ===]",
10851
- "[====]",
10852
- "[=== ]",
10853
- "[== ]",
10854
- "[= ]"
10855
- ]
10856
- },
10857
- bouncingBall: {
10858
- interval: 80,
10859
- frames: [
10860
- "( ● )",
10861
- "( ● )",
10862
- "( ● )",
10863
- "( ● )",
10864
- "( ●)",
10865
- "( ● )",
10866
- "( ● )",
10867
- "( ● )",
10868
- "( ● )",
10869
- "(● )"
10870
- ]
10871
- },
10872
- smiley: {
10873
- interval: 200,
10874
- frames: [
10875
- "😄 ",
10876
- "😝 "
10877
- ]
10878
- },
10879
- monkey: {
10880
- interval: 300,
10881
- frames: [
10882
- "🙈 ",
10883
- "🙈 ",
10884
- "🙉 ",
10885
- "🙊 "
10886
- ]
10887
- },
10888
- hearts: {
10889
- interval: 100,
10890
- frames: [
10891
- "💛 ",
10892
- "💙 ",
10893
- "💜 ",
10894
- "💚 ",
10895
- "💗 "
10896
- ]
10897
- },
10898
- clock: {
10899
- interval: 100,
10900
- frames: [
10901
- "🕛 ",
10902
- "🕐 ",
10903
- "🕑 ",
10904
- "🕒 ",
10905
- "🕓 ",
10906
- "🕔 ",
10907
- "🕕 ",
10908
- "🕖 ",
10909
- "🕗 ",
10910
- "🕘 ",
10911
- "🕙 ",
10912
- "🕚 "
10913
- ]
10914
- },
10915
- earth: {
10916
- interval: 180,
10917
- frames: [
10918
- "🌍 ",
10919
- "🌎 ",
10920
- "🌏 "
10921
- ]
10922
- },
10923
- material: {
10924
- interval: 17,
10925
- frames: [
10926
- "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
10927
- "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
10928
- "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
10929
- "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
10930
- "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
10931
- "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
10932
- "███████▁▁▁▁▁▁▁▁▁▁▁▁▁",
10933
- "████████▁▁▁▁▁▁▁▁▁▁▁▁",
10934
- "█████████▁▁▁▁▁▁▁▁▁▁▁",
10935
- "█████████▁▁▁▁▁▁▁▁▁▁▁",
10936
- "██████████▁▁▁▁▁▁▁▁▁▁",
10937
- "███████████▁▁▁▁▁▁▁▁▁",
10938
- "█████████████▁▁▁▁▁▁▁",
10939
- "██████████████▁▁▁▁▁▁",
10940
- "██████████████▁▁▁▁▁▁",
10941
- "▁██████████████▁▁▁▁▁",
10942
- "▁██████████████▁▁▁▁▁",
10943
- "▁██████████████▁▁▁▁▁",
10944
- "▁▁██████████████▁▁▁▁",
10945
- "▁▁▁██████████████▁▁▁",
10946
- "▁▁▁▁█████████████▁▁▁",
10947
- "▁▁▁▁██████████████▁▁",
10948
- "▁▁▁▁██████████████▁▁",
10949
- "▁▁▁▁▁██████████████▁",
10950
- "▁▁▁▁▁██████████████▁",
10951
- "▁▁▁▁▁██████████████▁",
10952
- "▁▁▁▁▁▁██████████████",
10953
- "▁▁▁▁▁▁██████████████",
10954
- "▁▁▁▁▁▁▁█████████████",
10955
- "▁▁▁▁▁▁▁█████████████",
10956
- "▁▁▁▁▁▁▁▁████████████",
10957
- "▁▁▁▁▁▁▁▁████████████",
10958
- "▁▁▁▁▁▁▁▁▁███████████",
10959
- "▁▁▁▁▁▁▁▁▁███████████",
10960
- "▁▁▁▁▁▁▁▁▁▁██████████",
10961
- "▁▁▁▁▁▁▁▁▁▁██████████",
10962
- "▁▁▁▁▁▁▁▁▁▁▁▁████████",
10963
- "▁▁▁▁▁▁▁▁▁▁▁▁▁███████",
10964
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████",
10965
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████",
10966
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████",
10967
- "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
10968
- "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
10969
- "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
10970
- "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
10971
- "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
10972
- "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
10973
- "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
10974
- "██████▁▁▁▁▁▁▁▁▁▁▁▁▁█",
10975
- "████████▁▁▁▁▁▁▁▁▁▁▁▁",
10976
- "█████████▁▁▁▁▁▁▁▁▁▁▁",
10977
- "█████████▁▁▁▁▁▁▁▁▁▁▁",
10978
- "█████████▁▁▁▁▁▁▁▁▁▁▁",
10979
- "█████████▁▁▁▁▁▁▁▁▁▁▁",
10980
- "███████████▁▁▁▁▁▁▁▁▁",
10981
- "████████████▁▁▁▁▁▁▁▁",
10982
- "████████████▁▁▁▁▁▁▁▁",
10983
- "██████████████▁▁▁▁▁▁",
10984
- "██████████████▁▁▁▁▁▁",
10985
- "▁██████████████▁▁▁▁▁",
10986
- "▁██████████████▁▁▁▁▁",
10987
- "▁▁▁█████████████▁▁▁▁",
10988
- "▁▁▁▁▁████████████▁▁▁",
10989
- "▁▁▁▁▁████████████▁▁▁",
10990
- "▁▁▁▁▁▁███████████▁▁▁",
10991
- "▁▁▁▁▁▁▁▁█████████▁▁▁",
10992
- "▁▁▁▁▁▁▁▁█████████▁▁▁",
10993
- "▁▁▁▁▁▁▁▁▁█████████▁▁",
10994
- "▁▁▁▁▁▁▁▁▁█████████▁▁",
10995
- "▁▁▁▁▁▁▁▁▁▁█████████▁",
10996
- "▁▁▁▁▁▁▁▁▁▁▁████████▁",
10997
- "▁▁▁▁▁▁▁▁▁▁▁████████▁",
10998
- "▁▁▁▁▁▁▁▁▁▁▁▁███████▁",
10999
- "▁▁▁▁▁▁▁▁▁▁▁▁███████▁",
11000
- "▁▁▁▁▁▁▁▁▁▁▁▁▁███████",
11001
- "▁▁▁▁▁▁▁▁▁▁▁▁▁███████",
11002
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████",
11003
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
11004
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
11005
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
11006
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
11007
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
11008
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
11009
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
11010
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
11011
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
11012
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
11013
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
11014
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
11015
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
11016
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
11017
- "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁"
11018
- ]
11019
- },
11020
- moon: {
11021
- interval: 80,
11022
- frames: [
11023
- "🌑 ",
11024
- "🌒 ",
11025
- "🌓 ",
11026
- "🌔 ",
11027
- "🌕 ",
11028
- "🌖 ",
11029
- "🌗 ",
11030
- "🌘 "
11031
- ]
11032
- },
11033
- runner: {
11034
- interval: 140,
11035
- frames: [
11036
- "🚶 ",
11037
- "🏃 "
11038
- ]
11039
- },
11040
- pong: {
11041
- interval: 80,
11042
- frames: [
11043
- "▐⠂ ▌",
11044
- "▐⠈ ▌",
11045
- "▐ ⠂ ▌",
11046
- "▐ ⠠ ▌",
11047
- "▐ ⡀ ▌",
11048
- "▐ ⠠ ▌",
11049
- "▐ ⠂ ▌",
11050
- "▐ ⠈ ▌",
11051
- "▐ ⠂ ▌",
11052
- "▐ ⠠ ▌",
11053
- "▐ ⡀ ▌",
11054
- "▐ ⠠ ▌",
11055
- "▐ ⠂ ▌",
11056
- "▐ ⠈ ▌",
11057
- "▐ ⠂▌",
11058
- "▐ ⠠▌",
11059
- "▐ ⡀▌",
11060
- "▐ ⠠ ▌",
11061
- "▐ ⠂ ▌",
11062
- "▐ ⠈ ▌",
11063
- "▐ ⠂ ▌",
11064
- "▐ ⠠ ▌",
11065
- "▐ ⡀ ▌",
11066
- "▐ ⠠ ▌",
11067
- "▐ ⠂ ▌",
11068
- "▐ ⠈ ▌",
11069
- "▐ ⠂ ▌",
11070
- "▐ ⠠ ▌",
11071
- "▐ ⡀ ▌",
11072
- "▐⠠ ▌"
11073
- ]
11074
- },
11075
- shark: {
11076
- interval: 120,
11077
- frames: [
11078
- "▐|\\____________▌",
11079
- "▐_|\\___________▌",
11080
- "▐__|\\__________▌",
11081
- "▐___|\\_________▌",
11082
- "▐____|\\________▌",
11083
- "▐_____|\\_______▌",
11084
- "▐______|\\______▌",
11085
- "▐_______|\\_____▌",
11086
- "▐________|\\____▌",
11087
- "▐_________|\\___▌",
11088
- "▐__________|\\__▌",
11089
- "▐___________|\\_▌",
11090
- "▐____________|\\▌",
11091
- "▐____________/|▌",
11092
- "▐___________/|_▌",
11093
- "▐__________/|__▌",
11094
- "▐_________/|___▌",
11095
- "▐________/|____▌",
11096
- "▐_______/|_____▌",
11097
- "▐______/|______▌",
11098
- "▐_____/|_______▌",
11099
- "▐____/|________▌",
11100
- "▐___/|_________▌",
11101
- "▐__/|__________▌",
11102
- "▐_/|___________▌",
11103
- "▐/|____________▌"
11104
- ]
11105
- },
11106
- dqpb: {
11107
- interval: 100,
11108
- frames: [
11109
- "d",
11110
- "q",
11111
- "p",
11112
- "b"
11113
- ]
11114
- },
11115
- weather: {
11116
- interval: 100,
11117
- frames: [
11118
- "☀️ ",
11119
- "☀️ ",
11120
- "☀️ ",
11121
- "🌤 ",
11122
- "⛅️ ",
11123
- "🌥 ",
11124
- "☁️ ",
11125
- "🌧 ",
11126
- "🌨 ",
11127
- "🌧 ",
11128
- "🌨 ",
11129
- "🌧 ",
11130
- "🌨 ",
11131
- "⛈ ",
11132
- "🌨 ",
11133
- "🌧 ",
11134
- "🌨 ",
11135
- "☁️ ",
11136
- "🌥 ",
11137
- "⛅️ ",
11138
- "🌤 ",
11139
- "☀️ ",
11140
- "☀️ "
11141
- ]
11142
- },
11143
- christmas: {
11144
- interval: 400,
11145
- frames: [
11146
- "🌲",
11147
- "🎄"
11148
- ]
11149
- },
11150
- grenade: {
11151
- interval: 80,
11152
- frames: [
11153
- "، ",
11154
- "′ ",
11155
- " ´ ",
11156
- " ‾ ",
11157
- " ⸌",
11158
- " ⸊",
11159
- " |",
11160
- " ⁎",
11161
- " ⁕",
11162
- " ෴ ",
11163
- " ⁓",
11164
- " ",
11165
- " ",
11166
- " "
11167
- ]
11168
- },
11169
- point: {
11170
- interval: 125,
11171
- frames: [
11172
- "∙∙∙",
11173
- "●∙∙",
11174
- "∙●∙",
11175
- "∙∙●",
11176
- "∙∙∙"
11177
- ]
11178
- },
11179
- layer: {
11180
- interval: 150,
11181
- frames: [
11182
- "-",
11183
- "=",
11184
- "≡"
11185
- ]
11186
- },
11187
- betaWave: {
11188
- interval: 80,
11189
- frames: [
11190
- "ρββββββ",
11191
- "βρβββββ",
11192
- "ββρββββ",
11193
- "βββρβββ",
11194
- "ββββρββ",
11195
- "βββββρβ",
11196
- "ββββββρ"
11197
- ]
11198
- },
11199
- fingerDance: {
11200
- interval: 160,
11201
- frames: [
11202
- "🤘 ",
11203
- "🤟 ",
11204
- "🖖 ",
11205
- "✋ ",
11206
- "🤚 ",
11207
- "👆 "
11208
- ]
11209
- },
11210
- fistBump: {
11211
- interval: 80,
11212
- frames: [
11213
- "🤜    🤛 ",
11214
- "🤜    🤛 ",
11215
- "🤜    🤛 ",
11216
- " 🤜  🤛  ",
11217
- "  🤜🤛   ",
11218
- " 🤜✨🤛   ",
11219
- "🤜 ✨ 🤛  "
11220
- ]
11221
- },
11222
- soccerHeader: {
11223
- interval: 80,
11224
- frames: [
11225
- " 🧑⚽️ 🧑 ",
11226
- "🧑 ⚽️ 🧑 ",
11227
- "🧑 ⚽️ 🧑 ",
11228
- "🧑 ⚽️ 🧑 ",
11229
- "🧑 ⚽️ 🧑 ",
11230
- "🧑 ⚽️ 🧑 ",
11231
- "🧑 ⚽️🧑 ",
11232
- "🧑 ⚽️ 🧑 ",
11233
- "🧑 ⚽️ 🧑 ",
11234
- "🧑 ⚽️ 🧑 ",
11235
- "🧑 ⚽️ 🧑 ",
11236
- "🧑 ⚽️ 🧑 "
11237
- ]
11238
- },
11239
- mindblown: {
11240
- interval: 160,
11241
- frames: [
11242
- "😐 ",
11243
- "😐 ",
11244
- "😮 ",
11245
- "😮 ",
11246
- "😦 ",
11247
- "😦 ",
11248
- "😧 ",
11249
- "😧 ",
11250
- "🤯 ",
11251
- "💥 ",
11252
- "✨ ",
11253
- "  ",
11254
- "  ",
11255
- "  "
11256
- ]
11257
- },
11258
- speaker: {
11259
- interval: 160,
11260
- frames: [
11261
- "🔈 ",
11262
- "🔉 ",
11263
- "🔊 ",
11264
- "🔉 "
11265
- ]
11266
- },
11267
- orangePulse: {
11268
- interval: 100,
11269
- frames: [
11270
- "🔸 ",
11271
- "🔶 ",
11272
- "🟠 ",
11273
- "🟠 ",
11274
- "🔶 "
11275
- ]
11276
- },
11277
- bluePulse: {
11278
- interval: 100,
11279
- frames: [
11280
- "🔹 ",
11281
- "🔷 ",
11282
- "🔵 ",
11283
- "🔵 ",
11284
- "🔷 "
11285
- ]
11286
- },
11287
- orangeBluePulse: {
11288
- interval: 100,
11289
- frames: [
11290
- "🔸 ",
11291
- "🔶 ",
11292
- "🟠 ",
11293
- "🟠 ",
11294
- "🔶 ",
11295
- "🔹 ",
11296
- "🔷 ",
11297
- "🔵 ",
11298
- "🔵 ",
11299
- "🔷 "
11300
- ]
11301
- },
11302
- timeTravel: {
11303
- interval: 100,
11304
- frames: [
11305
- "🕛 ",
11306
- "🕚 ",
11307
- "🕙 ",
11308
- "🕘 ",
11309
- "🕗 ",
11310
- "🕖 ",
11311
- "🕕 ",
11312
- "🕔 ",
11313
- "🕓 ",
11314
- "🕒 ",
11315
- "🕑 ",
11316
- "🕐 "
11317
- ]
11318
- },
11319
- aesthetic: {
11320
- interval: 80,
11321
- frames: [
11322
- "▰▱▱▱▱▱▱",
11323
- "▰▰▱▱▱▱▱",
11324
- "▰▰▰▱▱▱▱",
11325
- "▰▰▰▰▱▱▱",
11326
- "▰▰▰▰▰▱▱",
11327
- "▰▰▰▰▰▰▱",
11328
- "▰▰▰▰▰▰▰",
11329
- "▰▱▱▱▱▱▱"
11330
- ]
11331
- },
11332
- dwarfFortress: {
11333
- interval: 80,
11334
- frames: [
11335
- " ██████£££ ",
11336
- "☺██████£££ ",
11337
- "☺██████£££ ",
11338
- "☺▓█████£££ ",
11339
- "☺▓█████£££ ",
11340
- "☺▒█████£££ ",
11341
- "☺▒█████£££ ",
11342
- "☺░█████£££ ",
11343
- "☺░█████£££ ",
11344
- "☺ █████£££ ",
11345
- " ☺█████£££ ",
11346
- " ☺█████£££ ",
11347
- " ☺▓████£££ ",
11348
- " ☺▓████£££ ",
11349
- " ☺▒████£££ ",
11350
- " ☺▒████£££ ",
11351
- " ☺░████£££ ",
11352
- " ☺░████£££ ",
11353
- " ☺ ████£££ ",
11354
- " ☺████£££ ",
11355
- " ☺████£££ ",
11356
- " ☺▓███£££ ",
11357
- " ☺▓███£££ ",
11358
- " ☺▒███£££ ",
11359
- " ☺▒███£££ ",
11360
- " ☺░███£££ ",
11361
- " ☺░███£££ ",
11362
- " ☺ ███£££ ",
11363
- " ☺███£££ ",
11364
- " ☺███£££ ",
11365
- " ☺▓██£££ ",
11366
- " ☺▓██£££ ",
11367
- " ☺▒██£££ ",
11368
- " ☺▒██£££ ",
11369
- " ☺░██£££ ",
11370
- " ☺░██£££ ",
11371
- " ☺ ██£££ ",
11372
- " ☺██£££ ",
11373
- " ☺██£££ ",
11374
- " ☺▓█£££ ",
11375
- " ☺▓█£££ ",
11376
- " ☺▒█£££ ",
11377
- " ☺▒█£££ ",
11378
- " ☺░█£££ ",
11379
- " ☺░█£££ ",
11380
- " ☺ █£££ ",
11381
- " ☺█£££ ",
11382
- " ☺█£££ ",
11383
- " ☺▓£££ ",
11384
- " ☺▓£££ ",
11385
- " ☺▒£££ ",
11386
- " ☺▒£££ ",
11387
- " ☺░£££ ",
11388
- " ☺░£££ ",
11389
- " ☺ £££ ",
11390
- " ☺£££ ",
11391
- " ☺£££ ",
11392
- " ☺▓££ ",
11393
- " ☺▓££ ",
11394
- " ☺▒££ ",
11395
- " ☺▒££ ",
11396
- " ☺░££ ",
11397
- " ☺░££ ",
11398
- " ☺ ££ ",
11399
- " ☺££ ",
11400
- " ☺££ ",
11401
- " ☺▓£ ",
11402
- " ☺▓£ ",
11403
- " ☺▒£ ",
11404
- " ☺▒£ ",
11405
- " ☺░£ ",
11406
- " ☺░£ ",
11407
- " ☺ £ ",
11408
- " ☺£ ",
11409
- " ☺£ ",
11410
- " ☺▓ ",
11411
- " ☺▓ ",
11412
- " ☺▒ ",
11413
- " ☺▒ ",
11414
- " ☺░ ",
11415
- " ☺░ ",
11416
- " ☺ ",
11417
- " ☺ &",
11418
- " ☺ ☼&",
11419
- " ☺ ☼ &",
11420
- " ☺☼ &",
11421
- " ☺☼ & ",
11422
- " ‼ & ",
11423
- " ☺ & ",
11424
- " ‼ & ",
11425
- " ☺ & ",
11426
- " ‼ & ",
11427
- " ☺ & ",
11428
- "‼ & ",
11429
- " & ",
11430
- " & ",
11431
- " & ░ ",
11432
- " & ▒ ",
11433
- " & ▓ ",
11434
- " & £ ",
11435
- " & ░£ ",
11436
- " & ▒£ ",
11437
- " & ▓£ ",
11438
- " & ££ ",
11439
- " & ░££ ",
11440
- " & ▒££ ",
11441
- "& ▓££ ",
11442
- "& £££ ",
11443
- " ░£££ ",
11444
- " ▒£££ ",
11445
- " ▓£££ ",
11446
- " █£££ ",
11447
- " ░█£££ ",
11448
- " ▒█£££ ",
11449
- " ▓█£££ ",
11450
- " ██£££ ",
11451
- " ░██£££ ",
11452
- " ▒██£££ ",
11453
- " ▓██£££ ",
11454
- " ███£££ ",
11455
- " ░███£££ ",
11456
- " ▒███£££ ",
11457
- " ▓███£££ ",
11458
- " ████£££ ",
11459
- " ░████£££ ",
11460
- " ▒████£££ ",
11461
- " ▓████£££ ",
11462
- " █████£££ ",
11463
- " ░█████£££ ",
11464
- " ▒█████£££ ",
11465
- " ▓█████£££ ",
11466
- " ██████£££ ",
11467
- " ██████£££ "
11468
- ]
11469
- },
11470
- fish: {
11471
- interval: 80,
11472
- frames: [
11473
- "~~~~~~~~~~~~~~~~~~~~",
11474
- "> ~~~~~~~~~~~~~~~~~~",
11475
- "º> ~~~~~~~~~~~~~~~~~",
11476
- "(º> ~~~~~~~~~~~~~~~~",
11477
- "((º> ~~~~~~~~~~~~~~~",
11478
- "<((º> ~~~~~~~~~~~~~~",
11479
- "><((º> ~~~~~~~~~~~~~",
11480
- " ><((º> ~~~~~~~~~~~~",
11481
- "~ ><((º> ~~~~~~~~~~~",
11482
- "~~ <>((º> ~~~~~~~~~~",
11483
- "~~~ ><((º> ~~~~~~~~~",
11484
- "~~~~ <>((º> ~~~~~~~~",
11485
- "~~~~~ ><((º> ~~~~~~~",
11486
- "~~~~~~ <>((º> ~~~~~~",
11487
- "~~~~~~~ ><((º> ~~~~~",
11488
- "~~~~~~~~ <>((º> ~~~~",
11489
- "~~~~~~~~~ ><((º> ~~~",
11490
- "~~~~~~~~~~ <>((º> ~~",
11491
- "~~~~~~~~~~~ ><((º> ~",
11492
- "~~~~~~~~~~~~ <>((º> ",
11493
- "~~~~~~~~~~~~~ ><((º>",
11494
- "~~~~~~~~~~~~~~ <>((º",
11495
- "~~~~~~~~~~~~~~~ ><((",
11496
- "~~~~~~~~~~~~~~~~ <>(",
11497
- "~~~~~~~~~~~~~~~~~ ><",
11498
- "~~~~~~~~~~~~~~~~~~ <",
11499
- "~~~~~~~~~~~~~~~~~~~~"
11500
- ]
11501
- }
11502
- };
11503
- });
11504
-
11505
- // ../../node_modules/.bun/cli-spinners@3.4.0/node_modules/cli-spinners/index.js
11506
- var cli_spinners_default, spinnersList;
11507
- var init_cli_spinners = __esm(() => {
11508
- init_spinners();
11509
- cli_spinners_default = spinners_default;
11510
- spinnersList = Object.keys(spinners_default);
11511
- });
11512
-
11513
- // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/spinner/use-spinner.js
11514
- import { useEffect as useEffect4, useState as useState5 } from "react";
11515
- function useSpinner({ type = "dots" }) {
11516
- const [frame, setFrame] = useState5(0);
11517
- const spinner = cli_spinners_default[type];
11518
- useEffect4(() => {
11519
- const timer = setInterval(() => {
11520
- setFrame((previousFrame) => {
11521
- const isLastFrame = previousFrame === spinner.frames.length - 1;
11522
- return isLastFrame ? 0 : previousFrame + 1;
11523
- });
11524
- }, spinner.interval);
11525
- return () => {
11526
- clearInterval(timer);
11527
- };
11528
- }, [spinner]);
11529
- return {
11530
- frame: spinner.frames[frame] ?? ""
11531
- };
11532
- }
11533
- var init_use_spinner = __esm(() => {
11534
- init_cli_spinners();
11535
- });
11536
-
11537
- // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/spinner/spinner.js
11538
- import React11 from "react";
11539
- import { Box as Box13, Text as Text16 } from "ink";
11540
- function Spinner({ label, type }) {
11541
- const { frame } = useSpinner({ type });
11542
- const { styles } = useComponentTheme("Spinner");
11543
- return React11.createElement(Box13, { ...styles.container() }, React11.createElement(Text16, { ...styles.frame() }, frame), label && React11.createElement(Text16, { ...styles.label() }, label));
11544
- }
11545
- var init_spinner = __esm(() => {
11546
- init_theme16();
11547
- init_use_spinner();
11548
- });
11549
-
11550
- // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/spinner/index.js
11551
- var init_spinner2 = __esm(() => {
11552
- init_spinner();
11553
- init_use_spinner();
11554
- });
11555
-
11556
- // ../../node_modules/.bun/@inkjs+ui@2.0.0+fa875fef9f949ebd/node_modules/@inkjs/ui/build/components/text-input/use-text-input-state.js
11557
- import { useReducer as useReducer3, useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo4 } from "react";
11558
- var init_use_text_input_state = () => {};
11559
-
11560
- // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
11561
- function assembleStyles() {
11562
- const codes = new Map;
11563
- for (const [groupName, group] of Object.entries(styles)) {
11564
- for (const [styleName, style] of Object.entries(group)) {
11565
- styles[styleName] = {
11566
- open: `\x1B[${style[0]}m`,
11567
- close: `\x1B[${style[1]}m`
11568
- };
11569
- group[styleName] = styles[styleName];
11570
- codes.set(style[0], style[1]);
11571
- }
11572
- Object.defineProperty(styles, groupName, {
11573
- value: group,
11574
- enumerable: false
11575
- });
11576
- }
11577
- Object.defineProperty(styles, "codes", {
11578
- value: codes,
11579
- enumerable: false
11580
- });
11581
- styles.color.close = "\x1B[39m";
11582
- styles.bgColor.close = "\x1B[49m";
11583
- styles.color.ansi = wrapAnsi16();
11584
- styles.color.ansi256 = wrapAnsi256();
11585
- styles.color.ansi16m = wrapAnsi16m();
11586
- styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
11587
- styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
11588
- styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
11589
- Object.defineProperties(styles, {
11590
- rgbToAnsi256: {
11591
- value(red, green, blue) {
11592
- if (red === green && green === blue) {
11593
- if (red < 8) {
11594
- return 16;
11595
- }
11596
- if (red > 248) {
11597
- return 231;
11598
- }
11599
- return Math.round((red - 8) / 247 * 24) + 232;
11600
- }
11601
- return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
11602
- },
11603
- enumerable: false
11604
- },
11605
- hexToRgb: {
11606
- value(hex) {
11607
- const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
11608
- if (!matches) {
11609
- return [0, 0, 0];
11610
- }
11611
- let [colorString] = matches;
11612
- if (colorString.length === 3) {
11613
- colorString = [...colorString].map((character) => character + character).join("");
11614
- }
11615
- const integer = Number.parseInt(colorString, 16);
11616
- return [
11617
- integer >> 16 & 255,
11618
- integer >> 8 & 255,
11619
- integer & 255
11620
- ];
11621
- },
11622
- enumerable: false
11623
- },
11624
- hexToAnsi256: {
11625
- value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
11626
- enumerable: false
10100
+ hexToAnsi256: {
10101
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
10102
+ enumerable: false
11627
10103
  },
11628
10104
  ansi256ToAnsi: {
11629
10105
  value(code) {
@@ -12395,9 +10871,9 @@ function applyRailKey(state, ev, catLen, itemLen) {
12395
10871
  return { state: { ...state, focus: clampFocus(state.focus - 1) }, exit: false, act: false };
12396
10872
  }
12397
10873
  if (right) {
12398
- if (state.focus === 2)
12399
- return { state, exit: false, act: false };
12400
- return { state: { ...state, focus: clampFocus(state.focus + 1) }, exit: false, act: false };
10874
+ if (state.focus >= 1)
10875
+ return still;
10876
+ return { state: { ...state, focus: 1 }, exit: false, act: false };
12401
10877
  }
12402
10878
  if (up || down)
12403
10879
  return {
@@ -12734,48 +11210,19 @@ var init_preview = __esm(() => {
12734
11210
  init_scenarios();
12735
11211
  });
12736
11212
 
12737
- // src/tui/sections/catalog.tsx
12738
- var ENGINE_ROOT;
12739
- var init_catalog2 = __esm(() => {
12740
- init_sources();
12741
- ENGINE_ROOT = engineRoot(import.meta.url);
12742
- });
12743
-
12744
11213
  // src/tui/sections/CharacterSection.tsx
12745
11214
  import { Box as Box21, Text as Text26 } from "ink";
12746
11215
  import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
12747
11216
  function CharacterSection(props) {
12748
- const {
12749
- state,
12750
- packs,
12751
- installed,
12752
- activeIds,
12753
- mode,
12754
- detail,
12755
- installStatus,
12756
- errorMsg,
12757
- reducedMotion = false,
12758
- rows,
12759
- tokens,
12760
- glyphs,
12761
- hues,
12762
- nowMs,
12763
- moodShift
12764
- } = props;
12765
- const rosterItems = [
12766
- { id: MODE_ROW, label: `Mode ${glyphs.marker} ${mode}` },
12767
- ...packs.map((id) => ({
12768
- id,
12769
- label: `${activeIds.includes(id) ? glyphs.tabActive : glyphs.tabInactive} ${id}`
12770
- }))
12771
- ];
12772
- const browseItems = packs.map((id) => ({
11217
+ const { state, packs, activeIds, mode, detail, rows, tokens, glyphs, hues, nowMs, moodShift } = props;
11218
+ const modeItems = ["fixed", "random"].map((m) => ({
11219
+ id: m,
11220
+ label: `${mode === m ? glyphs.tabActive : glyphs.tabInactive} ${m}`
11221
+ }));
11222
+ const rosterItems = packs.map((id) => ({
12773
11223
  id,
12774
- label: `${installed.includes(id) ? glyphs.tabActive : glyphs.tabInactive} ${id}`
11224
+ label: `${activeIds.includes(id) ? glyphs.tabActive : glyphs.tabInactive} ${id}`
12775
11225
  }));
12776
- const otherPacks = packs.filter((id) => id !== BUNDLED_PACK);
12777
- const browseEmpty = otherPacks.length === 0;
12778
- const selectedId = packs[Math.min(state.itemCursor, packs.length - 1)] ?? packs[0] ?? "";
12779
11226
  const figW = Math.max(1, ...detail.figure.map((r) => Array.from(r).length));
12780
11227
  const figH = Math.max(1, detail.figure.length);
12781
11228
  const figureRows2 = detail.figure.map((row, y) => /* @__PURE__ */ jsxDEV13(Text26, {
@@ -12785,7 +11232,7 @@ function CharacterSection(props) {
12785
11232
  children: ch
12786
11233
  }, `c-${String(x)}`, false, undefined, this)) : row
12787
11234
  }, `fig-${String(y)}`, false, undefined, this));
12788
- const rosterDetail = detail.ok ? /* @__PURE__ */ jsxDEV13(Box21, {
11235
+ const figure = detail.ok ? /* @__PURE__ */ jsxDEV13(Box21, {
12789
11236
  flexDirection: "column",
12790
11237
  children: [
12791
11238
  /* @__PURE__ */ jsxDEV13(Text26, {
@@ -12810,57 +11257,32 @@ function CharacterSection(props) {
12810
11257
  }, undefined, false, undefined, this)
12811
11258
  ]
12812
11259
  }, undefined, true, undefined, this);
12813
- const browseDetail = /* @__PURE__ */ jsxDEV13(Box21, {
11260
+ const detailNode = state.catCursor === 0 ? /* @__PURE__ */ jsxDEV13(Box21, {
12814
11261
  flexDirection: "column",
12815
11262
  children: [
12816
11263
  /* @__PURE__ */ jsxDEV13(Text26, {
12817
- ...tokens.accent,
12818
- children: detail.displayName
12819
- }, undefined, false, undefined, this),
12820
- installStatus === "installing" ? reducedMotion ? /* @__PURE__ */ jsxDEV13(Text26, {
12821
11264
  ...tokens.textMuted,
12822
- children: [
12823
- "Installing",
12824
- glyphs.ellipsis
12825
- ]
12826
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV13(Spinner, {
12827
- label: "Installing..."
12828
- }, undefined, false, undefined, this) : null,
12829
- installStatus === "error" ? /* @__PURE__ */ jsxDEV13(Text26, {
12830
- ...tokens.critical,
12831
- children: [
12832
- "! ",
12833
- errorMsg ?? "install failed"
12834
- ]
12835
- }, undefined, true, undefined, this) : null,
12836
- installStatus === "idle" && installed.includes(selectedId) ? /* @__PURE__ */ jsxDEV13(Text26, {
12837
- ...tokens.nominal,
12838
- children: "installed"
12839
- }, undefined, false, undefined, this) : null,
12840
- installStatus === "idle" && !installed.includes(selectedId) ? /* @__PURE__ */ jsxDEV13(Text26, {
12841
- ...tokens.textMuted,
12842
- children: "[enter] install"
12843
- }, undefined, false, undefined, this) : null
11265
+ children: mode === "fixed" ? "Shows one fixed character." : "Rotates through the roster each session."
11266
+ }, undefined, false, undefined, this),
11267
+ /* @__PURE__ */ jsxDEV13(Text26, {
11268
+ children: " "
11269
+ }, undefined, false, undefined, this),
11270
+ figure
12844
11271
  ]
12845
- }, undefined, true, undefined, this);
12846
- const items = state.catCursor === 0 ? rosterItems : browseEmpty ? [] : browseItems;
12847
- const body = state.catCursor === 0 ? rosterDetail : browseEmpty ? /* @__PURE__ */ jsxDEV13(Text26, {
12848
- ...tokens.textMuted,
12849
- children: "no other packs available"
12850
- }, undefined, false, undefined, this) : browseDetail;
11272
+ }, undefined, true, undefined, this) : figure;
11273
+ const items = state.catCursor === 0 ? modeItems : rosterItems;
12851
11274
  return /* @__PURE__ */ jsxDEV13(Rail, {
12852
- categories: ["Roster", "Browse"],
11275
+ categories: ["Mode", "Roster"],
12853
11276
  items,
12854
- detail: body,
11277
+ detail: detailNode,
12855
11278
  state,
12856
11279
  rows,
12857
11280
  tokens,
12858
11281
  glyphs
12859
11282
  }, undefined, false, undefined, this);
12860
11283
  }
12861
- var isBlank = (ch) => ch === " " || ch === "⠀", MODE_ROW = "__mode__";
11284
+ var isBlank = (ch) => ch === " " || ch === "⠀";
12862
11285
  var init_CharacterSection = __esm(() => {
12863
- init_packs();
12864
11286
  init_render();
12865
11287
  init_theme2();
12866
11288
  init_widgets();
@@ -13181,35 +11603,41 @@ function statuslineFields(d) {
13181
11603
  id: "currency",
13182
11604
  label: "Currency",
13183
11605
  kind: "text",
13184
- value: d.line.currency,
13185
- raw: d.line.currency,
11606
+ value: d.statusline.currency,
11607
+ raw: d.statusline.currency,
13186
11608
  commit: (c, raw) => {
13187
11609
  const v = raw.trim().toUpperCase();
13188
- return v === "" ? c : { ...c, line: { ...c.line, currency: v } };
11610
+ return v === "" ? c : { ...c, statusline: { ...c.statusline, currency: v } };
13189
11611
  }
13190
11612
  };
13191
11613
  const budget = {
13192
11614
  id: "budget",
13193
11615
  label: "Budget (USD/mo)",
13194
11616
  kind: "number",
13195
- value: d.line.budget === undefined ? "off" : String(d.line.budget),
13196
- raw: d.line.budget === undefined ? "" : String(d.line.budget),
11617
+ value: d.statusline.budget === undefined ? "off" : String(d.statusline.budget),
11618
+ raw: d.statusline.budget === undefined ? "" : String(d.statusline.budget),
13197
11619
  commit: (c, raw) => {
13198
11620
  const t = raw.trim();
13199
11621
  if (t === "")
13200
- return { ...c, line: { currency: c.line.currency, widgets: c.line.widgets } };
11622
+ return {
11623
+ ...c,
11624
+ statusline: { currency: c.statusline.currency, widgets: c.statusline.widgets }
11625
+ };
13201
11626
  const n = Number(t);
13202
- return Number.isFinite(n) && n >= 0 ? { ...c, line: { ...c.line, budget: n } } : c;
11627
+ return Number.isFinite(n) && n >= 0 ? { ...c, statusline: { ...c.statusline, budget: n } } : c;
13203
11628
  }
13204
11629
  };
13205
- const widgets = WIDGET_IDS.map((id) => ({
11630
+ const widgets = WIDGET_IDS2.map((id) => ({
13206
11631
  id: `widget:${id}`,
13207
11632
  label: id,
13208
11633
  kind: "toggle",
13209
- value: onOff(d.line.widgets[id]),
11634
+ value: onOff(d.statusline.widgets[id]),
13210
11635
  toggle: (c) => ({
13211
11636
  ...c,
13212
- line: { ...c.line, widgets: { ...c.line.widgets, [id]: !c.line.widgets[id] } }
11637
+ statusline: {
11638
+ ...c.statusline,
11639
+ widgets: { ...c.statusline.widgets, [id]: !c.statusline.widgets[id] }
11640
+ }
13213
11641
  })
13214
11642
  }));
13215
11643
  return [currency, budget, ...widgets];
@@ -13235,40 +11663,32 @@ function themeSettingsFields(d) {
13235
11663
  }
13236
11664
  ];
13237
11665
  }
13238
- function voiceFields(d) {
13239
- return [
13240
- {
13241
- id: "comments_enabled",
13242
- label: "Comments",
13243
- kind: "toggle",
13244
- value: onOff(d.comments.enabled),
13245
- toggle: (c) => ({ ...c, comments: { enabled: !c.comments.enabled } })
13246
- }
13247
- ];
13248
- }
13249
- function tipsFields(d) {
13250
- return [
13251
- {
13252
- id: "helpful_enabled",
13253
- label: "Enabled",
13254
- kind: "toggle",
13255
- value: onOff(d.helpful.enabled),
13256
- toggle: (c) => ({ ...c, helpful: { ...c.helpful, enabled: !c.helpful.enabled } })
13257
- },
13258
- {
13259
- id: "min_severity",
13260
- label: "Min severity",
13261
- kind: "cycle",
13262
- value: d.helpful.min_severity,
13263
- next: (c) => ({
13264
- ...c,
13265
- helpful: {
13266
- ...c.helpful,
13267
- min_severity: step(SEVERITIES, c.helpful.min_severity, 1)
13268
- }
13269
- })
13270
- }
13271
- ];
11666
+ function commentsFields(d) {
11667
+ const characterComments = {
11668
+ id: "comments_character",
11669
+ label: "Character Comments",
11670
+ kind: "toggle",
11671
+ value: onOff(d.comments.character),
11672
+ toggle: (c) => ({ ...c, comments: { ...c.comments, character: !c.comments.character } })
11673
+ };
11674
+ const helpfulComments = {
11675
+ id: "comments_helpful",
11676
+ label: "Helpful Comments",
11677
+ kind: "toggle",
11678
+ value: onOff(d.comments.helpful),
11679
+ toggle: (c) => ({ ...c, comments: { ...c.comments, helpful: !c.comments.helpful } })
11680
+ };
11681
+ const minSeverity = {
11682
+ id: "min_severity",
11683
+ label: "Min severity",
11684
+ kind: "cycle",
11685
+ value: d.comments.min_severity,
11686
+ next: (c) => ({
11687
+ ...c,
11688
+ comments: { ...c.comments, min_severity: step(SEVERITIES2, c.comments.min_severity, 1) }
11689
+ })
11690
+ };
11691
+ return d.comments.helpful ? [characterComments, helpfulComments, minSeverity] : [characterComments, helpfulComments];
13272
11692
  }
13273
11693
  function networkFields(d) {
13274
11694
  return [
@@ -13304,26 +11724,24 @@ function sectionFields(section2, d) {
13304
11724
  case 1:
13305
11725
  return themeSettingsFields(d);
13306
11726
  case 2:
13307
- return voiceFields(d);
11727
+ return commentsFields(d);
13308
11728
  case 3:
13309
- return tipsFields(d);
13310
- case 4:
13311
11729
  return networkFields(d);
13312
- case 5:
11730
+ case 4:
13313
11731
  return statuslineFields(d);
13314
11732
  default:
13315
11733
  return [];
13316
11734
  }
13317
11735
  }
13318
- var onOff = (b) => b ? "on" : "off", WIDGET_IDS, SEVERITIES, BANDINGS, step = (arr, cur, dir) => {
11736
+ var onOff = (b) => b ? "on" : "off", WIDGET_IDS2, SEVERITIES2, BANDINGS, step = (arr, cur, dir) => {
13319
11737
  const n = arr.length;
13320
11738
  const i = arr.indexOf(cur);
13321
11739
  return arr[((i + dir) % n + n) % n] ?? cur;
13322
11740
  };
13323
11741
  var init_forms = __esm(() => {
13324
11742
  init_sources();
13325
- WIDGET_IDS = Object.keys(DEFAULT_CONFIG.line.widgets);
13326
- SEVERITIES = ["low", "medium", "high", "critical"];
11743
+ WIDGET_IDS2 = Object.keys(DEFAULT_CONFIG.statusline.widgets);
11744
+ SEVERITIES2 = ["low", "medium", "high", "critical"];
13327
11745
  BANDINGS = ["solid", "cycle"];
13328
11746
  });
13329
11747
 
@@ -13384,42 +11802,6 @@ var init_FormSection = __esm(() => {
13384
11802
  init_widgets();
13385
11803
  });
13386
11804
 
13387
- // src/tui/sections/installAsync.ts
13388
- import { spawn } from "node:child_process";
13389
- function installPackAsync(name, engineDir = ENGINE_ROOT, run = spawn) {
13390
- const pkg = packPackageName(name);
13391
- if (!isAllowedPackPackage(pkg)) {
13392
- return Promise.reject(new Error(`ccsidekick: refusing to install off-allowlist pack "${name}"`));
13393
- }
13394
- return new Promise((resolve3, reject) => {
13395
- const child = run("npm", ["install", pkg, "--ignore-scripts"], {
13396
- cwd: engineDir,
13397
- stdio: ["ignore", "ignore", "pipe"]
13398
- });
13399
- let stderr = "";
13400
- child.stderr?.on("data", (chunk) => {
13401
- stderr += String(chunk);
13402
- });
13403
- child.on("error", (err) => {
13404
- reject(err instanceof Error ? err : new Error(String(err)));
13405
- });
13406
- child.on("close", (code) => {
13407
- if (code === 0) {
13408
- resolve3();
13409
- return;
13410
- }
13411
- const detail = stderr.trim();
13412
- const tail = detail.length > 500 ? detail.slice(-500) : detail;
13413
- reject(new Error(`ccsidekick: npm install ${pkg} exited ${String(code)}${tail ? `
13414
- ${tail}` : ""}`));
13415
- });
13416
- });
13417
- }
13418
- var init_installAsync = __esm(() => {
13419
- init_packs();
13420
- init_catalog2();
13421
- });
13422
-
13423
11805
  // src/tui/sections/InstallPanel.tsx
13424
11806
  import { Box as Box24, Text as Text29 } from "ink";
13425
11807
  import { jsxDEV as jsxDEV16 } from "react/jsx-dev-runtime";
@@ -14002,7 +12384,7 @@ function StatuslineSection(props) {
14002
12384
  const widgets = group?.widgets ?? [];
14003
12385
  const widgetItems = widgets.map((id) => ({
14004
12386
  id,
14005
- label: `${config.line.widgets[id] ? glyphs.tabActive : glyphs.tabInactive} ${id}`
12387
+ label: `${config.statusline.widgets[id] ? glyphs.tabActive : glyphs.tabInactive} ${id}`
14006
12388
  }));
14007
12389
  const items = isFormat ? formatItems : widgetItems;
14008
12390
  const formatIdx = Math.min(state.itemCursor, 1);
@@ -14185,13 +12567,11 @@ var init_ThemeSection = __esm(() => {
14185
12567
 
14186
12568
  // src/tui/sections/index.ts
14187
12569
  var init_sections = __esm(() => {
14188
- init_catalog2();
14189
12570
  init_CharacterSection();
14190
12571
  init_configdir();
14191
12572
  init_currencyModel();
14192
12573
  init_forms();
14193
12574
  init_FormSection();
14194
- init_installAsync();
14195
12575
  init_InstallPanel();
14196
12576
  init_StatsSection();
14197
12577
  init_statsView();
@@ -14200,32 +12580,6 @@ var init_sections = __esm(() => {
14200
12580
  init_widgetGroups();
14201
12581
  });
14202
12582
 
14203
- // src/tui/shell/useTransitionFade.ts
14204
- import { useEffect as useEffect8, useState as useState7 } from "react";
14205
- function useTransitionFade(transitionKey, reducedMotion) {
14206
- const [step2, setStep] = useState7(reducedMotion ? FADE_STEPS : 0);
14207
- useEffect8(() => {
14208
- if (reducedMotion) {
14209
- setStep(FADE_STEPS);
14210
- return;
14211
- }
14212
- setStep(0);
14213
- let current = 0;
14214
- const id = setInterval(() => {
14215
- current += 1;
14216
- setStep(current);
14217
- if (current >= FADE_STEPS)
14218
- clearInterval(id);
14219
- }, FADE_STEP_MS);
14220
- return () => {
14221
- clearInterval(id);
14222
- };
14223
- }, [transitionKey, reducedMotion]);
14224
- return step2 / FADE_STEPS;
14225
- }
14226
- var FADE_STEPS = 2, FADE_STEP_MS = 90;
14227
- var init_useTransitionFade = () => {};
14228
-
14229
12583
  // src/tui/shell/AppShell.tsx
14230
12584
  import { Box as Box28, Text as Text33 } from "ink";
14231
12585
  import { jsxDEV as jsxDEV20, Fragment } from "react/jsx-dev-runtime";
@@ -14351,19 +12705,16 @@ function HintBar({ nav, tokens }) {
14351
12705
  }, h.key + h.label, true, undefined, this))
14352
12706
  }, undefined, false, undefined, this);
14353
12707
  }
14354
- function Content({ nav, tokens, glyphs, children, reducedMotion }) {
12708
+ function Content({ nav, tokens, glyphs, children }) {
14355
12709
  const focused = nav.zone === "content";
14356
12710
  const eyebrow = `${focused ? `${glyphs.marker} ` : ""}${SECTIONS[nav.section]?.toUpperCase() ?? ""}`;
14357
- const fade = useTransitionFade(nav.section, reducedMotion ?? false);
14358
- const settled = focused ? tokens.accent : tokens.textMuted;
14359
- const eyebrowStyle = fade >= 1 ? settled : fade > 0 ? { ...tokens.accent, dimColor: true } : tokens.textMuted;
14360
12711
  return /* @__PURE__ */ jsxDEV20(Box28, {
14361
12712
  flexDirection: "column",
14362
12713
  flexGrow: 1,
14363
12714
  paddingLeft: 2,
14364
12715
  children: [
14365
12716
  /* @__PURE__ */ jsxDEV20(Text33, {
14366
- ...eyebrowStyle,
12717
+ ...tokens.accent,
14367
12718
  children: eyebrow
14368
12719
  }, undefined, false, undefined, this),
14369
12720
  /* @__PURE__ */ jsxDEV20(Box28, {
@@ -14419,7 +12770,6 @@ var POPUP_CHROME_ROWS = 6, CONTENT_CHROME_ROWS = 6, CONTENT_CHROME_COLS = 27;
14419
12770
  var init_AppShell = __esm(() => {
14420
12771
  init_nav();
14421
12772
  init_widgets();
14422
- init_useTransitionFade();
14423
12773
  });
14424
12774
 
14425
12775
  // src/tui/shell/findIndex.ts
@@ -14439,7 +12789,7 @@ function buildFindIndex(deps) {
14439
12789
  run: deps.focusField(section2, fieldIndex)
14440
12790
  }));
14441
12791
  });
14442
- const toggles = WIDGET_IDS.map((id) => ({
12792
+ const toggles = WIDGET_IDS2.map((id) => ({
14443
12793
  id: `toggle:${id}`,
14444
12794
  label: `Toggle ${id}`,
14445
12795
  kind: "action",
@@ -14475,7 +12825,7 @@ var init_findIndex = __esm(() => {
14475
12825
  init_nav();
14476
12826
  init_sections();
14477
12827
  init_widgets();
14478
- FORM_SECTIONS = [2, 3, 4];
12828
+ FORM_SECTIONS = [2, 3];
14479
12829
  });
14480
12830
 
14481
12831
  // src/tui/shell/inputRoute.ts
@@ -14487,7 +12837,7 @@ function overlayRoute(overlay, section2, ev) {
14487
12837
  const { input, key } = ev;
14488
12838
  if (overlay === "save")
14489
12839
  return "save";
14490
- if (section2 === 7 && overlay === "none" && key.return === true)
12840
+ if (section2 === 6 && overlay === "none" && key.return === true)
14491
12841
  return "saveSection";
14492
12842
  if (overlay === "find")
14493
12843
  return "find";
@@ -14502,9 +12852,9 @@ function sectionRoute(section2, ev) {
14502
12852
  return "character";
14503
12853
  if (section2 === 1 && isFieldNavKey(ev))
14504
12854
  return "theme";
14505
- if (section2 === 6 && isStatsKey(ev))
12855
+ if (section2 === 5 && isStatsKey(ev))
14506
12856
  return "stats";
14507
- if (section2 === 5 && isFieldNavKey(ev))
12857
+ if (section2 === 4 && isFieldNavKey(ev))
14508
12858
  return "statusline";
14509
12859
  return null;
14510
12860
  }
@@ -14520,7 +12870,7 @@ function routeKey(ctx, ev) {
14520
12870
  if (sectionR !== null)
14521
12871
  return sectionR;
14522
12872
  }
14523
- if (section2 === 7 && overlay === "none" && ev.input === " ")
12873
+ if (section2 === 6 && overlay === "none" && ev.input === " ")
14524
12874
  return "saveToggle";
14525
12875
  if (overlay === "none" && zone === "content" && isFieldNavKey(ev))
14526
12876
  return "content";
@@ -14533,7 +12883,7 @@ var init_inputRoute = __esm(() => {
14533
12883
  });
14534
12884
 
14535
12885
  // src/tui/shell/saveTarget.ts
14536
- import { existsSync as existsSync8, readFileSync as readFileSync12 } from "node:fs";
12886
+ import { existsSync as existsSync8, readFileSync as readFileSync13 } from "node:fs";
14537
12887
  import { join as join22 } from "node:path";
14538
12888
  function chipFor(targets) {
14539
12889
  if (targets.every((t) => t.scope === "global"))
@@ -14546,7 +12896,7 @@ function alreadyWired(settingsPath) {
14546
12896
  if (!existsSync8(settingsPath))
14547
12897
  return false;
14548
12898
  try {
14549
- const parsed = JSON.parse(readFileSync12(settingsPath, "utf8"));
12899
+ const parsed = JSON.parse(readFileSync13(settingsPath, "utf8"));
14550
12900
  return isOurStatusLine(parsed.statusLine);
14551
12901
  } catch {
14552
12902
  return false;
@@ -14664,10 +13014,10 @@ function savePreviewSet(config, installed, packs) {
14664
13014
  }
14665
13015
 
14666
13016
  // src/tui/shell/scenarioBodies.ts
14667
- import { useEffect as useEffect9, useState as useState8 } from "react";
13017
+ import { useEffect as useEffect8, useState as useState7 } from "react";
14668
13018
  function usePreviewBody(active, scenario, draft, columns, noColor) {
14669
- const [body, setBody] = useState8("");
14670
- useEffect9(() => {
13019
+ const [body, setBody] = useState7("");
13020
+ useEffect8(() => {
14671
13021
  if (!active) {
14672
13022
  setBody("");
14673
13023
  return;
@@ -14675,9 +13025,9 @@ function usePreviewBody(active, scenario, draft, columns, noColor) {
14675
13025
  const id = setTimeout(() => {
14676
13026
  const previewConfig = {
14677
13027
  ...draft,
14678
- line: {
14679
- ...draft.line,
14680
- widgets: { ...draft.line.widgets, compactions: true, todo: true }
13028
+ statusline: {
13029
+ ...draft.statusline,
13030
+ widgets: { ...draft.statusline.widgets, compactions: true, todo: true }
14681
13031
  }
14682
13032
  };
14683
13033
  setBody(renderScenario(scenario, previewConfig, { columns, noColor }));
@@ -14689,8 +13039,8 @@ function usePreviewBody(active, scenario, draft, columns, noColor) {
14689
13039
  return body;
14690
13040
  }
14691
13041
  function useSaveCharacterBody(active, character, draft, columns) {
14692
- const [body, setBody] = useState8("");
14693
- useEffect9(() => {
13042
+ const [body, setBody] = useState7("");
13043
+ useEffect8(() => {
14694
13044
  if (!active) {
14695
13045
  setBody("");
14696
13046
  return;
@@ -14704,9 +13054,9 @@ function useSaveCharacterBody(active, character, draft, columns) {
14704
13054
  const previewConfig = {
14705
13055
  ...draft,
14706
13056
  character: { ...draft.character, mode: "fixed", name: character },
14707
- line: {
14708
- ...draft.line,
14709
- widgets: { ...draft.line.widgets, compactions: true, todo: true }
13057
+ statusline: {
13058
+ ...draft.statusline,
13059
+ widgets: { ...draft.statusline.widgets, compactions: true, todo: true }
14710
13060
  }
14711
13061
  };
14712
13062
  setBody(renderScenario(scenario, previewConfig, { columns, noColor: false }));
@@ -14718,8 +13068,8 @@ function useSaveCharacterBody(active, character, draft, columns) {
14718
13068
  return body;
14719
13069
  }
14720
13070
  function useThemeDetailBody(active, itemCursor, themeKeys, scenarioIndex, draft, columns) {
14721
- const [body, setBody] = useState8("");
14722
- useEffect9(() => {
13071
+ const [body, setBody] = useState7("");
13072
+ useEffect8(() => {
14723
13073
  if (!active) {
14724
13074
  setBody("");
14725
13075
  return;
@@ -14751,7 +13101,7 @@ var init_scenarioBodies = __esm(() => {
14751
13101
 
14752
13102
  // src/tui/shell/useMouseWheel.ts
14753
13103
  import { useStdin } from "ink";
14754
- import { useEffect as useEffect10 } from "react";
13104
+ import { useEffect as useEffect9 } from "react";
14755
13105
  function parseMouseWheel(data) {
14756
13106
  let dx = 0;
14757
13107
  let dy = 0;
@@ -14777,7 +13127,7 @@ function parseMouseWheel(data) {
14777
13127
  }
14778
13128
  function useMouseWheel(active, onScroll) {
14779
13129
  const { stdin, setRawMode, isRawModeSupported } = useStdin();
14780
- useEffect10(() => {
13130
+ useEffect9(() => {
14781
13131
  if (!active || !isRawModeSupported)
14782
13132
  return;
14783
13133
  setRawMode(true);
@@ -14800,16 +13150,10 @@ var init_useMouseWheel = __esm(() => {
14800
13150
  });
14801
13151
 
14802
13152
  // src/tui/shell/Dashboard.tsx
14803
- import { readFileSync as readFileSync13 } from "node:fs";
13153
+ import { readFileSync as readFileSync14 } from "node:fs";
14804
13154
  import { join as join23 } from "node:path";
14805
13155
  import { Box as Box30, Text as Text35, useApp as useApp2, useInput as useInput8 } from "ink";
14806
- import {
14807
- useCallback as useCallback6,
14808
- useEffect as useEffect11,
14809
- useMemo as useMemo9,
14810
- useRef,
14811
- useState as useState9
14812
- } from "react";
13156
+ import { useCallback as useCallback6, useMemo as useMemo9, useState as useState8 } from "react";
14813
13157
  import { jsxDEV as jsxDEV22 } from "react/jsx-dev-runtime";
14814
13158
  function Dashboard(props) {
14815
13159
  const {
@@ -14822,63 +13166,52 @@ function Dashboard(props) {
14822
13166
  rows
14823
13167
  } = props;
14824
13168
  const app = useApp2();
14825
- const mounted = useRef(true);
14826
- useEffect11(() => {
14827
- mounted.current = true;
14828
- return () => {
14829
- mounted.current = false;
14830
- };
14831
- }, []);
14832
- const [nav, setNav] = useState9(INITIAL_NAV);
14833
- const [targets, setTargets] = useState9(props.targets);
13169
+ const [nav, setNav] = useState8(INITIAL_NAV);
13170
+ const [targets, setTargets] = useState8(props.targets);
14834
13171
  const configDir2 = targets[0]?.dir ?? "";
14835
13172
  const root = join23(configDir2, "ccsidekick");
14836
- const [draft, setDraft] = useState9(() => seed(configDir2, initialConfig));
14837
- const [dirty2, setDirty] = useState9(false);
14838
- const [cursor4, setCursor] = useState9(0);
14839
- const [editing, setEditing] = useState9(false);
14840
- const [buffer, setBuffer] = useState9("");
14841
- const [error, setError] = useState9(null);
14842
- const [scenarioIndex, setScenarioIndex] = useState9(0);
14843
- const [previewNoColor, setPreviewNoColor] = useState9(false);
14844
- const [previewNarrow, setPreviewNarrow] = useState9(false);
14845
- const [installedScan, setInstalled] = useState9(() => props.installed ?? listInstalledPacks(ENGINE_ROOT));
14846
- const installed = useMemo9(() => installedScan.includes(BUNDLED_PACK) ? installedScan : [BUNDLED_PACK, ...installedScan], [installedScan]);
14847
- const [characterRail, setCharacterRail] = useState9({
13173
+ const [draft, setDraft] = useState8(() => seed(configDir2, initialConfig));
13174
+ const [dirty2, setDirty] = useState8(props.initialDirty ?? false);
13175
+ const [cursor4, setCursor] = useState8(0);
13176
+ const [editing, setEditing] = useState8(false);
13177
+ const [buffer, setBuffer] = useState8("");
13178
+ const [error, setError] = useState8(null);
13179
+ const [scenarioIndex, setScenarioIndex] = useState8(0);
13180
+ const [previewNoColor, setPreviewNoColor] = useState8(false);
13181
+ const [previewNarrow, setPreviewNarrow] = useState8(false);
13182
+ const [characterRail, setCharacterRail] = useState8({
14848
13183
  focus: 0,
14849
13184
  catCursor: 0,
14850
13185
  itemCursor: 0
14851
13186
  });
14852
- const [themeRail, setThemeRail] = useState9({
13187
+ const [themeRail, setThemeRail] = useState8({
14853
13188
  focus: 0,
14854
13189
  catCursor: 0,
14855
13190
  itemCursor: 0
14856
13191
  });
14857
- const [statuslineRail, setStatuslineRail] = useState9({
13192
+ const [statuslineRail, setStatuslineRail] = useState8({
14858
13193
  focus: 0,
14859
13194
  catCursor: 0,
14860
13195
  itemCursor: 0
14861
13196
  });
14862
- const [installStatus, setInstallStatus] = useState9("idle");
14863
- const [installError, setInstallError] = useState9(null);
14864
- const [query, setQuery] = useState9("");
14865
- const [overlayCursor, setOverlayCursor] = useState9(0);
14866
- const [currencyQuery, setCurrencyQuery] = useState9("");
14867
- const [statsDimension, setStatsDimension] = useState9(0);
14868
- const [statsWindow, setStatsWindow] = useState9(0);
14869
- const [statsFocus, setStatsFocus] = useState9(0);
14870
- const [statsEntry, setStatsEntry] = useState9(0);
14871
- const [statsScrollX, setStatsScrollX] = useState9(0);
14872
- const [statsScrollY, setStatsScrollY] = useState9(0);
14873
- const [saveCharIdx, setSaveCharIdx] = useState9(0);
14874
- const [saveScrollX, setSaveScrollX] = useState9(0);
14875
- const [saveScrollY, setSaveScrollY] = useState9(0);
14876
- const packs = props.packs ?? dedupe([...FIRST_PARTY_PACKS, ...installed]);
13197
+ const [query, setQuery] = useState8("");
13198
+ const [overlayCursor, setOverlayCursor] = useState8(0);
13199
+ const [currencyQuery, setCurrencyQuery] = useState8("");
13200
+ const [statsDimension, setStatsDimension] = useState8(0);
13201
+ const [statsWindow, setStatsWindow] = useState8(0);
13202
+ const [statsFocus, setStatsFocus] = useState8(0);
13203
+ const [statsEntry, setStatsEntry] = useState8(0);
13204
+ const [statsScrollX, setStatsScrollX] = useState8(0);
13205
+ const [statsScrollY, setStatsScrollY] = useState8(0);
13206
+ const [saveCharIdx, setSaveCharIdx] = useState8(0);
13207
+ const [saveScrollX, setSaveScrollX] = useState8(0);
13208
+ const [saveScrollY, setSaveScrollY] = useState8(0);
13209
+ const [done, setDone] = useState8(false);
13210
+ const packs = props.packs ?? [...PACKS];
13211
+ const installed = packs;
14877
13212
  const rosterList = packs;
14878
- const browseList = packs;
14879
- const install = props.install ?? installPackAsync;
14880
13213
  const themeSettingRows = themeSettingsFields(draft);
14881
- const activeIds = draft.character.mode === "fixed" ? [draft.character.name] : draft.character.roster;
13214
+ const activeIds = draft.character.mode === "fixed" ? [draft.character.name] : draft.character.roster.length > 0 ? draft.character.roster : packs;
14882
13215
  const savePreviewChars = savePreviewSet(draft, installed, packs);
14883
13216
  const saveCharIdxClamped = Math.min(saveCharIdx, savePreviewChars.length - 1);
14884
13217
  const saveCharName = savePreviewChars[saveCharIdxClamped] ?? "batman";
@@ -14886,7 +13219,9 @@ function Dashboard(props) {
14886
13219
  const ch = draft.character;
14887
13220
  if (ch.mode === "fixed")
14888
13221
  return { ...draft, character: { ...ch, name: id } };
14889
- const roster = ch.roster.includes(id) ? ch.roster.filter((r) => r !== id) : [...ch.roster, id];
13222
+ const current = ch.roster.length > 0 ? ch.roster : packs;
13223
+ const next = current.includes(id) ? current.filter((r) => r !== id) : [...current, id];
13224
+ const roster = next.length === packs.length || next.length === 0 ? [] : next;
14890
13225
  return { ...draft, character: { ...ch, roster } };
14891
13226
  };
14892
13227
  const columns = cols ?? 80;
@@ -14920,7 +13255,6 @@ function Dashboard(props) {
14920
13255
  const theme15 = themeTable[draft.theme.name] ?? THEMES.houston;
14921
13256
  const tokens = resolveTokens(theme15, capability);
14922
13257
  const glyphs = glyphSet(false);
14923
- const reducedMotion = props.reducedMotion ?? detectReducedMotion(env2);
14924
13258
  const fields = sectionFields(nav.section, draft);
14925
13259
  const change = (next) => {
14926
13260
  setDraft(next);
@@ -14970,13 +13304,13 @@ function Dashboard(props) {
14970
13304
  change(spec.toggle(draft));
14971
13305
  },
14972
13306
  openCurrencyPicker: () => {
14973
- setNav({ ...nav, section: 5, zone: "content", overlay: "currency" });
13307
+ setNav({ ...nav, section: 4, zone: "content", overlay: "currency" });
14974
13308
  setStatuslineRail((s) => ({ ...s, focus: 1, catCursor: 0, itemCursor: 0 }));
14975
13309
  setCurrencyQuery("");
14976
13310
  setOverlayCursor(0);
14977
13311
  },
14978
13312
  beginBudgetEdit: () => {
14979
- setNav({ ...nav, section: 5, zone: "content", overlay: "none" });
13313
+ setNav({ ...nav, section: 4, zone: "content", overlay: "none" });
14980
13314
  setStatuslineRail((s) => ({ ...s, focus: 1, catCursor: 0, itemCursor: 1 }));
14981
13315
  setCursor(1);
14982
13316
  setBuffer(statuslineFields(draft)[1]?.raw ?? "");
@@ -15053,7 +13387,7 @@ function Dashboard(props) {
15053
13387
  setCurrencyQuery("");
15054
13388
  setOverlayCursor(0);
15055
13389
  if (code !== undefined)
15056
- change({ ...draft, line: { ...draft.line, currency: code } });
13390
+ change({ ...draft, statusline: { ...draft.statusline, currency: code } });
15057
13391
  return;
15058
13392
  }
15059
13393
  if (key.backspace || key.delete) {
@@ -15078,59 +13412,22 @@ function Dashboard(props) {
15078
13412
  };
15079
13413
  const activateCharacter = (state) => {
15080
13414
  if (state.catCursor === 0) {
15081
- if (state.itemCursor === 0) {
15082
- const ch = draft.character;
15083
- change({
15084
- ...draft,
15085
- character: { ...ch, mode: ch.mode === "fixed" ? "random" : "fixed" }
15086
- });
15087
- return;
15088
- }
15089
- const id2 = rosterList[state.itemCursor - 1];
15090
- if (id2 !== undefined)
15091
- change(selectCharacter(id2));
15092
- return;
15093
- }
15094
- const id = browseList[Math.min(state.itemCursor, browseList.length - 1)];
15095
- if (id === undefined)
15096
- return;
15097
- if (installStatus === "installing")
15098
- return;
15099
- if (!installed.includes(id)) {
15100
- setInstallStatus("installing");
15101
- setInstallError(null);
15102
- install(id).then(() => {
15103
- if (!mounted.current)
15104
- return;
15105
- setInstalled((prev) => prev.includes(id) ? prev : [...prev, id]);
15106
- setInstallStatus("idle");
15107
- }).catch((e) => {
15108
- if (!mounted.current)
15109
- return;
15110
- setInstallStatus("error");
15111
- setInstallError(e instanceof Error ? e.message : String(e));
15112
- });
13415
+ const mode = state.itemCursor === 0 ? "fixed" : "random";
13416
+ change({ ...draft, character: { ...draft.character, mode } });
15113
13417
  return;
15114
13418
  }
15115
- change(selectCharacter(id));
13419
+ const id = rosterList[Math.min(state.itemCursor, rosterList.length - 1)];
13420
+ if (id !== undefined)
13421
+ change(selectCharacter(id));
15116
13422
  };
15117
13423
  const handleCharacterKey = (input, key) => {
15118
- const listLength = characterRail.catCursor === 0 ? rosterList.length + 1 : browseList.length;
15119
- const r = applyRailKey(characterRail, { input, key }, 2, listLength);
15120
- let next = r.state;
15121
- if (r.state.catCursor !== characterRail.catCursor) {
15122
- const delta = r.state.catCursor === 0 ? 1 : -1;
15123
- const nextLen = r.state.catCursor === 0 ? rosterList.length + 1 : browseList.length;
15124
- next = {
15125
- ...r.state,
15126
- itemCursor: Math.max(0, Math.min(nextLen - 1, r.state.itemCursor + delta))
15127
- };
15128
- }
15129
- setCharacterRail(next);
13424
+ const listLen = characterRail.catCursor === 0 ? 2 : rosterList.length;
13425
+ const r = applyRailKey(characterRail, { input, key }, 2, listLen);
13426
+ setCharacterRail(r.state);
15130
13427
  if (r.exit)
15131
13428
  setNav({ ...nav, zone: "sidebar" });
15132
13429
  if (r.act)
15133
- activateCharacter(next);
13430
+ activateCharacter(r.state);
15134
13431
  };
15135
13432
  const activateThemeRow = (state) => {
15136
13433
  if (state.catCursor === 0) {
@@ -15243,7 +13540,7 @@ function Dashboard(props) {
15243
13540
  const handleSaveKey = (input, key) => {
15244
13541
  if (input === "y" || key.return) {
15245
13542
  if (runInstall())
15246
- setNav({ ...nav, overlay: "none" });
13543
+ setDone(true);
15247
13544
  } else if (key.escape) {
15248
13545
  setNav({ ...nav, overlay: "none" });
15249
13546
  } else if (key.leftArrow) {
@@ -15319,6 +13616,14 @@ function Dashboard(props) {
15319
13616
  quitNow();
15320
13617
  };
15321
13618
  useInput8((input, key) => {
13619
+ if (done) {
13620
+ quitNow();
13621
+ return;
13622
+ }
13623
+ if (key.ctrl && input === "w" && props.onWizard) {
13624
+ props.onWizard(draft, dirty2);
13625
+ return;
13626
+ }
15322
13627
  const route = routeKey({ editing, zone: nav.zone, overlay: nav.overlay, section: nav.section }, { input, key });
15323
13628
  switch (route) {
15324
13629
  case "editing":
@@ -15366,8 +13671,9 @@ function Dashboard(props) {
15366
13671
  const themeDetailCols = Math.max(20, columns - 73);
15367
13672
  const scenario = useMemo9(() => SCENARIOS[scenarioIndex] ?? SCENARIOS[0] ?? { label: "none" }, [scenarioIndex]);
15368
13673
  const previewBody = usePreviewBody(nav.overlay === "preview", scenario, draft, previewBodyCols, previewNoColor);
15369
- const detailIdx = characterRail.catCursor === 0 ? Math.max(0, Math.min(characterRail.itemCursor - 1, rosterList.length - 1)) : Math.min(characterRail.itemCursor, browseList.length - 1);
15370
- const selectedCharId = (characterRail.catCursor === 0 ? rosterList : browseList)[detailIdx] ?? packs[0] ?? "batman";
13674
+ const rosterIdx = Math.max(0, Math.min(characterRail.itemCursor, rosterList.length - 1));
13675
+ const selectedCharId = characterRail.catCursor === 1 ? rosterList[rosterIdx] ?? packs[0] ?? "batman" : packs.includes(draft.character.name) ? draft.character.name : packs[0] ?? "batman";
13676
+ const figureHues = draft.theme.name === CHARACTER_THEME ? themeTable[selectedCharId]?.hues ?? THEMES.houston.hues : theme15.hues;
15371
13677
  const characterDetail = useMemo9(() => {
15372
13678
  const res = loadPack(selectedCharId);
15373
13679
  if (!res.ok)
@@ -15396,7 +13702,7 @@ function Dashboard(props) {
15396
13702
  const themeDetailBody = useThemeDetailBody(nav.section === 1 && themeRail.catCursor === 0, themeRail.itemCursor, themeKeys, scenarioIndex, draft, themeDetailCols);
15397
13703
  const clock = props.clock ?? systemClock;
15398
13704
  const metrics = useMemo9(() => props.metrics ?? loadMetrics(root, clock), [props.metrics, root, clock]);
15399
- const statsBoard = statsView(metrics, statsDimension, statsWindow, statsEntry, draft.line.budget);
13705
+ const statsBoard = statsView(metrics, statsDimension, statsWindow, statsEntry, draft.statusline.budget);
15400
13706
  const statsAxisCount = statsBoard.entry !== null ? 3 : 2;
15401
13707
  const contentRows = Math.max(1, height - CONTENT_CHROME_ROWS);
15402
13708
  const contentCols = Math.max(20, columns - CONTENT_CHROME_COLS);
@@ -15409,7 +13715,7 @@ function Dashboard(props) {
15409
13715
  setStatsScrollX((x) => clampScroll(x + dx, statsBoardW, contentCols));
15410
13716
  setStatsScrollY((y) => clampScroll(y + dy, statsBoardH, statsBoardViewRows));
15411
13717
  }, [statsBoardW, contentCols, statsBoardH, statsBoardViewRows]);
15412
- const statsFocused = nav.section === 6 && nav.zone === "content" && nav.overlay === "none";
13718
+ const statsFocused = nav.section === 5 && nav.zone === "content" && nav.overlay === "none";
15413
13719
  const wheelActive = nav.overlay === "save" || statsFocused;
15414
13720
  const onWheel = useCallback6((dx, dy) => {
15415
13721
  if (nav.overlay === "save")
@@ -15418,6 +13724,36 @@ function Dashboard(props) {
15418
13724
  scrollStats(dx, dy);
15419
13725
  }, [nav.overlay, scrollSave, scrollStats]);
15420
13726
  useMouseWheel(wheelActive, onWheel);
13727
+ if (done) {
13728
+ return /* @__PURE__ */ jsxDEV22(Box30, {
13729
+ width: columns,
13730
+ height,
13731
+ flexDirection: "column",
13732
+ paddingX: 1,
13733
+ borderStyle: "round",
13734
+ borderColor: tokens.frame.color ?? "gray",
13735
+ children: [
13736
+ /* @__PURE__ */ jsxDEV22(Text35, {
13737
+ ...tokens.accent,
13738
+ children: "ccsidekick"
13739
+ }, undefined, false, undefined, this),
13740
+ /* @__PURE__ */ jsxDEV22(Box30, {
13741
+ marginTop: 1,
13742
+ flexDirection: "column",
13743
+ children: [
13744
+ /* @__PURE__ */ jsxDEV22(Text35, {
13745
+ ...tokens.nominal,
13746
+ children: "✓ Saved. Press any key to finish."
13747
+ }, undefined, false, undefined, this),
13748
+ /* @__PURE__ */ jsxDEV22(Text35, {
13749
+ ...tokens.textMuted,
13750
+ children: "Restart Claude Code to see your status line."
13751
+ }, undefined, false, undefined, this)
13752
+ ]
13753
+ }, undefined, true, undefined, this)
13754
+ ]
13755
+ }, undefined, true, undefined, this);
13756
+ }
15421
13757
  if (breakpoint === "floor") {
15422
13758
  return /* @__PURE__ */ jsxDEV22(Popup, {
15423
13759
  title: "Terminal too small",
@@ -15438,7 +13774,7 @@ function Dashboard(props) {
15438
13774
  }, undefined, true, undefined, this);
15439
13775
  }
15440
13776
  const buildSectionBody = () => {
15441
- if (nav.section === 7)
13777
+ if (nav.section === 6)
15442
13778
  return /* @__PURE__ */ jsxDEV22(InstallPanel, {
15443
13779
  scope: chipFor(targets),
15444
13780
  dirty: dirty2,
@@ -15449,17 +13785,13 @@ function Dashboard(props) {
15449
13785
  return /* @__PURE__ */ jsxDEV22(CharacterSection, {
15450
13786
  state: characterRail,
15451
13787
  packs,
15452
- installed,
15453
13788
  activeIds,
15454
13789
  mode: draft.character.mode,
15455
13790
  detail: characterDetail,
15456
- installStatus,
15457
- ...installError !== null ? { errorMsg: installError } : {},
15458
13791
  rows: contentRows,
15459
- reducedMotion,
15460
13792
  tokens,
15461
13793
  glyphs,
15462
- hues: theme15.hues,
13794
+ hues: figureHues,
15463
13795
  nowMs: 0,
15464
13796
  moodShift: draft.theme.mood_shift
15465
13797
  }, undefined, false, undefined, this);
@@ -15475,7 +13807,7 @@ function Dashboard(props) {
15475
13807
  tokens,
15476
13808
  glyphs
15477
13809
  }, undefined, false, undefined, this);
15478
- if (nav.section === 5)
13810
+ if (nav.section === 4)
15479
13811
  return /* @__PURE__ */ jsxDEV22(StatuslineSection, {
15480
13812
  state: statuslineRail,
15481
13813
  config: draft,
@@ -15485,7 +13817,7 @@ function Dashboard(props) {
15485
13817
  tokens,
15486
13818
  glyphs
15487
13819
  }, undefined, false, undefined, this);
15488
- if (nav.section === 6)
13820
+ if (nav.section === 5)
15489
13821
  return /* @__PURE__ */ jsxDEV22(StatsSection, {
15490
13822
  dimension: statsDimension,
15491
13823
  windowIdx: statsWindow,
@@ -15606,7 +13938,6 @@ function Dashboard(props) {
15606
13938
  configDir: configDir2,
15607
13939
  scope: chipFor(targets),
15608
13940
  dirty: dirty2,
15609
- reducedMotion,
15610
13941
  columns,
15611
13942
  rows: height,
15612
13943
  collapsed: breakpoint === "narrow" && nav.zone === "content",
@@ -15614,11 +13945,11 @@ function Dashboard(props) {
15614
13945
  children: content
15615
13946
  }, undefined, false, undefined, this);
15616
13947
  }
15617
- var dedupe = (xs) => [...new Set(xs)], seed = (configDir2, initial) => {
13948
+ var seed = (configDir2, initial) => {
15618
13949
  if (initial)
15619
13950
  return initial;
15620
13951
  try {
15621
- return loadConfig(readFileSync13(join23(configDir2, "ccsidekick", "config.toml"), "utf8"));
13952
+ return loadConfig(readFileSync14(join23(configDir2, "ccsidekick", "config.toml"), "utf8"));
15622
13953
  } catch {
15623
13954
  return loadConfig("");
15624
13955
  }
@@ -15650,99 +13981,30 @@ var init_wordmark = __esm(() => {
15650
13981
  " ██████╗ ██████╗███████╗██╗██████╗ ███████╗██╗ ██╗██╗ ██████╗██╗ ██╗",
15651
13982
  "██╔════╝██╔════╝██╔════╝██║██╔══██╗██╔════╝██║ ██╔╝██║██╔════╝██║ ██╔╝",
15652
13983
  "██║ ██║ ███████╗██║██║ ██║█████╗ █████╔╝ ██║██║ █████╔╝ ",
15653
- "██║ ██║ ╚════██║██║██║ ██║██╔══╝ ██╔═██╗ ██║██║ ██╔═██╗ ",
15654
- "╚██████╗╚██████╗███████║██║██████╔╝███████╗██║ ██╗██║╚██████╗██║ ██╗",
15655
- " ╚═════╝ ╚═════╝╚══════╝╚═╝╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝╚═╝ ╚═╝"
15656
- ];
15657
- LOGO_MIN_COLUMNS = WORDMARK_WIDTH + 2;
15658
- });
15659
-
15660
- // src/tui/shell/wordmarkColor.ts
15661
- var rgbToHsv = ([r, g, b]) => {
15662
- const rn = r / 255;
15663
- const gn = g / 255;
15664
- const bn = b / 255;
15665
- const mx = Math.max(rn, gn, bn);
15666
- const mn = Math.min(rn, gn, bn);
15667
- const d = mx - mn;
15668
- let h = 0;
15669
- if (d !== 0) {
15670
- if (mx === rn)
15671
- h = (gn - bn) / d % 6;
15672
- else if (mx === gn)
15673
- h = (bn - rn) / d + 2;
15674
- else
15675
- h = (rn - gn) / d + 4;
15676
- h *= 60;
15677
- if (h < 0)
15678
- h += 360;
15679
- }
15680
- const s = mx === 0 ? 0 : d / mx;
15681
- return [h, s, mx];
15682
- }, hsvToRgb = ([h, s, v]) => {
15683
- const c = v * s;
15684
- const hp = h / 60;
15685
- const x = c * (1 - Math.abs(hp % 2 - 1));
15686
- let r = 0;
15687
- let g = 0;
15688
- let b = 0;
15689
- if (hp < 1)
15690
- [r, g, b] = [c, x, 0];
15691
- else if (hp < 2)
15692
- [r, g, b] = [x, c, 0];
15693
- else if (hp < 3)
15694
- [r, g, b] = [0, c, x];
15695
- else if (hp < 4)
15696
- [r, g, b] = [0, x, c];
15697
- else if (hp < 5)
15698
- [r, g, b] = [x, 0, c];
15699
- else
15700
- [r, g, b] = [c, 0, x];
15701
- const m = v - c;
15702
- return [(r + m) * 255, (g + m) * 255, (b + m) * 255];
15703
- }, lerpHue = (a, b, t) => {
15704
- let diff = b - a;
15705
- if (diff > 180)
15706
- diff -= 360;
15707
- else if (diff < -180)
15708
- diff += 360;
15709
- let h = a + diff * t;
15710
- if (h < 0)
15711
- h += 360;
15712
- else if (h >= 360)
15713
- h -= 360;
15714
- return h;
15715
- }, lerp2 = (a, b, t) => a + (b - a) * t, frac2 = (x) => x - Math.floor(x), smoothstep2 = (x) => x * x * (3 - 2 * x), wordmarkColor = (stops, x, y, w, h, nowMs) => {
15716
- const phase = frac2(nowMs / SHIMMER_PERIOD_MS);
15717
- const t = (x / Math.max(1, w - 1) + y / Math.max(1, h - 1)) / 2 + phase;
15718
- const n = stops.length;
15719
- const p = frac2(t) * n;
15720
- const i = Math.floor(p);
15721
- const f = smoothstep2(p - i);
15722
- const a = rgbToHsv(xtermToRgb(stops[i % n] ?? 0));
15723
- const b = rgbToHsv(xtermToRgb(stops[(i + 1) % n] ?? 0));
15724
- const hsv = [lerpHue(a[0], b[0], f), lerp2(a[1], b[1], f), lerp2(a[2], b[2], f)];
15725
- return rgbToXterm(hsvToRgb(hsv));
15726
- };
15727
- var init_wordmarkColor = __esm(() => {
15728
- init_domain();
15729
- init_render();
13984
+ "██║ ██║ ╚════██║██║██║ ██║██╔══╝ ██╔═██╗ ██║██║ ██╔═██╗ ",
13985
+ "╚██████╗╚██████╗███████║██║██████╔╝███████╗██║ ██╗██║╚██████╗██║ ██╗",
13986
+ " ╚═════╝ ╚═════╝╚══════╝╚═╝╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝╚═╝ ╚═╝"
13987
+ ];
13988
+ LOGO_MIN_COLUMNS = WORDMARK_WIDTH + 2;
15730
13989
  });
15731
13990
 
15732
13991
  // src/tui/shell/Logo.tsx
15733
13992
  import { Box as Box31, Text as Text36 } from "ink";
15734
13993
  import { jsxDEV as jsxDEV23 } from "react/jsx-dev-runtime";
15735
- function Logo({ hues, capability, reducedMotion, nowMs, tokens }) {
15736
- const w = WORDMARK_WIDTH;
15737
- const h = WORDMARK.length;
15738
- const frozen = capability === "full" && reducedMotion ? gradient(hues, w) : null;
15739
- const solidStyle = (x, y) => {
13994
+ function brighten(index) {
13995
+ const [r, g, b] = xtermToRgb(index);
13996
+ const mx = Math.max(r, g, b, 1);
13997
+ const scale = 255 / mx;
13998
+ return rgbToXterm([r * scale, g * scale, b * scale]);
13999
+ }
14000
+ function Logo({ hues, capability, tokens }) {
14001
+ const ramp = capability === "full" ? gradient(hues, WORDMARK_WIDTH).map(brighten) : null;
14002
+ const solidStyle = (x) => {
15740
14003
  if (capability === "none")
15741
14004
  return { bold: true };
15742
14005
  if (capability === "basic")
15743
14006
  return tokens.accent;
15744
- const idx = frozen !== null ? frozen[x] ?? hues[0] ?? 0 : wordmarkColor(hues, x, y, w, h, nowMs);
15745
- return { color: hexForXterm(idx), bold: true };
14007
+ return { color: hexForXterm(ramp?.[x] ?? brighten(hues[0] ?? 0)), bold: true };
15746
14008
  };
15747
14009
  return /* @__PURE__ */ jsxDEV23(Box31, {
15748
14010
  flexDirection: "column",
@@ -15755,7 +14017,7 @@ function Logo({ hues, capability, reducedMotion, nowMs, tokens }) {
15755
14017
  }, key, false, undefined, this);
15756
14018
  if (ch === SOLID)
15757
14019
  return /* @__PURE__ */ jsxDEV23(Text36, {
15758
- ...solidStyle(x, y),
14020
+ ...solidStyle(x),
15759
14021
  children: ch
15760
14022
  }, key, false, undefined, this);
15761
14023
  return /* @__PURE__ */ jsxDEV23(Text36, {
@@ -15770,7 +14032,6 @@ var init_Logo = __esm(() => {
15770
14032
  init_render();
15771
14033
  init_theme2();
15772
14034
  init_wordmark();
15773
- init_wordmarkColor();
15774
14035
  init_wordmark();
15775
14036
  });
15776
14037
 
@@ -15788,8 +14049,6 @@ function Welcome({
15788
14049
  atFloor,
15789
14050
  hues,
15790
14051
  capability,
15791
- reducedMotion,
15792
- nowMs,
15793
14052
  tokens
15794
14053
  }) {
15795
14054
  const showLogo = columns >= LOGO_MIN_COLUMNS;
@@ -15801,8 +14060,6 @@ function Welcome({
15801
14060
  showLogo ? /* @__PURE__ */ jsxDEV24(Logo, {
15802
14061
  hues,
15803
14062
  capability,
15804
- reducedMotion,
15805
- nowMs,
15806
14063
  tokens
15807
14064
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV24(Text37, {
15808
14065
  ...tokens.accent,
@@ -15877,27 +14134,470 @@ var init_Welcome = __esm(() => {
15877
14134
  init_wordmark();
15878
14135
  });
15879
14136
 
15880
- // src/tui/shell/App.tsx
15881
- import { readFileSync as readFileSync14 } from "node:fs";
15882
- import { homedir as homedir6 } from "node:os";
15883
- import { join as join24 } from "node:path";
15884
- import { useInput as useInput9 } from "ink";
15885
- import { useEffect as useEffect12, useMemo as useMemo10, useState as useState10 } from "react";
14137
+ // src/tui/shell/Wizard.tsx
14138
+ import { Box as Box33, Text as Text38, useApp as useApp3, useInput as useInput9 } from "ink";
14139
+ import { useState as useState9 } from "react";
15886
14140
  import { jsxDEV as jsxDEV25 } from "react/jsx-dev-runtime";
15887
- function useShimmerNow(reducedMotion, active) {
15888
- const [now, setNow] = useState10(() => Date.now());
15889
- useEffect12(() => {
15890
- if (reducedMotion || !active)
15891
- return;
15892
- const id = setInterval(() => {
15893
- setNow(Date.now());
15894
- }, 120);
15895
- return () => {
15896
- clearInterval(id);
14141
+ function ThemeStep(props) {
14142
+ const { themeCursor, selectedName, contentRows, preview, tokens, glyphs } = props;
14143
+ const start = Math.max(0, themeCursor - contentRows + 2);
14144
+ const selKey = THEME_KEYS[themeCursor];
14145
+ const selData = selKey !== undefined ? THEMES[selKey] : undefined;
14146
+ return /* @__PURE__ */ jsxDEV25(Box33, {
14147
+ flexDirection: "row",
14148
+ children: [
14149
+ /* @__PURE__ */ jsxDEV25(Box33, {
14150
+ flexDirection: "column",
14151
+ width: 28,
14152
+ children: THEME_ENTRIES.slice(start, start + (contentRows - 1)).map((entry, i) => {
14153
+ const active = start + i === themeCursor;
14154
+ const selected = entry.key === selectedName;
14155
+ return /* @__PURE__ */ jsxDEV25(Text38, {
14156
+ ...active ? tokens.accent : tokens.text,
14157
+ children: [
14158
+ active ? glyphs.marker : " ",
14159
+ " ",
14160
+ selected ? glyphs.tabActive : glyphs.tabInactive,
14161
+ " ",
14162
+ entry.label
14163
+ ]
14164
+ }, entry.key, true, undefined, this);
14165
+ })
14166
+ }, undefined, false, undefined, this),
14167
+ /* @__PURE__ */ jsxDEV25(Box33, {
14168
+ flexDirection: "column",
14169
+ flexGrow: 1,
14170
+ paddingLeft: 2,
14171
+ children: [
14172
+ selKey === CHARACTER_THEME ? /* @__PURE__ */ jsxDEV25(Text38, {
14173
+ ...tokens.textMuted,
14174
+ children: "Follows the active character's palette."
14175
+ }, undefined, false, undefined, this) : selData !== undefined ? /* @__PURE__ */ jsxDEV25(Box33, {
14176
+ flexDirection: "column",
14177
+ children: [
14178
+ /* @__PURE__ */ jsxDEV25(Box33, {
14179
+ children: selData.hues.map((h, i) => /* @__PURE__ */ jsxDEV25(Text38, {
14180
+ color: hexForXterm(h),
14181
+ children: "██"
14182
+ }, `h${String(i)}`, false, undefined, this))
14183
+ }, undefined, false, undefined, this),
14184
+ /* @__PURE__ */ jsxDEV25(Box33, {
14185
+ children: [
14186
+ /* @__PURE__ */ jsxDEV25(Text38, {
14187
+ color: hexForXterm(selData.signals.nominal),
14188
+ children: "● "
14189
+ }, undefined, false, undefined, this),
14190
+ /* @__PURE__ */ jsxDEV25(Text38, {
14191
+ color: hexForXterm(selData.signals.caution),
14192
+ children: "● "
14193
+ }, undefined, false, undefined, this),
14194
+ /* @__PURE__ */ jsxDEV25(Text38, {
14195
+ color: hexForXterm(selData.signals.critical),
14196
+ children: "● "
14197
+ }, undefined, false, undefined, this)
14198
+ ]
14199
+ }, undefined, true, undefined, this)
14200
+ ]
14201
+ }, undefined, true, undefined, this) : null,
14202
+ preview !== "" ? /* @__PURE__ */ jsxDEV25(Box33, {
14203
+ marginTop: 1,
14204
+ children: /* @__PURE__ */ jsxDEV25(Text38, {
14205
+ children: preview
14206
+ }, undefined, false, undefined, this)
14207
+ }, undefined, false, undefined, this) : null
14208
+ ]
14209
+ }, undefined, true, undefined, this)
14210
+ ]
14211
+ }, undefined, true, undefined, this);
14212
+ }
14213
+ function packThemeHues(id) {
14214
+ const res = loadPack(id);
14215
+ return res.ok && res.pack.theme ? res.pack.theme.hues : THEMES.houston.hues;
14216
+ }
14217
+ function characterDetailFor(id) {
14218
+ const res = loadPack(id);
14219
+ if (!res.ok)
14220
+ return {
14221
+ ok: false,
14222
+ displayName: id,
14223
+ figure: [],
14224
+ moods: [],
14225
+ artist: "",
14226
+ source: "",
14227
+ tone: "",
14228
+ emblem: ""
15897
14229
  };
15898
- }, [reducedMotion, active]);
15899
- return now;
14230
+ const p = res.pack;
14231
+ return {
14232
+ ok: true,
14233
+ displayName: p.displayName,
14234
+ figure: p.art,
14235
+ moods: Object.keys(p.lines.mood),
14236
+ artist: p.attribution.artist,
14237
+ source: p.attribution.source,
14238
+ tone: p.tone,
14239
+ emblem: p.emblem
14240
+ };
14241
+ }
14242
+ function Wizard(props) {
14243
+ const { targets, renderBin = "ccsidekick-render", onAdvanced, onQuit, onSave } = props;
14244
+ const env2 = props.env ?? process.env;
14245
+ const columns = props.cols ?? 80;
14246
+ const rows = props.rows ?? 24;
14247
+ const app = useApp3();
14248
+ const [step2, setStep] = useState9(0);
14249
+ const [draft, setDraft] = useState9(props.initialConfig ?? DEFAULT_CONFIG);
14250
+ const [characterRail, setCharacterRail] = useState9({
14251
+ focus: 0,
14252
+ catCursor: 0,
14253
+ itemCursor: 0
14254
+ });
14255
+ const [themeCursor, setThemeCursor] = useState9(0);
14256
+ const [commentsCursor, setCommentsCursor] = useState9(0);
14257
+ const [error, setError] = useState9(null);
14258
+ const [done, setDone] = useState9(false);
14259
+ const capability = detectCapability(env2);
14260
+ const theme15 = THEMES[draft.theme.name] ?? THEMES.houston;
14261
+ const tokens = resolveTokens(theme15, capability);
14262
+ const glyphs = glyphSet(false);
14263
+ const packs = [...PACKS];
14264
+ const activeIds = draft.character.mode === "fixed" ? [draft.character.name] : draft.character.roster.length > 0 ? draft.character.roster : packs;
14265
+ const selectedCharId = characterRail.catCursor === 1 ? packs[Math.max(0, Math.min(characterRail.itemCursor, packs.length - 1))] ?? packs[0] ?? "batman" : packs.includes(draft.character.name) ? draft.character.name : packs[0] ?? "batman";
14266
+ const characterDetail = characterDetailFor(selectedCharId);
14267
+ const commentFields = commentsFields(draft);
14268
+ const figureHues = draft.theme.name === CHARACTER_THEME ? packThemeHues(selectedCharId) : theme15.hues;
14269
+ const previewCols = Math.max(24, columns - 46);
14270
+ const themePreview = useThemeDetailBody(step2 === 1, themeCursor, THEME_KEYS, 0, draft, previewCols);
14271
+ const quit = () => {
14272
+ if (onQuit)
14273
+ onQuit();
14274
+ else
14275
+ app.exit();
14276
+ };
14277
+ const nextStep = () => {
14278
+ setStep((s) => Math.min(STEPS.length - 1, s + 1));
14279
+ };
14280
+ const prevStep = () => {
14281
+ setStep((s) => Math.max(0, s - 1));
14282
+ };
14283
+ const selectCharacter = (id) => {
14284
+ setDraft((d) => {
14285
+ const ch = d.character;
14286
+ if (ch.mode === "fixed")
14287
+ return { ...d, character: { ...ch, name: id } };
14288
+ const current = ch.roster.length > 0 ? ch.roster : packs;
14289
+ const next = current.includes(id) ? current.filter((r) => r !== id) : [...current, id];
14290
+ const roster = next.length === packs.length || next.length === 0 ? [] : next;
14291
+ return { ...d, character: { ...ch, roster } };
14292
+ });
14293
+ };
14294
+ const activateCharacter = (state) => {
14295
+ if (state.catCursor === 0) {
14296
+ const mode = state.itemCursor === 0 ? "fixed" : "random";
14297
+ setDraft((d) => ({ ...d, character: { ...d.character, mode } }));
14298
+ return;
14299
+ }
14300
+ const id = packs[Math.min(state.itemCursor, packs.length - 1)];
14301
+ if (id !== undefined)
14302
+ selectCharacter(id);
14303
+ };
14304
+ const handleCharacter = (input, key) => {
14305
+ const listLen = characterRail.catCursor === 0 ? 2 : packs.length;
14306
+ const r = applyRailKey(characterRail, { input, key }, 2, listLen);
14307
+ setCharacterRail(r.state);
14308
+ if (r.exit)
14309
+ prevStep();
14310
+ if (r.act)
14311
+ activateCharacter(r.state);
14312
+ };
14313
+ const handleTheme = (input, key) => {
14314
+ if (key.leftArrow || input === "a") {
14315
+ prevStep();
14316
+ return;
14317
+ }
14318
+ if (key.upArrow || input === "k" || input === "w") {
14319
+ setThemeCursor((c) => Math.max(0, c - 1));
14320
+ return;
14321
+ }
14322
+ if (key.downArrow || input === "j" || input === "s") {
14323
+ setThemeCursor((c) => Math.min(THEME_ENTRIES.length - 1, c + 1));
14324
+ return;
14325
+ }
14326
+ if (key.return || input === " ") {
14327
+ const entry = THEME_ENTRIES[themeCursor];
14328
+ if (entry !== undefined)
14329
+ setDraft((d) => ({ ...d, theme: { ...d.theme, name: entry.key } }));
14330
+ }
14331
+ };
14332
+ const handleComments = (input, key) => {
14333
+ const r = applyContentKey(draft, commentFields, commentsCursor, { input, key });
14334
+ setCommentsCursor(r.cursor);
14335
+ if (r.changed)
14336
+ setDraft(r.draft);
14337
+ if (r.exit)
14338
+ prevStep();
14339
+ };
14340
+ const doSave = () => {
14341
+ try {
14342
+ for (const t of targets) {
14343
+ const opts = {
14344
+ ...t.cwd !== undefined ? { cwd: t.cwd } : {},
14345
+ ...t.wireLocalSettings !== undefined ? { wireLocalSettings: t.wireLocalSettings } : {}
14346
+ };
14347
+ if (onSave)
14348
+ onSave(draft, t);
14349
+ else
14350
+ save(draft, t.scope, t.dir, renderBin, opts);
14351
+ }
14352
+ setError(null);
14353
+ setDone(true);
14354
+ } catch (e) {
14355
+ setError(e instanceof Error ? e.message : String(e));
14356
+ }
14357
+ };
14358
+ const handleReview = (input, key) => {
14359
+ if (key.leftArrow || input === "a")
14360
+ prevStep();
14361
+ else if (key.return || input === "y")
14362
+ doSave();
14363
+ };
14364
+ const onEscape = () => {
14365
+ if (props.initialDirty === true && onAdvanced)
14366
+ onAdvanced(draft);
14367
+ else
14368
+ quit();
14369
+ };
14370
+ const routeStep = (input, key) => {
14371
+ if (step2 === 0)
14372
+ handleCharacter(input, key);
14373
+ else if (step2 === 1)
14374
+ handleTheme(input, key);
14375
+ else if (step2 === 2)
14376
+ handleComments(input, key);
14377
+ else
14378
+ handleReview(input, key);
14379
+ };
14380
+ useInput9((input, key) => {
14381
+ if (done) {
14382
+ quit();
14383
+ return;
14384
+ }
14385
+ if (key.escape) {
14386
+ onEscape();
14387
+ return;
14388
+ }
14389
+ if (key.ctrl && input === "d") {
14390
+ if (onAdvanced)
14391
+ onAdvanced(draft);
14392
+ return;
14393
+ }
14394
+ if (key.tab) {
14395
+ if (key.shift)
14396
+ prevStep();
14397
+ else
14398
+ nextStep();
14399
+ return;
14400
+ }
14401
+ routeStep(input, key);
14402
+ });
14403
+ const contentRows = Math.max(3, rows - 8);
14404
+ const body = (() => {
14405
+ if (done)
14406
+ return /* @__PURE__ */ jsxDEV25(Box33, {
14407
+ flexDirection: "column",
14408
+ children: [
14409
+ /* @__PURE__ */ jsxDEV25(Text38, {
14410
+ ...tokens.nominal,
14411
+ children: "✓ ccsidekick is set up. Press any key to finish."
14412
+ }, undefined, false, undefined, this),
14413
+ /* @__PURE__ */ jsxDEV25(Text38, {
14414
+ ...tokens.textMuted,
14415
+ children: "Restart Claude Code to see your status line."
14416
+ }, undefined, false, undefined, this)
14417
+ ]
14418
+ }, undefined, true, undefined, this);
14419
+ if (step2 === 0)
14420
+ return /* @__PURE__ */ jsxDEV25(CharacterSection, {
14421
+ state: characterRail,
14422
+ packs,
14423
+ activeIds,
14424
+ mode: draft.character.mode,
14425
+ detail: characterDetail,
14426
+ rows: contentRows,
14427
+ tokens,
14428
+ glyphs,
14429
+ hues: figureHues,
14430
+ nowMs: 0,
14431
+ moodShift: draft.theme.mood_shift
14432
+ }, undefined, false, undefined, this);
14433
+ if (step2 === 1)
14434
+ return /* @__PURE__ */ jsxDEV25(ThemeStep, {
14435
+ themeCursor,
14436
+ selectedName: draft.theme.name,
14437
+ contentRows,
14438
+ preview: themePreview,
14439
+ tokens,
14440
+ glyphs
14441
+ }, undefined, false, undefined, this);
14442
+ if (step2 === 2)
14443
+ return /* @__PURE__ */ jsxDEV25(FormSection, {
14444
+ fields: commentFields,
14445
+ cursor: commentsCursor,
14446
+ editing: false,
14447
+ buffer: "",
14448
+ rows: contentRows,
14449
+ tokens,
14450
+ glyphs
14451
+ }, undefined, false, undefined, this);
14452
+ return /* @__PURE__ */ jsxDEV25(Box33, {
14453
+ flexDirection: "column",
14454
+ children: [
14455
+ /* @__PURE__ */ jsxDEV25(Text38, {
14456
+ ...tokens.accent,
14457
+ children: "Review"
14458
+ }, undefined, false, undefined, this),
14459
+ /* @__PURE__ */ jsxDEV25(Text38, {
14460
+ ...tokens.text,
14461
+ children: [
14462
+ "Character: ",
14463
+ draft.character.mode === "fixed" ? draft.character.name : "random",
14464
+ draft.character.mode === "random" ? ` (${draft.character.roster.length > 0 ? draft.character.roster.join(", ") : "all"})` : ""
14465
+ ]
14466
+ }, undefined, true, undefined, this),
14467
+ /* @__PURE__ */ jsxDEV25(Text38, {
14468
+ ...tokens.text,
14469
+ children: [
14470
+ "Theme: ",
14471
+ draft.theme.name
14472
+ ]
14473
+ }, undefined, true, undefined, this),
14474
+ /* @__PURE__ */ jsxDEV25(Text38, {
14475
+ ...tokens.text,
14476
+ children: [
14477
+ "Character Comments: ",
14478
+ draft.comments.character ? "on" : "off"
14479
+ ]
14480
+ }, undefined, true, undefined, this),
14481
+ /* @__PURE__ */ jsxDEV25(Text38, {
14482
+ ...tokens.text,
14483
+ children: [
14484
+ "Helpful Comments: ",
14485
+ draft.comments.helpful ? "on" : "off"
14486
+ ]
14487
+ }, undefined, true, undefined, this),
14488
+ /* @__PURE__ */ jsxDEV25(Text38, {
14489
+ ...tokens.text,
14490
+ children: [
14491
+ "Save to: ",
14492
+ chipFor(targets)
14493
+ ]
14494
+ }, undefined, true, undefined, this),
14495
+ /* @__PURE__ */ jsxDEV25(Box33, {
14496
+ marginTop: 1,
14497
+ children: /* @__PURE__ */ jsxDEV25(Text38, {
14498
+ ...tokens.nominal,
14499
+ children: "Press ↵ to save and wire ccsidekick."
14500
+ }, undefined, false, undefined, this)
14501
+ }, undefined, false, undefined, this)
14502
+ ]
14503
+ }, undefined, true, undefined, this);
14504
+ })();
14505
+ const hints = done ? "any key to finish" : step2 === 3 ? "↵ save · shift+tab back · ^d advanced · esc quit" : "tab next · shift+tab back · ↵ select · ^d advanced · esc quit";
14506
+ return /* @__PURE__ */ jsxDEV25(Box33, {
14507
+ width: columns,
14508
+ height: rows,
14509
+ flexDirection: "column",
14510
+ paddingX: 1,
14511
+ borderStyle: "round",
14512
+ borderColor: tokens.frame.color ?? "gray",
14513
+ children: [
14514
+ /* @__PURE__ */ jsxDEV25(Box33, {
14515
+ justifyContent: "space-between",
14516
+ flexShrink: 0,
14517
+ children: [
14518
+ /* @__PURE__ */ jsxDEV25(Text38, {
14519
+ ...tokens.accent,
14520
+ children: "ccsidekick setup"
14521
+ }, undefined, false, undefined, this),
14522
+ /* @__PURE__ */ jsxDEV25(Text38, {
14523
+ ...tokens.textMuted,
14524
+ children: [
14525
+ "Step ",
14526
+ Math.min(step2 + 1, STEPS.length),
14527
+ " of ",
14528
+ STEPS.length
14529
+ ]
14530
+ }, undefined, true, undefined, this)
14531
+ ]
14532
+ }, undefined, true, undefined, this),
14533
+ /* @__PURE__ */ jsxDEV25(Box33, {
14534
+ flexShrink: 0,
14535
+ children: STEPS.map((name, i) => {
14536
+ const mark = i < step2 ? glyphs.tabActive : i === step2 ? glyphs.marker : glyphs.tabInactive;
14537
+ const style = i === step2 ? tokens.accent : i < step2 ? tokens.text : tokens.textMuted;
14538
+ return /* @__PURE__ */ jsxDEV25(Text38, {
14539
+ ...style,
14540
+ children: [
14541
+ mark,
14542
+ " ",
14543
+ name,
14544
+ " "
14545
+ ]
14546
+ }, name, true, undefined, this);
14547
+ })
14548
+ }, undefined, false, undefined, this),
14549
+ error !== null ? /* @__PURE__ */ jsxDEV25(Text38, {
14550
+ ...tokens.critical,
14551
+ children: [
14552
+ "! ",
14553
+ error
14554
+ ]
14555
+ }, undefined, true, undefined, this) : null,
14556
+ /* @__PURE__ */ jsxDEV25(Box33, {
14557
+ marginTop: 1,
14558
+ flexGrow: 1,
14559
+ children: body
14560
+ }, undefined, false, undefined, this),
14561
+ /* @__PURE__ */ jsxDEV25(Box33, {
14562
+ flexShrink: 0,
14563
+ children: /* @__PURE__ */ jsxDEV25(Text38, {
14564
+ ...tokens.textMuted,
14565
+ children: hints
14566
+ }, undefined, false, undefined, this)
14567
+ }, undefined, false, undefined, this)
14568
+ ]
14569
+ }, undefined, true, undefined, this);
15900
14570
  }
14571
+ var STEPS, THEME_ENTRIES, THEME_KEYS;
14572
+ var init_Wizard = __esm(() => {
14573
+ init_tui();
14574
+ init_data();
14575
+ init_packs();
14576
+ init_render();
14577
+ init_sources();
14578
+ init_sections();
14579
+ init_theme2();
14580
+ init_widgets();
14581
+ init_saveTarget();
14582
+ init_scenarioBodies();
14583
+ STEPS = ["Character", "Theme", "Comments", "Review"];
14584
+ THEME_ENTRIES = [
14585
+ { key: CHARACTER_THEME, label: "Match Character" },
14586
+ ...Object.entries(THEMES).map(([key, t]) => ({
14587
+ key,
14588
+ label: t.displayName
14589
+ }))
14590
+ ];
14591
+ THEME_KEYS = THEME_ENTRIES.map((e) => e.key);
14592
+ });
14593
+
14594
+ // src/tui/shell/App.tsx
14595
+ import { existsSync as existsSync9, readFileSync as readFileSync15 } from "node:fs";
14596
+ import { homedir as homedir6 } from "node:os";
14597
+ import { join as join24 } from "node:path";
14598
+ import { useInput as useInput10 } from "ink";
14599
+ import { useMemo as useMemo10, useState as useState10 } from "react";
14600
+ import { jsxDEV as jsxDEV26 } from "react/jsx-dev-runtime";
15901
14601
  function pickTheme(name) {
15902
14602
  if (name === undefined)
15903
14603
  return THEMES.houston;
@@ -15907,7 +14607,7 @@ function welcomeTheme(suggestedDir) {
15907
14607
  if (suggestedDir === undefined || suggestedDir === "")
15908
14608
  return THEMES.houston;
15909
14609
  try {
15910
- const text = readFileSync14(join24(suggestedDir, "ccsidekick", "config.toml"), "utf8");
14610
+ const text = readFileSync15(join24(suggestedDir, "ccsidekick", "config.toml"), "utf8");
15911
14611
  return pickTheme(loadConfig(text).theme.name);
15912
14612
  } catch {
15913
14613
  return THEMES.houston;
@@ -15916,22 +14616,46 @@ function welcomeTheme(suggestedDir) {
15916
14616
  function initialChosenDirs(configDir2) {
15917
14617
  return configDir2 === undefined ? null : [{ dir: configDir2, scope: "global" }];
15918
14618
  }
14619
+ function configPathFor(t) {
14620
+ return t.scope === "global" ? join24(t.dir, "ccsidekick", "config.toml") : join24(t.cwd ?? "", ".ccsidekick", "config.toml");
14621
+ }
14622
+ function isFirstRun(targets) {
14623
+ return !targets.some((t) => existsSync9(configPathFor(t)));
14624
+ }
15919
14625
  function onQuitProp(onQuit) {
15920
14626
  return onQuit !== undefined ? { onQuit } : {};
15921
14627
  }
14628
+ function entryExtras(props) {
14629
+ return {
14630
+ ...props.renderBin !== undefined ? { renderBin: props.renderBin } : {},
14631
+ ...props.onSave !== undefined ? { onSave: props.onSave } : {}
14632
+ };
14633
+ }
14634
+ function seedProp(seed2) {
14635
+ return seed2 !== undefined ? { initialConfig: seed2 } : {};
14636
+ }
14637
+ function dashboardBaseProps(props, env2, columns, rows) {
14638
+ return {
14639
+ env: env2,
14640
+ cols: columns,
14641
+ rows,
14642
+ ...props.themeName !== undefined ? { themeName: props.themeName } : {},
14643
+ ...props.packs !== undefined ? { packs: props.packs } : {},
14644
+ ...onQuitProp(props.onQuit),
14645
+ ...entryExtras(props)
14646
+ };
14647
+ }
15922
14648
  function App(props) {
15923
14649
  const env2 = props.env ?? process.env;
15924
14650
  const capability = detectCapability(env2);
15925
- const reducedMotion = detectReducedMotion(env2);
15926
14651
  const tokens = resolveTokens(THEMES.houston, capability);
15927
14652
  const [chosen, setChosen] = useState10(() => initialChosenDirs(props.configDir));
14653
+ const [override, setOverride] = useState10(null);
15928
14654
  const live = useTermSize();
15929
14655
  const columns = props.cols ?? live.columns;
15930
14656
  const rows = props.rows ?? live.rows;
15931
14657
  const atFloor = breakpointFor(columns, rows) === "floor";
15932
- useInput9(() => {});
15933
- const animating = chosen === null && capability === "full" && columns >= LOGO_MIN_COLUMNS && !atFloor;
15934
- const nowMs = useShimmerNow(reducedMotion, animating);
14658
+ useInput10(() => {});
15935
14659
  const home = props.homeDir ?? homedir6();
15936
14660
  const cwd = props.cwd ?? process.cwd();
15937
14661
  const suggested = props.suggestedDir ?? env2["CLAUDE_CONFIG_DIR"];
@@ -15943,22 +14667,9 @@ function App(props) {
15943
14667
  const isDuplicate = homeTargets.some((t) => t.dir === project.dir);
15944
14668
  return isDuplicate ? homeTargets : [...homeTargets, project];
15945
14669
  }, [dirs, cwd, home]);
15946
- const dashboardProps = {
15947
- env: env2,
15948
- reducedMotion,
15949
- cols: columns,
15950
- rows,
15951
- ...props.themeName !== undefined ? { themeName: props.themeName } : {},
15952
- ...onQuitProp(props.onQuit),
15953
- ...props.onSave !== undefined ? { onSave: props.onSave } : {},
15954
- ...props.renderBin !== undefined ? { renderBin: props.renderBin } : {},
15955
- ...props.initialConfig !== undefined ? { initialConfig: props.initialConfig } : {},
15956
- ...props.packs !== undefined ? { packs: props.packs } : {},
15957
- ...props.installed !== undefined ? { installed: props.installed } : {},
15958
- ...props.install !== undefined ? { install: props.install } : {}
15959
- };
14670
+ const dashboardProps = dashboardBaseProps(props, env2, columns, rows);
15960
14671
  if (chosen === null) {
15961
- return /* @__PURE__ */ jsxDEV25(Welcome, {
14672
+ return /* @__PURE__ */ jsxDEV26(Welcome, {
15962
14673
  dirs: options,
15963
14674
  suggestedIndex,
15964
14675
  onChosen: setChosen,
@@ -15967,16 +14678,36 @@ function App(props) {
15967
14678
  atFloor,
15968
14679
  hues: wordmarkHues,
15969
14680
  capability,
15970
- reducedMotion,
15971
- nowMs,
15972
14681
  tokens,
15973
14682
  ...suggested !== undefined ? { suggested } : {},
15974
14683
  ...onQuitProp(props.onQuit)
15975
14684
  }, undefined, false, undefined, this);
15976
14685
  }
15977
- return /* @__PURE__ */ jsxDEV25(Dashboard, {
14686
+ const view = override?.view ?? (isFirstRun(chosen) ? "wizard" : "dashboard");
14687
+ const seed2 = override?.draft ?? props.initialConfig;
14688
+ if (view === "wizard") {
14689
+ return /* @__PURE__ */ jsxDEV26(Wizard, {
14690
+ targets: chosen,
14691
+ cols: columns,
14692
+ rows,
14693
+ env: env2,
14694
+ initialDirty: override?.dirty ?? false,
14695
+ onAdvanced: (draft) => {
14696
+ setOverride({ view: "dashboard", draft, dirty: true });
14697
+ },
14698
+ ...onQuitProp(props.onQuit),
14699
+ ...entryExtras(props),
14700
+ ...seedProp(seed2)
14701
+ }, undefined, false, undefined, this);
14702
+ }
14703
+ return /* @__PURE__ */ jsxDEV26(Dashboard, {
15978
14704
  ...dashboardProps,
15979
- targets: chosen
14705
+ targets: chosen,
14706
+ initialDirty: override?.dirty ?? false,
14707
+ onWizard: (draft, dirty2) => {
14708
+ setOverride({ view: "wizard", draft, dirty: dirty2 });
14709
+ },
14710
+ ...seedProp(seed2)
15980
14711
  }, undefined, false, undefined, this);
15981
14712
  }
15982
14713
  var init_App = __esm(() => {
@@ -15988,14 +14719,12 @@ var init_App = __esm(() => {
15988
14719
  init_Dashboard();
15989
14720
  init_saveTarget();
15990
14721
  init_Welcome();
15991
- init_wordmark();
14722
+ init_Wizard();
15992
14723
  });
15993
14724
 
15994
14725
  // src/tui/shell/index.ts
15995
14726
  var exports_shell = {};
15996
14727
  __export(exports_shell, {
15997
- useTransitionFade: () => useTransitionFade,
15998
- useShimmerNow: () => useShimmerNow,
15999
14728
  useMouseWheel: () => useMouseWheel,
16000
14729
  routeKey: () => routeKey,
16001
14730
  rankFind: () => rankFind,
@@ -16004,6 +14733,7 @@ __export(exports_shell, {
16004
14733
  chipFor: () => chipFor,
16005
14734
  buildSaveConfirm: () => buildSaveConfirm,
16006
14735
  buildFindIndex: () => buildFindIndex,
14736
+ Wizard: () => Wizard,
16007
14737
  Welcome: () => Welcome,
16008
14738
  WORDMARK_WIDTH: () => WORDMARK_WIDTH,
16009
14739
  WORDMARK: () => WORDMARK,
@@ -16027,19 +14757,19 @@ var init_shell = __esm(() => {
16027
14757
  init_SaveConfirmPopup();
16028
14758
  init_saveTarget();
16029
14759
  init_Logo();
16030
- init_useTransitionFade();
16031
14760
  init_useMouseWheel();
16032
14761
  init_Welcome();
14762
+ init_Wizard();
16033
14763
  init_wordmark();
16034
14764
  });
16035
14765
 
16036
14766
  // src/bin/ccsidekick.ts
16037
14767
  init_cli();
16038
14768
  init_domain();
16039
- init_sources();
14769
+ init_tui();
16040
14770
  import { homedir as homedir7 } from "node:os";
16041
14771
  import { join as join25 } from "node:path";
16042
- import { fileURLToPath as fileURLToPath3 } from "node:url";
14772
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
16043
14773
  var sub = process.argv[2];
16044
14774
  function claudeDir() {
16045
14775
  return process.env["CLAUDE_CONFIG_DIR"] ?? join25(homedir7(), ".claude");
@@ -16050,6 +14780,8 @@ function printHelp() {
16050
14780
  "",
16051
14781
  "Usage:",
16052
14782
  " ccsidekick launch the setup TUI (needs a terminal)",
14783
+ " ccsidekick setup [flags] configure + wire without the TUI (see: setup --help)",
14784
+ " ccsidekick list <what> list valid characters | themes | widgets",
16053
14785
  " ccsidekick uninstall remove the status line + hooks from settings.json",
16054
14786
  " ccsidekick uninstall --restore-backup restore the pre-install settings backup",
16055
14787
  " ccsidekick help | --help | -h show this help",
@@ -16082,14 +14814,11 @@ async function launchTui() {
16082
14814
  const { render } = await import("ink");
16083
14815
  const { createElement } = await import("react");
16084
14816
  const { App: App2 } = await Promise.resolve().then(() => (init_shell(), exports_shell));
16085
- const engineDir = engineRoot(import.meta.url);
16086
- const renderBin = fileURLToPath3(new URL("ccsidekick-render.js", import.meta.url));
16087
- const installed = listInstalledPacks(engineDir);
14817
+ const renderBin = fileURLToPath2(new URL("ccsidekick-render.js", import.meta.url));
16088
14818
  const suggested = process.env["CLAUDE_CONFIG_DIR"];
16089
14819
  const instance = render(createElement(App2, {
16090
14820
  homeDir: homedir7(),
16091
14821
  renderBin,
16092
- installed,
16093
14822
  ...suggested !== undefined ? { suggestedDir: suggested } : {}
16094
14823
  }));
16095
14824
  await instance.waitUntilExit();
@@ -16106,6 +14835,28 @@ async function main() {
16106
14835
  });
16107
14836
  process.exit(0);
16108
14837
  }
14838
+ if (sub === "list") {
14839
+ const code = runList(process.argv[3], (s) => process.stdout.write(s), (s) => process.stderr.write(s));
14840
+ process.exit(code);
14841
+ }
14842
+ if (sub === "setup") {
14843
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
14844
+ process.stdout.write(setupHelp());
14845
+ process.exit(0);
14846
+ }
14847
+ const renderBin = fileURLToPath2(new URL("ccsidekick-render.js", import.meta.url));
14848
+ const code = runSetup(process.argv.slice(3), {
14849
+ save,
14850
+ renderBin,
14851
+ readConfig: defaultReadConfig,
14852
+ cwd: process.cwd(),
14853
+ homeDir: homedir7(),
14854
+ env: process.env,
14855
+ out: (s) => process.stdout.write(s),
14856
+ err: (s) => process.stderr.write(s)
14857
+ });
14858
+ process.exit(code);
14859
+ }
16109
14860
  if (!process.stdout.isTTY || !process.stdin.isTTY) {
16110
14861
  printManualSetup();
16111
14862
  process.exit(1);