ccsidekick 1.1.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.
@@ -1038,15 +1038,19 @@ function candidateSet(config, installed) {
1038
1038
  return ["batman"];
1039
1039
  }
1040
1040
  function derivePersona(config, state, session, installed) {
1041
- if (state.character !== undefined && state.character !== "")
1042
- return state.character;
1041
+ const candidates = candidateSet(config, installed);
1042
+ const sticky = state.character;
1043
+ if (sticky !== undefined && sticky !== "" && stickyValid(config, candidates, sticky))
1044
+ return sticky;
1043
1045
  if (config.character.mode === "fixed")
1044
1046
  return config.character.name;
1045
- const candidates = candidateSet(config, installed);
1046
1047
  const hash = createHash("sha1").update(session).digest("hex");
1047
1048
  const idx = parseInt(hash.slice(0, 8), 16) % candidates.length;
1048
1049
  return candidates[idx] ?? "batman";
1049
1050
  }
1051
+ function stickyValid(config, candidates, sticky) {
1052
+ return config.character.mode === "fixed" ? sticky === config.character.name : candidates.includes(sticky);
1053
+ }
1050
1054
  // src/derived/project.ts
1051
1055
  function deriveProject(git, payload) {
1052
1056
  const repo = payload.workspace.repo;
@@ -1212,12 +1216,6 @@ var sessionDir = (root, id) => join(root, "sessions", id);
1212
1216
  var cacheDir = (root) => join(root, "cache");
1213
1217
  var analyticsDir = (root) => join(root, "analytics");
1214
1218
 
1215
- // src/sources/storage/engineRoot.ts
1216
- import { fileURLToPath } from "node:url";
1217
- function engineRoot(moduleUrl) {
1218
- return fileURLToPath(new URL("../", moduleUrl));
1219
- }
1220
-
1221
1219
  // src/sources/storage/atomicWrite.ts
1222
1220
  import { mkdirSync, renameSync, writeFileSync } from "node:fs";
1223
1221
  import { dirname } from "node:path";
@@ -3525,41 +3523,8 @@ function readHelpfulEnv(cwd) {
3525
3523
  ...opt3("tfWorkspace", readTfWorkspace(cwd))
3526
3524
  };
3527
3525
  }
3528
- // src/sources/installed.ts
3529
- import { readdirSync, statSync as statSync3 } from "node:fs";
3530
- import { join as join10 } from "node:path";
3531
- var PREFIX = "pack-";
3532
- function listInstalledPacks(engineDir) {
3533
- const scope = join10(engineDir, "node_modules", "@ccsidekick");
3534
- let entries;
3535
- try {
3536
- entries = readdirSync(scope, { withFileTypes: true });
3537
- } catch {
3538
- return [];
3539
- }
3540
- const ids = [];
3541
- for (const entry of entries) {
3542
- if (!entry.name.startsWith(PREFIX) || entry.name.length <= PREFIX.length)
3543
- continue;
3544
- if (!isDir(entry, join10(scope, entry.name)))
3545
- continue;
3546
- ids.push(entry.name.slice(PREFIX.length));
3547
- }
3548
- return ids.sort();
3549
- }
3550
- function isDir(entry, path) {
3551
- if (entry.isDirectory())
3552
- return true;
3553
- if (!entry.isSymbolicLink())
3554
- return false;
3555
- try {
3556
- return statSync3(path).isDirectory();
3557
- } catch {
3558
- return false;
3559
- }
3560
- }
3561
3526
  // src/sources/markers.ts
3562
- import { readdirSync as readdirSync2 } from "node:fs";
3527
+ import { readdirSync } from "node:fs";
3563
3528
  import { dirname as dirname5, resolve as resolve2 } from "node:path";
3564
3529
  var FILE_MARKERS = {
3565
3530
  "package.json": "web",
@@ -3620,7 +3585,7 @@ function scanDir(dir, stacks) {
3620
3585
  let entries;
3621
3586
  let isRepoRoot = false;
3622
3587
  try {
3623
- entries = readdirSync2(dir);
3588
+ entries = readdirSync(dir);
3624
3589
  } catch {
3625
3590
  return false;
3626
3591
  }
@@ -3654,8 +3619,8 @@ function readMarkers(cwd) {
3654
3619
  return { stacks };
3655
3620
  }
3656
3621
  // src/sources/modelNames.ts
3657
- import { join as join11 } from "node:path";
3658
- var cachePath = (root) => join11(cacheDir(root), "model-names.json");
3622
+ import { join as join10 } from "node:path";
3623
+ var cachePath = (root) => join10(cacheDir(root), "model-names.json");
3659
3624
  function readModelNames(root) {
3660
3625
  return readJson(cachePath(root), {});
3661
3626
  }
@@ -3772,7 +3737,7 @@ function parsePayload(raw) {
3772
3737
  };
3773
3738
  }
3774
3739
  // src/sources/state.ts
3775
- import { join as join12 } from "node:path";
3740
+ import { join as join11 } from "node:path";
3776
3741
  var STATE_FILE = "state.json";
3777
3742
  var EMPTY2 = { pressureFired: [], milestones: [], helpful: {} };
3778
3743
  function isObject5(v) {
@@ -3797,7 +3762,7 @@ function asHelpful(v) {
3797
3762
  return out;
3798
3763
  }
3799
3764
  function readState(sessionDir2) {
3800
- const raw = readJson(join12(sessionDir2, STATE_FILE), undefined);
3765
+ const raw = readJson(join11(sessionDir2, STATE_FILE), undefined);
3801
3766
  if (!isObject5(raw))
3802
3767
  return EMPTY2;
3803
3768
  const character = raw["character"];
@@ -3827,14 +3792,14 @@ function mergeState(disk, next) {
3827
3792
  };
3828
3793
  }
3829
3794
  function writeState(sessionDir2, s) {
3830
- const path = join12(sessionDir2, STATE_FILE);
3795
+ const path = join11(sessionDir2, STATE_FILE);
3831
3796
  withLock(`${path}.lock`, () => {
3832
3797
  atomicWrite(path, JSON.stringify(mergeState(readState(sessionDir2), s)));
3833
3798
  }, () => {});
3834
3799
  }
3835
3800
  // src/sources/transcript.ts
3836
- import { readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
3837
- import { basename, dirname as dirname6, join as join13 } from "node:path";
3801
+ import { readFileSync as readFileSync8, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
3802
+ import { basename, dirname as dirname6, join as join12 } from "node:path";
3838
3803
  var asObj = (v) => v !== null && typeof v === "object" ? v : undefined;
3839
3804
  var asStr = (v) => typeof v === "string" ? v : undefined;
3840
3805
  var asNum = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
@@ -4059,7 +4024,7 @@ function reconstructTodos(lines) {
4059
4024
  }
4060
4025
  function statSafe(p) {
4061
4026
  try {
4062
- const s = statSync4(p);
4027
+ const s = statSync3(p);
4063
4028
  return { mtimeMs: s.mtimeMs, size: s.size };
4064
4029
  } catch {
4065
4030
  return null;
@@ -4149,15 +4114,15 @@ var repoRootCache = new Map;
4149
4114
  function* walkTree(dir, encodedDir) {
4150
4115
  let entries;
4151
4116
  try {
4152
- entries = readdirSync3(dir);
4117
+ entries = readdirSync2(dir);
4153
4118
  } catch {
4154
4119
  return;
4155
4120
  }
4156
4121
  for (const name of entries) {
4157
- const full = join13(dir, name);
4122
+ const full = join12(dir, name);
4158
4123
  let st;
4159
4124
  try {
4160
- st = statSync4(full);
4125
+ st = statSync3(full);
4161
4126
  } catch {
4162
4127
  continue;
4163
4128
  }
@@ -4171,12 +4136,12 @@ function* walkTree(dir, encodedDir) {
4171
4136
  function* walkJsonl(root) {
4172
4137
  let dirs;
4173
4138
  try {
4174
- dirs = readdirSync3(root);
4139
+ dirs = readdirSync2(root);
4175
4140
  } catch {
4176
4141
  return;
4177
4142
  }
4178
4143
  for (const encodedDir of dirs) {
4179
- yield* walkTree(join13(root, encodedDir), encodedDir);
4144
+ yield* walkTree(join12(root, encodedDir), encodedDir);
4180
4145
  }
4181
4146
  }
4182
4147
  function scanBounds(lines) {
@@ -4387,7 +4352,7 @@ function runClassify(stdin, env, clock) {
4387
4352
  }
4388
4353
  // src/cli/render.ts
4389
4354
  import { readFileSync as readFileSync10 } from "node:fs";
4390
- import { dirname as dirname7, join as join15 } from "node:path";
4355
+ import { dirname as dirname7, join as join14 } from "node:path";
4391
4356
 
4392
4357
  // src/compose/character.ts
4393
4358
  import { createHash as createHash5 } from "node:crypto";
@@ -5238,7 +5203,13 @@ var truncateField = (f, budget) => {
5238
5203
  if (f.id === "model" && f.segments.length >= 2 && tail !== undefined) {
5239
5204
  const tailText = sanitizePackText(tail.text);
5240
5205
  const headText = f.segments.slice(0, -1).map((s) => sanitizePackText(s.text)).filter((t) => t !== "").join(" ");
5241
- const headBudget = Math.max(1, budget - displayWidth(tailText) - 1);
5206
+ const headBudget = budget - displayWidth(tailText) - 1;
5207
+ if (headBudget < 1) {
5208
+ return {
5209
+ id: f.id,
5210
+ segments: [{ role: "value", text: truncToWidth(fieldPlain(f), budget) }]
5211
+ };
5212
+ }
5242
5213
  return {
5243
5214
  id: f.id,
5244
5215
  segments: [
@@ -5249,6 +5220,21 @@ var truncateField = (f, budget) => {
5249
5220
  }
5250
5221
  return { id: f.id, segments: [{ role: "value", text: truncToWidth(fieldPlain(f), budget) }] };
5251
5222
  };
5223
+ var fitCells = (cells, avail, sepGlyph) => {
5224
+ if (cells.length === 0 || rowPlainWidth(cells, sepGlyph) <= avail)
5225
+ return [...cells];
5226
+ const last = cells[cells.length - 1];
5227
+ if (last === undefined)
5228
+ return [...cells];
5229
+ const head = cells.slice(0, -1);
5230
+ const sepWidth = displayWidth(` ${sepGlyph} `);
5231
+ const headWidth = head.length > 0 ? displayWidth(head.map(fieldPlain).join(` ${sepGlyph} `)) : 0;
5232
+ const budget = avail - headWidth - (head.length > 0 ? sepWidth : 0);
5233
+ if (budget >= 1)
5234
+ return [...head, truncateField(last, budget)];
5235
+ const headFitted = fitCells(head, Math.max(1, avail - sepWidth - 1), sepGlyph);
5236
+ return [...headFitted, truncateField(last, 1)];
5237
+ };
5252
5238
  var fitRow = (row, cells, avail, sepGlyph) => {
5253
5239
  const present = [...cells];
5254
5240
  for (const id of dropOrder(row)) {
@@ -5260,15 +5246,7 @@ var fitRow = (row, cells, avail, sepGlyph) => {
5260
5246
  if (idx >= 0)
5261
5247
  present.splice(idx, 1);
5262
5248
  }
5263
- if (rowPlainWidth(present, sepGlyph) <= avail)
5264
- return present;
5265
- const last = present[present.length - 1];
5266
- if (last === undefined)
5267
- return present;
5268
- const head = present.slice(0, -1);
5269
- const headWidth = head.length > 0 ? displayWidth(head.map(fieldPlain).join(` ${sepGlyph} `)) + displayWidth(` ${sepGlyph} `) : 0;
5270
- const budget = Math.max(1, avail - headWidth);
5271
- return [...head, truncateField(last, budget)];
5249
+ return fitCells(present, avail, sepGlyph);
5272
5250
  };
5273
5251
  var colorCell = (field, lineIdx, cellIdx, input, term) => {
5274
5252
  const { theme, moodShift, mood } = input;
@@ -6750,16 +6728,16 @@ function resolveHelpful(inputs, state, clock, minSeverity) {
6750
6728
  }
6751
6729
  // src/packs/load.ts
6752
6730
  import { readFileSync as readFileSync9 } from "node:fs";
6753
- import { fileURLToPath as fileURLToPath2 } from "node:url";
6731
+ import { fileURLToPath } from "node:url";
6754
6732
 
6755
6733
  // src/packs/allowlist.ts
6756
- var PREFIX2 = "@ccsidekick/pack-";
6734
+ var PREFIX = "@ccsidekick/pack-";
6757
6735
  var NAME_SEGMENT = /^[a-z0-9-]+$/;
6758
- var packPackageName = (name) => `${PREFIX2}${name}`;
6736
+ var packPackageName = (name) => `${PREFIX}${name}`;
6759
6737
  function isAllowedPackPackage(pkg) {
6760
- if (!pkg.startsWith(PREFIX2))
6738
+ if (!pkg.startsWith(PREFIX))
6761
6739
  return false;
6762
- return NAME_SEGMENT.test(pkg.slice(PREFIX2.length));
6740
+ return NAME_SEGMENT.test(pkg.slice(PREFIX.length));
6763
6741
  }
6764
6742
 
6765
6743
  // src/packs/validate.ts
@@ -6961,7 +6939,7 @@ var validatePack = (raw) => {
6961
6939
  };
6962
6940
 
6963
6941
  // src/packs/load.ts
6964
- var defaultResolver = (spec) => fileURLToPath2(import.meta.resolve(spec));
6942
+ var defaultResolver = (spec) => fileURLToPath(import.meta.resolve(spec));
6965
6943
  var errMessage = (e) => e instanceof Error ? e.message : String(e);
6966
6944
  function loadPack(name, resolver = defaultResolver) {
6967
6945
  if (!isAllowedPackPackage(packPackageName(name))) {
@@ -6991,17 +6969,30 @@ function loadPack(name, resolver = defaultResolver) {
6991
6969
  return { ok: false, reason: "pack failed validation" };
6992
6970
  return { ok: true, pack };
6993
6971
  }
6972
+ // src/packs/registry.ts
6973
+ var PACKS = [
6974
+ "barbie",
6975
+ "batman",
6976
+ "deadpool",
6977
+ "harry-potter",
6978
+ "hello-kitty",
6979
+ "james-bond",
6980
+ "joker",
6981
+ "pikachu",
6982
+ "sherlock-holmes",
6983
+ "spiderman"
6984
+ ];
6994
6985
  // src/cli/gc.ts
6995
- import { existsSync as existsSync2, readdirSync as readdirSync4, rmSync, statSync as statSync5 } from "node:fs";
6996
- import { join as join14 } from "node:path";
6986
+ import { existsSync as existsSync2, readdirSync as readdirSync3, rmSync, statSync as statSync4 } from "node:fs";
6987
+ import { join as join13 } from "node:path";
6997
6988
  var DAY_MS = 86400000;
6998
6989
  function newestMtime(dir) {
6999
6990
  let newest = 0;
7000
6991
  try {
7001
- newest = statSync5(dir).mtimeMs;
7002
- for (const name of readdirSync4(dir)) {
6992
+ newest = statSync4(dir).mtimeMs;
6993
+ for (const name of readdirSync3(dir)) {
7003
6994
  try {
7004
- const m = statSync5(join14(dir, name)).mtimeMs;
6995
+ const m = statSync4(join13(dir, name)).mtimeMs;
7005
6996
  if (m > newest)
7006
6997
  newest = m;
7007
6998
  } catch {}
@@ -7010,18 +7001,18 @@ function newestMtime(dir) {
7010
7001
  return newest;
7011
7002
  }
7012
7003
  function pruneSessions(root, now) {
7013
- const sessions = join14(root, "sessions");
7004
+ const sessions = join13(root, "sessions");
7014
7005
  let names;
7015
7006
  try {
7016
- names = readdirSync4(sessions);
7007
+ names = readdirSync3(sessions);
7017
7008
  } catch {
7018
7009
  return;
7019
7010
  }
7020
7011
  const cutoff = now - SESSION_TTL_DAYS * DAY_MS;
7021
7012
  for (const name of names) {
7022
- const dir = join14(sessions, name);
7013
+ const dir = join13(sessions, name);
7023
7014
  try {
7024
- if (!statSync5(dir).isDirectory())
7015
+ if (!statSync4(dir).isDirectory())
7025
7016
  continue;
7026
7017
  } catch {
7027
7018
  continue;
@@ -7093,13 +7084,12 @@ function applyThemeIcons(fields, theme, config) {
7093
7084
  };
7094
7085
  });
7095
7086
  }
7096
- function readGated(overrides, envInputs, config, root, dir, markers, sessionState, clock) {
7087
+ function readGated(overrides, envInputs, config, root, dir, markers, clock) {
7097
7088
  const creds = overrides?.creds !== undefined ? overrides.creds : envInputs.hasApiKey || config.network.usage_fetch ? readCreds() : null;
7098
7089
  const usage = overrides?.usage !== undefined ? overrides.usage : config.network.usage_fetch ? readUsageCached(root) : null;
7099
7090
  const balance = overrides?.balance !== undefined ? overrides.balance : config.network.balance_path !== "" ? readBalance(config.network.balance_path, clock) : null;
7100
7091
  const helpfulEnv = needsHelpfulEnv(markers) ? readHelpfulEnv(dir) : EMPTY_HELPFUL_ENV;
7101
- const installed = sessionState.character === undefined && config.character.mode === "random" && config.character.roster.length === 0 ? listInstalledPacks(engineRoot(import.meta.url)) : [];
7102
- return { creds, usage, balance, helpfulEnv, installed };
7092
+ return { creds, usage, balance, helpfulEnv };
7103
7093
  }
7104
7094
  var DEFAULT_EMBLEM = "❝";
7105
7095
  function lookupPackTheme(name) {
@@ -7128,10 +7118,10 @@ function build(stdin, env, term, clock, overrides) {
7128
7118
  return { line: "", persist: NOOP };
7129
7119
  const root = ccsidekickRoot(env);
7130
7120
  const base = dirname7(root);
7131
- const projectsRoot = join15(base, "projects");
7121
+ const projectsRoot = join14(base, "projects");
7132
7122
  const dir = payload.workspace.current_dir ?? payload.cwd ?? process.cwd();
7133
- const globalToml = readTextSafe(join15(root, "config.toml"));
7134
- const projectToml = readTextSafe(join15(dir, ".ccsidekick", "config.toml"));
7123
+ const globalToml = readTextSafe(join14(root, "config.toml"));
7124
+ const projectToml = readTextSafe(join14(dir, ".ccsidekick", "config.toml"));
7135
7125
  const config = loadConfig(globalToml, projectToml);
7136
7126
  const envInputs = readEnv(env);
7137
7127
  const aliases = readModelAliases(env);
@@ -7146,8 +7136,8 @@ function build(stdin, env, term, clock, overrides) {
7146
7136
  const attribution = readAttribution(root);
7147
7137
  const costCache = readCostCache(root);
7148
7138
  const fxTable = readFxCached(root);
7149
- const { creds, usage, balance, helpfulEnv, installed } = readGated(overrides, envInputs, config, root, dir, markers, sessionState, clock);
7150
- const persona = derivePersona(config, sessionState, session, installed);
7139
+ const { creds, usage, balance, helpfulEnv } = readGated(overrides, envInputs, config, root, dir, markers, clock);
7140
+ const persona = derivePersona(config, sessionState, session, PACKS);
7151
7141
  const loaded = loadPack(persona);
7152
7142
  const pack = loaded.ok ? loaded.pack : null;
7153
7143
  const project = deriveProject(git, payload);
@@ -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;
@@ -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
@@ -4012,11 +4028,14 @@ var init_registry = __esm(() => {
4012
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
 
@@ -4032,13 +4051,6 @@ import { join } from "node:path";
4032
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");
4033
4052
  var init_configDir = () => {};
4034
4053
 
4035
- // src/sources/storage/engineRoot.ts
4036
- import { fileURLToPath as fileURLToPath2 } from "node:url";
4037
- function engineRoot(moduleUrl) {
4038
- return fileURLToPath2(new URL("../", moduleUrl));
4039
- }
4040
- var init_engineRoot = () => {};
4041
-
4042
4054
  // src/sources/storage/atomicWrite.ts
4043
4055
  import { mkdirSync, renameSync, writeFileSync } from "node:fs";
4044
4056
  import { dirname } from "node:path";
@@ -4125,7 +4137,6 @@ var init_singleFlight = () => {};
4125
4137
  // src/sources/storage/index.ts
4126
4138
  var init_storage = __esm(() => {
4127
4139
  init_configDir();
4128
- init_engineRoot();
4129
4140
  init_atomicWrite();
4130
4141
  init_readJson();
4131
4142
  init_withLock();
@@ -6564,49 +6575,14 @@ function readHelpfulEnv(cwd) {
6564
6575
  var opt3 = (key, value) => value !== undefined ? { [key]: value } : {};
6565
6576
  var init_helpfulEnv = () => {};
6566
6577
 
6567
- // src/sources/installed.ts
6568
- import { readdirSync, statSync as statSync3 } from "node:fs";
6569
- import { join as join10 } from "node:path";
6570
- function listInstalledPacks(engineDir) {
6571
- const scope = join10(engineDir, "node_modules", "@ccsidekick");
6572
- let entries;
6573
- try {
6574
- entries = readdirSync(scope, { withFileTypes: true });
6575
- } catch {
6576
- return [];
6577
- }
6578
- const ids = [];
6579
- for (const entry of entries) {
6580
- if (!entry.name.startsWith(PREFIX2) || entry.name.length <= PREFIX2.length)
6581
- continue;
6582
- if (!isDir(entry, join10(scope, entry.name)))
6583
- continue;
6584
- ids.push(entry.name.slice(PREFIX2.length));
6585
- }
6586
- return ids.sort();
6587
- }
6588
- function isDir(entry, path) {
6589
- if (entry.isDirectory())
6590
- return true;
6591
- if (!entry.isSymbolicLink())
6592
- return false;
6593
- try {
6594
- return statSync3(path).isDirectory();
6595
- } catch {
6596
- return false;
6597
- }
6598
- }
6599
- var PREFIX2 = "pack-";
6600
- var init_installed = () => {};
6601
-
6602
6578
  // src/sources/markers.ts
6603
- import { readdirSync as readdirSync2 } from "node:fs";
6579
+ import { readdirSync } from "node:fs";
6604
6580
  import { dirname as dirname4, resolve as resolve2 } from "node:path";
6605
6581
  function scanDir(dir, stacks) {
6606
6582
  let entries;
6607
6583
  let isRepoRoot = false;
6608
6584
  try {
6609
- entries = readdirSync2(dir);
6585
+ entries = readdirSync(dir);
6610
6586
  } catch {
6611
6587
  return false;
6612
6588
  }
@@ -6699,7 +6675,7 @@ var init_markers = __esm(() => {
6699
6675
  });
6700
6676
 
6701
6677
  // src/sources/modelNames.ts
6702
- import { join as join11 } from "node:path";
6678
+ import { join as join10 } from "node:path";
6703
6679
  function readModelNames(root) {
6704
6680
  return readJson(cachePath(root), {});
6705
6681
  }
@@ -6708,7 +6684,7 @@ function learnModelName(root, current, id, name) {
6708
6684
  return;
6709
6685
  atomicWrite(cachePath(root), JSON.stringify({ ...current, [id]: name }));
6710
6686
  }
6711
- var cachePath = (root) => join11(cacheDir(root), "model-names.json");
6687
+ var cachePath = (root) => join10(cacheDir(root), "model-names.json");
6712
6688
  var init_modelNames = __esm(() => {
6713
6689
  init_storage();
6714
6690
  });
@@ -6818,7 +6794,7 @@ function parsePayload(raw) {
6818
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 } : {};
6819
6795
 
6820
6796
  // src/sources/state.ts
6821
- import { join as join12 } from "node:path";
6797
+ import { join as join11 } from "node:path";
6822
6798
  function isObject5(v) {
6823
6799
  return typeof v === "object" && v !== null && !Array.isArray(v);
6824
6800
  }
@@ -6841,7 +6817,7 @@ function asHelpful(v) {
6841
6817
  return out;
6842
6818
  }
6843
6819
  function readState(sessionDir2) {
6844
- const raw = readJson(join12(sessionDir2, STATE_FILE), undefined);
6820
+ const raw = readJson(join11(sessionDir2, STATE_FILE), undefined);
6845
6821
  if (!isObject5(raw))
6846
6822
  return EMPTY2;
6847
6823
  const character = raw["character"];
@@ -6871,7 +6847,7 @@ function mergeState(disk, next) {
6871
6847
  };
6872
6848
  }
6873
6849
  function writeState(sessionDir2, s) {
6874
- const path = join12(sessionDir2, STATE_FILE);
6850
+ const path = join11(sessionDir2, STATE_FILE);
6875
6851
  withLock(`${path}.lock`, () => {
6876
6852
  atomicWrite(path, JSON.stringify(mergeState(readState(sessionDir2), s)));
6877
6853
  }, () => {});
@@ -6883,8 +6859,8 @@ var init_state = __esm(() => {
6883
6859
  });
6884
6860
 
6885
6861
  // src/sources/transcript.ts
6886
- import { readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
6887
- 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";
6888
6864
  function parseTs(s) {
6889
6865
  if (s === undefined)
6890
6866
  return;
@@ -7105,7 +7081,7 @@ function reconstructTodos(lines) {
7105
7081
  }
7106
7082
  function statSafe(p) {
7107
7083
  try {
7108
- const s = statSync4(p);
7084
+ const s = statSync3(p);
7109
7085
  return { mtimeMs: s.mtimeMs, size: s.size };
7110
7086
  } catch {
7111
7087
  return null;
@@ -7192,7 +7168,7 @@ function repoRootForCwd(cwd) {
7192
7168
  let result = cwd;
7193
7169
  while (dir !== "" && dir !== dirname5(dir)) {
7194
7170
  try {
7195
- if (statSync4(join13(dir, ".git")).isDirectory()) {
7171
+ if (statSync3(join12(dir, ".git")).isDirectory()) {
7196
7172
  result = dir;
7197
7173
  break;
7198
7174
  }
@@ -7205,15 +7181,15 @@ function repoRootForCwd(cwd) {
7205
7181
  function* walkTree(dir, encodedDir) {
7206
7182
  let entries;
7207
7183
  try {
7208
- entries = readdirSync3(dir);
7184
+ entries = readdirSync2(dir);
7209
7185
  } catch {
7210
7186
  return;
7211
7187
  }
7212
7188
  for (const name of entries) {
7213
- const full = join13(dir, name);
7189
+ const full = join12(dir, name);
7214
7190
  let st;
7215
7191
  try {
7216
- st = statSync4(full);
7192
+ st = statSync3(full);
7217
7193
  } catch {
7218
7194
  continue;
7219
7195
  }
@@ -7227,12 +7203,12 @@ function* walkTree(dir, encodedDir) {
7227
7203
  function* walkJsonl(root) {
7228
7204
  let dirs;
7229
7205
  try {
7230
- dirs = readdirSync3(root);
7206
+ dirs = readdirSync2(root);
7231
7207
  } catch {
7232
7208
  return;
7233
7209
  }
7234
7210
  for (const encodedDir of dirs) {
7235
- yield* walkTree(join13(root, encodedDir), encodedDir);
7211
+ yield* walkTree(join12(root, encodedDir), encodedDir);
7236
7212
  }
7237
7213
  }
7238
7214
  function scanBounds(lines) {
@@ -7387,7 +7363,6 @@ var init_sources = __esm(() => {
7387
7363
  init_fx();
7388
7364
  init_git();
7389
7365
  init_helpfulEnv();
7390
- init_installed();
7391
7366
  init_markers();
7392
7367
  init_modelNames();
7393
7368
  init_oauthUsage();
@@ -7397,15 +7372,15 @@ var init_sources = __esm(() => {
7397
7372
  });
7398
7373
 
7399
7374
  // src/cli/gc.ts
7400
- import { existsSync as existsSync2, readdirSync as readdirSync4, rmSync, statSync as statSync5 } from "node:fs";
7401
- 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";
7402
7377
  function newestMtime(dir) {
7403
7378
  let newest = 0;
7404
7379
  try {
7405
- newest = statSync5(dir).mtimeMs;
7406
- for (const name of readdirSync4(dir)) {
7380
+ newest = statSync4(dir).mtimeMs;
7381
+ for (const name of readdirSync3(dir)) {
7407
7382
  try {
7408
- const m = statSync5(join14(dir, name)).mtimeMs;
7383
+ const m = statSync4(join13(dir, name)).mtimeMs;
7409
7384
  if (m > newest)
7410
7385
  newest = m;
7411
7386
  } catch {}
@@ -7414,18 +7389,18 @@ function newestMtime(dir) {
7414
7389
  return newest;
7415
7390
  }
7416
7391
  function pruneSessions(root, now) {
7417
- const sessions = join14(root, "sessions");
7392
+ const sessions = join13(root, "sessions");
7418
7393
  let names;
7419
7394
  try {
7420
- names = readdirSync4(sessions);
7395
+ names = readdirSync3(sessions);
7421
7396
  } catch {
7422
7397
  return;
7423
7398
  }
7424
7399
  const cutoff = now - SESSION_TTL_DAYS * DAY_MS;
7425
7400
  for (const name of names) {
7426
- const dir = join14(sessions, name);
7401
+ const dir = join13(sessions, name);
7427
7402
  try {
7428
- if (!statSync5(dir).isDirectory())
7403
+ if (!statSync4(dir).isDirectory())
7429
7404
  continue;
7430
7405
  } catch {
7431
7406
  continue;
@@ -7464,7 +7439,7 @@ var init_gc = __esm(() => {
7464
7439
 
7465
7440
  // src/cli/render.ts
7466
7441
  import { readFileSync as readFileSync9 } from "node:fs";
7467
- import { dirname as dirname6, join as join15 } from "node:path";
7442
+ import { dirname as dirname6, join as join14 } from "node:path";
7468
7443
  function readTextSafe(path) {
7469
7444
  try {
7470
7445
  return readFileSync9(path, "utf8");
@@ -7501,13 +7476,12 @@ function applyThemeIcons(fields, theme, config) {
7501
7476
  };
7502
7477
  });
7503
7478
  }
7504
- function readGated(overrides, envInputs, config, root, dir, markers, sessionState, clock) {
7479
+ function readGated(overrides, envInputs, config, root, dir, markers, clock) {
7505
7480
  const creds = overrides?.creds !== undefined ? overrides.creds : envInputs.hasApiKey || config.network.usage_fetch ? readCreds() : null;
7506
7481
  const usage = overrides?.usage !== undefined ? overrides.usage : config.network.usage_fetch ? readUsageCached(root) : null;
7507
7482
  const balance = overrides?.balance !== undefined ? overrides.balance : config.network.balance_path !== "" ? readBalance(config.network.balance_path, clock) : null;
7508
7483
  const helpfulEnv = needsHelpfulEnv(markers) ? readHelpfulEnv(dir) : EMPTY_HELPFUL_ENV;
7509
- const installed = sessionState.character === undefined && config.character.mode === "random" && config.character.roster.length === 0 ? listInstalledPacks(engineRoot(import.meta.url)) : [];
7510
- return { creds, usage, balance, helpfulEnv, installed };
7484
+ return { creds, usage, balance, helpfulEnv };
7511
7485
  }
7512
7486
  function lookupPackTheme(name) {
7513
7487
  const loaded = loadPack(name);
@@ -7534,10 +7508,10 @@ function build(stdin, env, term, clock, overrides) {
7534
7508
  return { line: "", persist: NOOP };
7535
7509
  const root = ccsidekickRoot(env);
7536
7510
  const base = dirname6(root);
7537
- const projectsRoot = join15(base, "projects");
7511
+ const projectsRoot = join14(base, "projects");
7538
7512
  const dir = payload.workspace.current_dir ?? payload.cwd ?? process.cwd();
7539
- const globalToml = readTextSafe(join15(root, "config.toml"));
7540
- 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"));
7541
7515
  const config = loadConfig(globalToml, projectToml);
7542
7516
  const envInputs = readEnv(env);
7543
7517
  const aliases = readModelAliases(env);
@@ -7552,8 +7526,8 @@ function build(stdin, env, term, clock, overrides) {
7552
7526
  const attribution = readAttribution(root);
7553
7527
  const costCache = readCostCache(root);
7554
7528
  const fxTable = readFxCached(root);
7555
- const { creds, usage, balance, helpfulEnv, installed } = readGated(overrides, envInputs, config, root, dir, markers, sessionState, clock);
7556
- 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);
7557
7531
  const loaded = loadPack(persona);
7558
7532
  const pack = loaded.ok ? loaded.pack : null;
7559
7533
  const project = deriveProject(git, payload);
@@ -7726,8 +7700,8 @@ var init_render2 = __esm(() => {
7726
7700
  });
7727
7701
 
7728
7702
  // src/cli/settings.ts
7729
- import { existsSync as existsSync3, readFileSync as readFileSync10, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
7730
- 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";
7731
7705
  function asRecord(v) {
7732
7706
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
7733
7707
  }
@@ -7751,9 +7725,9 @@ function isOurClassifyEntry(entry, classifyCmd) {
7751
7725
  function pruneBackups(settingsPath) {
7752
7726
  const dir = dirname7(settingsPath);
7753
7727
  const prefix = backupPrefix(settingsPath);
7754
- 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);
7755
7729
  for (const b of baks.slice(1, -1))
7756
- rmSync2(join16(dir, b.name), { force: true });
7730
+ rmSync2(join15(dir, b.name), { force: true });
7757
7731
  }
7758
7732
  function safeWriteJson(path, text, restoreText) {
7759
7733
  const tmp = `${path}.tmp.${String(process.pid)}.${Math.random().toString(36).slice(2)}`;
@@ -7808,7 +7782,7 @@ function installSettings(opts) {
7808
7782
  `, originalText);
7809
7783
  }
7810
7784
  function writeConfigToml(root, config) {
7811
- atomicWrite(join16(root, "config.toml"), stringify(config));
7785
+ atomicWrite(join15(root, "config.toml"), stringify(config));
7812
7786
  }
7813
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.`;
7814
7788
  var init_settings = __esm(() => {
@@ -7820,7 +7794,7 @@ var init_settings = __esm(() => {
7820
7794
 
7821
7795
  // src/cli/setup.ts
7822
7796
  import { readFileSync as readFileSync11 } from "node:fs";
7823
- import { join as join17 } from "node:path";
7797
+ import { join as join16 } from "node:path";
7824
7798
  function themeNames() {
7825
7799
  return [CHARACTER_THEME, ...Object.keys(THEMES), ...PACKS];
7826
7800
  }
@@ -7890,7 +7864,7 @@ function parseSetup(argv, homeDir, env) {
7890
7864
  if (bools.has("global") && bools.has("local"))
7891
7865
  errors.push("ccsidekick: pass only one of --global / --local");
7892
7866
  const scope = bools.has("local") ? "local" : "global";
7893
- const dir = pairs.get("config-dir") ?? env["CLAUDE_CONFIG_DIR"] ?? join17(homeDir, ".claude");
7867
+ const dir = pairs.get("config-dir") ?? env["CLAUDE_CONFIG_DIR"] ?? join16(homeDir, ".claude");
7894
7868
  return { flags, target: { scope, dir }, errors };
7895
7869
  }
7896
7870
  function applySetup(base, flags) {
@@ -7923,7 +7897,7 @@ function applySetup(base, flags) {
7923
7897
  };
7924
7898
  }
7925
7899
  function existingConfigPath(target, cwd) {
7926
- return target.scope === "global" ? join17(target.dir, "ccsidekick", "config.toml") : join17(cwd, ".ccsidekick", "config.toml");
7900
+ return target.scope === "global" ? join16(target.dir, "ccsidekick", "config.toml") : join16(cwd, ".ccsidekick", "config.toml");
7927
7901
  }
7928
7902
  function runSetup(argv, deps) {
7929
7903
  const parsed = parseSetup(argv, deps.homeDir, deps.env);
@@ -8071,8 +8045,8 @@ var init_setup = __esm(() => {
8071
8045
  });
8072
8046
 
8073
8047
  // src/cli/uninstall.ts
8074
- import { existsSync as existsSync4, readFileSync as readFileSync12, readdirSync as readdirSync6 } from "node:fs";
8075
- import { basename as basename4, dirname as dirname8, join as join18 } from "node:path";
8048
+ import { existsSync as existsSync4, readFileSync as readFileSync12, readdirSync as readdirSync5 } from "node:fs";
8049
+ import { basename as basename4, dirname as dirname8, join as join17 } from "node:path";
8076
8050
  function asRecord2(v) {
8077
8051
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
8078
8052
  }
@@ -8107,7 +8081,7 @@ function restoreNewestBackup(settingsPath) {
8107
8081
  const dir = dirname8(settingsPath);
8108
8082
  const prefix = `${basename4(settingsPath)}.ccsidekick-bak.`;
8109
8083
  let newest;
8110
- for (const f of readdirSync6(dir)) {
8084
+ for (const f of readdirSync5(dir)) {
8111
8085
  if (!f.startsWith(prefix))
8112
8086
  continue;
8113
8087
  const epoch = Number(f.slice(prefix.length));
@@ -8118,7 +8092,7 @@ function restoreNewestBackup(settingsPath) {
8118
8092
  }
8119
8093
  if (newest === undefined)
8120
8094
  return null;
8121
- atomicWrite(settingsPath, readFileSync12(join18(dir, newest.name), "utf8"));
8095
+ atomicWrite(settingsPath, readFileSync12(join17(dir, newest.name), "utf8"));
8122
8096
  return newest.name;
8123
8097
  }
8124
8098
  function runRestore(settingsPath, emit) {
@@ -8200,21 +8174,21 @@ var init_cli = __esm(() => {
8200
8174
  });
8201
8175
 
8202
8176
  // src/tui/configDirs.ts
8203
- import { existsSync as existsSync5, readdirSync as readdirSync7 } from "node:fs";
8204
- import { join as join19 } from "node:path";
8177
+ import { existsSync as existsSync5, readdirSync as readdirSync6 } from "node:fs";
8178
+ import { join as join18 } from "node:path";
8205
8179
  function discoverConfigDirs(homeDir, suggested) {
8206
- const home = join19(homeDir, ".claude");
8180
+ const home = join18(homeDir, ".claude");
8207
8181
  const set = new Set([home]);
8208
8182
  try {
8209
- for (const entry of readdirSync7(homeDir, { withFileTypes: true })) {
8183
+ for (const entry of readdirSync6(homeDir, { withFileTypes: true })) {
8210
8184
  if (entry.isDirectory() && entry.name.startsWith(".claude")) {
8211
- set.add(join19(homeDir, entry.name));
8185
+ set.add(join18(homeDir, entry.name));
8212
8186
  }
8213
8187
  }
8214
8188
  } catch {}
8215
8189
  if (suggested !== undefined && suggested !== "")
8216
8190
  set.add(suggested);
8217
- const dirs = [...set].filter((d) => existsSync5(join19(d, "settings.json"))).sort();
8191
+ const dirs = [...set].filter((d) => existsSync5(join18(d, "settings.json"))).sort();
8218
8192
  let suggestedIndex = 0;
8219
8193
  if (suggested !== undefined && suggested !== "" && dirs.includes(suggested)) {
8220
8194
  suggestedIndex = dirs.indexOf(suggested);
@@ -8255,18 +8229,11 @@ var ACCENT = "#ffd700", FRAME = "gray", DANGER = "red";
8255
8229
 
8256
8230
  // src/tui/save.ts
8257
8231
  import { mkdirSync as mkdirSync4 } from "node:fs";
8258
- import { join as join20 } from "node:path";
8232
+ import { join as join19 } from "node:path";
8259
8233
  function defaultResolveVerbs(name) {
8260
8234
  const loaded = loadPack(name);
8261
8235
  return loaded.ok ? loaded.pack.spinnerVerbs : [];
8262
8236
  }
8263
- function defaultInstalled() {
8264
- try {
8265
- return listInstalledPacks(engineRoot(import.meta.url));
8266
- } catch {
8267
- return [];
8268
- }
8269
- }
8270
8237
  function spinnerVerbUnion(config, resolveVerbs, installed) {
8271
8238
  const candidates = config.character.mode === "fixed" ? [config.character.name] : config.character.roster.length > 0 ? [...config.character.roster] : [...installed];
8272
8239
  const seen = new Set;
@@ -8286,21 +8253,21 @@ function normalize(config) {
8286
8253
  }
8287
8254
  function save(config, scope, dir, renderBin, opts = {}) {
8288
8255
  const resolveVerbs = opts.resolveVerbs ?? defaultResolveVerbs;
8289
- const installed = opts.installed ?? defaultInstalled();
8256
+ const installed = opts.installed ?? PACKS;
8290
8257
  const cwd = opts.cwd ?? process.cwd();
8291
8258
  const normalized = normalize(config);
8292
8259
  const spinnerVerbs = spinnerVerbUnion(normalized, resolveVerbs, installed);
8293
8260
  if (scope === "global") {
8294
- writeConfigToml(join20(dir, "ccsidekick"), normalized);
8295
- installSettings({ settingsPath: join20(dir, "settings.json"), renderBin, spinnerVerbs });
8261
+ writeConfigToml(join19(dir, "ccsidekick"), normalized);
8262
+ installSettings({ settingsPath: join19(dir, "settings.json"), renderBin, spinnerVerbs });
8296
8263
  return;
8297
8264
  }
8298
- writeConfigToml(join20(cwd, ".ccsidekick"), normalized);
8265
+ writeConfigToml(join19(cwd, ".ccsidekick"), normalized);
8299
8266
  if (opts.wireLocalSettings === true) {
8300
- const claudeDir = join20(cwd, ".claude");
8267
+ const claudeDir = join19(cwd, ".claude");
8301
8268
  mkdirSync4(claudeDir, { recursive: true });
8302
8269
  installSettings({
8303
- settingsPath: join20(claudeDir, "settings.json"),
8270
+ settingsPath: join19(claudeDir, "settings.json"),
8304
8271
  renderBin,
8305
8272
  spinnerVerbs
8306
8273
  });
@@ -10998,9 +10965,9 @@ var init_PreviewPanel = __esm(() => {
10998
10965
  import { execFileSync } from "node:child_process";
10999
10966
  import { existsSync as existsSync6, mkdirSync as mkdirSync5, mkdtempSync, realpathSync, writeFileSync as writeFileSync4 } from "node:fs";
11000
10967
  import { tmpdir } from "node:os";
11001
- import { join as join21 } from "node:path";
10968
+ import { join as join20 } from "node:path";
11002
10969
  function seedTranscriptFixture(workdir) {
11003
- const path = join21(workdir, "preview-transcript.jsonl");
10970
+ const path = join20(workdir, "preview-transcript.jsonl");
11004
10971
  try {
11005
10972
  mkdirSync5(workdir, { recursive: true });
11006
10973
  if (!existsSync6(path)) {
@@ -11071,7 +11038,7 @@ function gitEnv() {
11071
11038
  function setupGitFixture(workdir) {
11072
11039
  try {
11073
11040
  mkdirSync5(workdir, { recursive: true });
11074
- if (existsSync6(join21(workdir, ".git")))
11041
+ if (existsSync6(join20(workdir, ".git")))
11075
11042
  return;
11076
11043
  const env2 = gitEnv();
11077
11044
  const git = (...args) => {
@@ -11081,20 +11048,20 @@ function setupGitFixture(workdir) {
11081
11048
  git("config", "user.email", "wayne@example.com");
11082
11049
  git("config", "user.name", "Bruce Wayne");
11083
11050
  git("remote", "add", "origin", "https://github.com/wayne/ccsidekick.git");
11084
- writeFileSync4(join21(workdir, "README.md"), `# ccsidekick
11051
+ writeFileSync4(join20(workdir, "README.md"), `# ccsidekick
11085
11052
 
11086
11053
  original line
11087
11054
  keep me
11088
11055
  `);
11089
11056
  git("add", "README.md");
11090
11057
  git("commit", "-q", "-m", "initial commit");
11091
- writeFileSync4(join21(workdir, "README.md"), `# ccsidekick
11058
+ writeFileSync4(join20(workdir, "README.md"), `# ccsidekick
11092
11059
 
11093
11060
  edited line
11094
11061
  keep me
11095
11062
  new line
11096
11063
  `);
11097
- writeFileSync4(join21(workdir, "src.ts"), `export const answer = 42;
11064
+ writeFileSync4(join20(workdir, "src.ts"), `export const answer = 42;
11098
11065
  `);
11099
11066
  git("add", "src.ts");
11100
11067
  } catch {}
@@ -11116,24 +11083,24 @@ function transcriptLine(id, model, inputTokens, outputTokens) {
11116
11083
  });
11117
11084
  }
11118
11085
  function seedCostFixture(root, workdir) {
11119
- const projectsRoot = join21(root, "projects");
11120
- const currentProjectDir = join21(projectsRoot, workdir.replace(/[/.]/g, "-"));
11121
- const otherProjectDir = join21(projectsRoot, "-other-project");
11086
+ const projectsRoot = join20(root, "projects");
11087
+ const currentProjectDir = join20(projectsRoot, workdir.replace(/[/.]/g, "-"));
11088
+ const otherProjectDir = join20(projectsRoot, "-other-project");
11122
11089
  mkdirSync5(currentProjectDir, { recursive: true });
11123
11090
  mkdirSync5(otherProjectDir, { recursive: true });
11124
- writeFileSync4(join21(currentProjectDir, "sess-a.jsonl"), `${transcriptLine("sess-a-1", "claude-opus-4-8", 1e5, 20000)}
11091
+ writeFileSync4(join20(currentProjectDir, "sess-a.jsonl"), `${transcriptLine("sess-a-1", "claude-opus-4-8", 1e5, 20000)}
11125
11092
  `);
11126
- writeFileSync4(join21(otherProjectDir, "sess-b.jsonl"), `${transcriptLine("sess-b-1", "claude-opus-4-8", 200000, 50000)}
11093
+ writeFileSync4(join20(otherProjectDir, "sess-b.jsonl"), `${transcriptLine("sess-b-1", "claude-opus-4-8", 200000, 50000)}
11127
11094
  `);
11128
11095
  }
11129
11096
  function scratchRoot(scratchDir) {
11130
11097
  if (scratchDir !== undefined)
11131
11098
  return scratchDir;
11132
- sharedScratch ??= mkdtempSync(join21(tmpdir(), "ccsidekick-preview-"));
11099
+ sharedScratch ??= mkdtempSync(join20(tmpdir(), "ccsidekick-preview-"));
11133
11100
  return sharedScratch;
11134
11101
  }
11135
11102
  function previewEnv(root, extra) {
11136
- const homeBase = join21(root, "home");
11103
+ const homeBase = join20(root, "home");
11137
11104
  mkdirSync5(homeBase, { recursive: true });
11138
11105
  let home = homeBase;
11139
11106
  try {
@@ -11210,15 +11177,15 @@ var init_scenarios = __esm(() => {
11210
11177
  });
11211
11178
 
11212
11179
  // src/tui/preview/render.ts
11213
- import { join as join22 } from "node:path";
11180
+ import { join as join21 } from "node:path";
11214
11181
  function renderScenario(scenario, draft, opts) {
11215
11182
  try {
11216
11183
  const clock = opts.clock ?? DEFAULT_CLOCK;
11217
11184
  const root = scratchRoot(opts.scratchDir);
11218
- writeConfigToml(join22(root, "ccsidekick"), draft);
11185
+ writeConfigToml(join21(root, "ccsidekick"), draft);
11219
11186
  const env2 = previewEnv(root, scenario.env ?? {});
11220
11187
  const home = env2["HOME"] ?? root;
11221
- const workdir = join22(home, "ccsidekick");
11188
+ const workdir = join21(home, "ccsidekick");
11222
11189
  setupGitFixture(workdir);
11223
11190
  seedCostFixture(root, workdir);
11224
11191
  const term = { columns: opts.columns, noColor: opts.noColor, isTTY: true };
@@ -12917,7 +12884,7 @@ var init_inputRoute = __esm(() => {
12917
12884
 
12918
12885
  // src/tui/shell/saveTarget.ts
12919
12886
  import { existsSync as existsSync8, readFileSync as readFileSync13 } from "node:fs";
12920
- import { join as join23 } from "node:path";
12887
+ import { join as join22 } from "node:path";
12921
12888
  function chipFor(targets) {
12922
12889
  if (targets.every((t) => t.scope === "global"))
12923
12890
  return "global";
@@ -12936,12 +12903,12 @@ function alreadyWired(settingsPath) {
12936
12903
  }
12937
12904
  }
12938
12905
  function projectTarget(cwd, _homeDir) {
12939
- const dir = join23(cwd, ".claude");
12906
+ const dir = join22(cwd, ".claude");
12940
12907
  return {
12941
12908
  dir,
12942
12909
  scope: "local",
12943
12910
  cwd,
12944
- wireLocalSettings: !alreadyWired(join23(dir, "settings.json"))
12911
+ wireLocalSettings: !alreadyWired(join22(dir, "settings.json"))
12945
12912
  };
12946
12913
  }
12947
12914
  var init_saveTarget = __esm(() => {
@@ -13184,7 +13151,7 @@ var init_useMouseWheel = __esm(() => {
13184
13151
 
13185
13152
  // src/tui/shell/Dashboard.tsx
13186
13153
  import { readFileSync as readFileSync14 } from "node:fs";
13187
- import { join as join24 } from "node:path";
13154
+ import { join as join23 } from "node:path";
13188
13155
  import { Box as Box30, Text as Text35, useApp as useApp2, useInput as useInput8 } from "ink";
13189
13156
  import { useCallback as useCallback6, useMemo as useMemo9, useState as useState8 } from "react";
13190
13157
  import { jsxDEV as jsxDEV22 } from "react/jsx-dev-runtime";
@@ -13202,7 +13169,7 @@ function Dashboard(props) {
13202
13169
  const [nav, setNav] = useState8(INITIAL_NAV);
13203
13170
  const [targets, setTargets] = useState8(props.targets);
13204
13171
  const configDir2 = targets[0]?.dir ?? "";
13205
- const root = join24(configDir2, "ccsidekick");
13172
+ const root = join23(configDir2, "ccsidekick");
13206
13173
  const [draft, setDraft] = useState8(() => seed(configDir2, initialConfig));
13207
13174
  const [dirty2, setDirty] = useState8(props.initialDirty ?? false);
13208
13175
  const [cursor4, setCursor] = useState8(0);
@@ -13982,7 +13949,7 @@ var seed = (configDir2, initial) => {
13982
13949
  if (initial)
13983
13950
  return initial;
13984
13951
  try {
13985
- return loadConfig(readFileSync14(join24(configDir2, "ccsidekick", "config.toml"), "utf8"));
13952
+ return loadConfig(readFileSync14(join23(configDir2, "ccsidekick", "config.toml"), "utf8"));
13986
13953
  } catch {
13987
13954
  return loadConfig("");
13988
13955
  }
@@ -14627,7 +14594,7 @@ var init_Wizard = __esm(() => {
14627
14594
  // src/tui/shell/App.tsx
14628
14595
  import { existsSync as existsSync9, readFileSync as readFileSync15 } from "node:fs";
14629
14596
  import { homedir as homedir6 } from "node:os";
14630
- import { join as join25 } from "node:path";
14597
+ import { join as join24 } from "node:path";
14631
14598
  import { useInput as useInput10 } from "ink";
14632
14599
  import { useMemo as useMemo10, useState as useState10 } from "react";
14633
14600
  import { jsxDEV as jsxDEV26 } from "react/jsx-dev-runtime";
@@ -14640,7 +14607,7 @@ function welcomeTheme(suggestedDir) {
14640
14607
  if (suggestedDir === undefined || suggestedDir === "")
14641
14608
  return THEMES.houston;
14642
14609
  try {
14643
- const text = readFileSync15(join25(suggestedDir, "ccsidekick", "config.toml"), "utf8");
14610
+ const text = readFileSync15(join24(suggestedDir, "ccsidekick", "config.toml"), "utf8");
14644
14611
  return pickTheme(loadConfig(text).theme.name);
14645
14612
  } catch {
14646
14613
  return THEMES.houston;
@@ -14650,7 +14617,7 @@ function initialChosenDirs(configDir2) {
14650
14617
  return configDir2 === undefined ? null : [{ dir: configDir2, scope: "global" }];
14651
14618
  }
14652
14619
  function configPathFor(t) {
14653
- return t.scope === "global" ? join25(t.dir, "ccsidekick", "config.toml") : join25(t.cwd ?? "", ".ccsidekick", "config.toml");
14620
+ return t.scope === "global" ? join24(t.dir, "ccsidekick", "config.toml") : join24(t.cwd ?? "", ".ccsidekick", "config.toml");
14654
14621
  }
14655
14622
  function isFirstRun(targets) {
14656
14623
  return !targets.some((t) => existsSync9(configPathFor(t)));
@@ -14801,11 +14768,11 @@ init_cli();
14801
14768
  init_domain();
14802
14769
  init_tui();
14803
14770
  import { homedir as homedir7 } from "node:os";
14804
- import { join as join26 } from "node:path";
14805
- import { fileURLToPath as fileURLToPath3 } from "node:url";
14771
+ import { join as join25 } from "node:path";
14772
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
14806
14773
  var sub = process.argv[2];
14807
14774
  function claudeDir() {
14808
- return process.env["CLAUDE_CONFIG_DIR"] ?? join26(homedir7(), ".claude");
14775
+ return process.env["CLAUDE_CONFIG_DIR"] ?? join25(homedir7(), ".claude");
14809
14776
  }
14810
14777
  function printHelp() {
14811
14778
  process.stdout.write([
@@ -14835,7 +14802,7 @@ function printManualSetup() {
14835
14802
  "Run `ccsidekick` directly in your terminal to configure and wire it.",
14836
14803
  "",
14837
14804
  "To wire it by hand, add to your Claude Code settings.json:",
14838
- ` • settings.json: ${join26(dir, "settings.json")}`,
14805
+ ` • settings.json: ${join25(dir, "settings.json")}`,
14839
14806
  ` • "statusLine": { "type": "command", "command": "ccsidekick-render render", "refreshInterval": ${String(REFRESH_INTERVAL_SEC)} }`,
14840
14807
  ' • three hooks, each running "ccsidekick-render classify" with the same matcher:',
14841
14808
  ' "PostToolUse", "PostToolUseFailure", and "PostToolBatch"',
@@ -14847,7 +14814,7 @@ async function launchTui() {
14847
14814
  const { render } = await import("ink");
14848
14815
  const { createElement } = await import("react");
14849
14816
  const { App: App2 } = await Promise.resolve().then(() => (init_shell(), exports_shell));
14850
- const renderBin = fileURLToPath3(new URL("ccsidekick-render.js", import.meta.url));
14817
+ const renderBin = fileURLToPath2(new URL("ccsidekick-render.js", import.meta.url));
14851
14818
  const suggested = process.env["CLAUDE_CONFIG_DIR"];
14852
14819
  const instance = render(createElement(App2, {
14853
14820
  homeDir: homedir7(),
@@ -14863,7 +14830,7 @@ async function main() {
14863
14830
  }
14864
14831
  if (sub === "uninstall") {
14865
14832
  runUninstall({
14866
- settingsPath: join26(claudeDir(), "settings.json"),
14833
+ settingsPath: join25(claudeDir(), "settings.json"),
14867
14834
  restoreBackup: process.argv.includes("--restore-backup")
14868
14835
  });
14869
14836
  process.exit(0);
@@ -14877,7 +14844,7 @@ async function main() {
14877
14844
  process.stdout.write(setupHelp());
14878
14845
  process.exit(0);
14879
14846
  }
14880
- const renderBin = fileURLToPath3(new URL("ccsidekick-render.js", import.meta.url));
14847
+ const renderBin = fileURLToPath2(new URL("ccsidekick-render.js", import.meta.url));
14881
14848
  const code = runSetup(process.argv.slice(3), {
14882
14849
  save,
14883
14850
  renderBin,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccsidekick",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -24,6 +24,9 @@
24
24
  "@ccsidekick/pack-harry-potter": "1.0.0",
25
25
  "@ccsidekick/pack-hello-kitty": "1.0.0",
26
26
  "@ccsidekick/pack-james-bond": "1.0.0",
27
+ "@ccsidekick/pack-joker": "1.0.0",
28
+ "@ccsidekick/pack-pikachu": "1.0.0",
29
+ "@ccsidekick/pack-sherlock-holmes": "1.0.0",
27
30
  "@ccsidekick/pack-spiderman": "1.0.0",
28
31
  "@inkjs/ui": "2.0.0",
29
32
  "ink": "^5.2.0",