claudekit-cli 3.22.0 → 3.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +161 -72
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12606,7 +12606,7 @@ var require_get_stream = __commonJS((exports, module) => {
12606
12606
  };
12607
12607
  const { maxBuffer } = options;
12608
12608
  let stream;
12609
- await new Promise((resolve6, reject) => {
12609
+ await new Promise((resolve5, reject) => {
12610
12610
  const rejectPromise = (error) => {
12611
12611
  if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
12612
12612
  error.bufferedData = stream.getBufferedValue();
@@ -12618,7 +12618,7 @@ var require_get_stream = __commonJS((exports, module) => {
12618
12618
  rejectPromise(error);
12619
12619
  return;
12620
12620
  }
12621
- resolve6();
12621
+ resolve5();
12622
12622
  });
12623
12623
  stream.on("data", () => {
12624
12624
  if (stream.getBufferedLength() > maxBuffer) {
@@ -13979,7 +13979,7 @@ var require_extract_zip = __commonJS((exports, module) => {
13979
13979
  debug("opening", this.zipPath, "with opts", this.opts);
13980
13980
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
13981
13981
  this.canceled = false;
13982
- return new Promise((resolve6, reject) => {
13982
+ return new Promise((resolve5, reject) => {
13983
13983
  this.zipfile.on("error", (err) => {
13984
13984
  this.canceled = true;
13985
13985
  reject(err);
@@ -13988,7 +13988,7 @@ var require_extract_zip = __commonJS((exports, module) => {
13988
13988
  this.zipfile.on("close", () => {
13989
13989
  if (!this.canceled) {
13990
13990
  debug("zip extraction complete");
13991
- resolve6();
13991
+ resolve5();
13992
13992
  }
13993
13993
  });
13994
13994
  this.zipfile.on("entry", async (entry) => {
@@ -16592,7 +16592,7 @@ function getPagerArgs(pagerCmd) {
16592
16592
  return [];
16593
16593
  }
16594
16594
  async function trySystemPager(content) {
16595
- return new Promise((resolve11) => {
16595
+ return new Promise((resolve10) => {
16596
16596
  const pagerCmd = process.env.PAGER || "less";
16597
16597
  const pagerArgs = getPagerArgs(pagerCmd);
16598
16598
  try {
@@ -16602,20 +16602,20 @@ async function trySystemPager(content) {
16602
16602
  });
16603
16603
  const timeout = setTimeout(() => {
16604
16604
  pager.kill();
16605
- resolve11(false);
16605
+ resolve10(false);
16606
16606
  }, 30000);
16607
16607
  pager.stdin.write(content);
16608
16608
  pager.stdin.end();
16609
16609
  pager.on("close", (code2) => {
16610
16610
  clearTimeout(timeout);
16611
- resolve11(code2 === 0);
16611
+ resolve10(code2 === 0);
16612
16612
  });
16613
16613
  pager.on("error", () => {
16614
16614
  clearTimeout(timeout);
16615
- resolve11(false);
16615
+ resolve10(false);
16616
16616
  });
16617
16617
  } catch {
16618
- resolve11(false);
16618
+ resolve10(false);
16619
16619
  }
16620
16620
  });
16621
16621
  }
@@ -16642,16 +16642,16 @@ async function basicPager(content) {
16642
16642
  break;
16643
16643
  }
16644
16644
  const remaining = lines.length - currentLine;
16645
- await new Promise((resolve11) => {
16645
+ await new Promise((resolve10) => {
16646
16646
  rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
16647
16647
  if (answer.toLowerCase() === "q") {
16648
16648
  rl.close();
16649
16649
  process.exitCode = 0;
16650
- resolve11();
16650
+ resolve10();
16651
16651
  return;
16652
16652
  }
16653
16653
  process.stdout.write("\x1B[1A\x1B[2K");
16654
- resolve11();
16654
+ resolve10();
16655
16655
  });
16656
16656
  });
16657
16657
  }
@@ -18507,6 +18507,20 @@ class PathResolver {
18507
18507
  static isWSL() {
18508
18508
  return isWSL();
18509
18509
  }
18510
+ static isAtHomeDirectory(cwd) {
18511
+ const currentDir = normalize(cwd || process.cwd());
18512
+ const homeDir = normalize(homedir());
18513
+ return currentDir === homeDir;
18514
+ }
18515
+ static getLocalClaudeDir(baseDir) {
18516
+ const dir = baseDir || process.cwd();
18517
+ return join(dir, ".claude");
18518
+ }
18519
+ static isLocalSameAsGlobal(cwd) {
18520
+ const localPath = normalize(PathResolver.getLocalClaudeDir(cwd));
18521
+ const globalPath = normalize(PathResolver.getGlobalKitDir());
18522
+ return localPath === globalPath;
18523
+ }
18510
18524
  }
18511
18525
 
18512
18526
  // src/shared/skip-directories.ts
@@ -18621,7 +18635,8 @@ async function getClaudeKitSetup(projectDir = process.cwd()) {
18621
18635
  setup.global.components = await scanClaudeKitDirectory(globalDir);
18622
18636
  }
18623
18637
  const projectClaudeDir = join2(projectDir, ".claude");
18624
- if (await import_fs_extra.pathExists(projectClaudeDir)) {
18638
+ const isLocalSameAsGlobal = projectClaudeDir === globalDir;
18639
+ if (!isLocalSameAsGlobal && await import_fs_extra.pathExists(projectClaudeDir)) {
18625
18640
  setup.project.path = projectClaudeDir;
18626
18641
  setup.project.metadata = await readClaudeKitMetadata(join2(projectClaudeDir, "metadata.json"));
18627
18642
  setup.project.components = await scanClaudeKitDirectory(projectClaudeDir);
@@ -22383,11 +22398,15 @@ function getInstalledKits(metadata) {
22383
22398
  return Object.keys(metadata.kits);
22384
22399
  }
22385
22400
  const nameToCheck = metadata.name || "";
22401
+ const kits = [];
22386
22402
  if (/\bengineer\b/i.test(nameToCheck)) {
22387
- return ["engineer"];
22403
+ kits.push("engineer");
22388
22404
  }
22389
22405
  if (/\bmarketing\b/i.test(nameToCheck)) {
22390
- return ["marketing"];
22406
+ kits.push("marketing");
22407
+ }
22408
+ if (kits.length > 0) {
22409
+ return kits;
22391
22410
  }
22392
22411
  if (metadata.version) {
22393
22412
  return ["engineer"];
@@ -24815,6 +24834,28 @@ class PromptsManager {
24815
24834
  async promptDirectorySelection(global2 = false) {
24816
24835
  return promptDirectorySelection(global2);
24817
24836
  }
24837
+ async selectScope() {
24838
+ const options = [
24839
+ {
24840
+ value: "global",
24841
+ label: "Install globally",
24842
+ hint: "Continue installing to ~/.claude/"
24843
+ },
24844
+ {
24845
+ value: "different",
24846
+ label: "Use a different directory",
24847
+ hint: "Cancel and run from a project directory"
24848
+ }
24849
+ ];
24850
+ const selected = await ie({
24851
+ message: "What would you like to do?",
24852
+ options
24853
+ });
24854
+ if (lD(selected)) {
24855
+ return "cancel";
24856
+ }
24857
+ return selected;
24858
+ }
24818
24859
  }
24819
24860
 
24820
24861
  // src/commands/init/init-command.ts
@@ -24864,18 +24905,18 @@ init_types2();
24864
24905
 
24865
24906
  // src/commands/init/phases/conflict-handler.ts
24866
24907
  init_logger();
24867
- import { join as join27, resolve as resolve4 } from "node:path";
24908
+ import { join as join27 } from "node:path";
24868
24909
  var import_fs_extra3 = __toESM(require_lib(), 1);
24869
24910
  async function handleConflicts(ctx) {
24870
24911
  if (ctx.cancelled)
24871
24912
  return ctx;
24872
24913
  if (!ctx.options.global)
24873
24914
  return ctx;
24874
- const globalKitDir = PathResolver.getGlobalKitDir();
24875
- const cwdResolved = resolve4(process.cwd());
24876
- const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve4(globalKitDir, "..");
24915
+ if (PathResolver.isLocalSameAsGlobal()) {
24916
+ return ctx;
24917
+ }
24877
24918
  const localSettingsPath = join27(process.cwd(), ".claude", "settings.json");
24878
- if (isInGlobalDir || !await import_fs_extra3.pathExists(localSettingsPath)) {
24919
+ if (!await import_fs_extra3.pathExists(localSettingsPath)) {
24879
24920
  return ctx;
24880
24921
  }
24881
24922
  if (ctx.isNonInteractive) {
@@ -26503,11 +26544,11 @@ init_types2();
26503
26544
 
26504
26545
  // src/domains/installation/utils/path-security.ts
26505
26546
  init_types2();
26506
- import { relative as relative3, resolve as resolve5 } from "node:path";
26547
+ import { relative as relative3, resolve as resolve4 } from "node:path";
26507
26548
  var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
26508
26549
  function isPathSafe(basePath, targetPath) {
26509
- const resolvedBase = resolve5(basePath);
26510
- const resolvedTarget = resolve5(targetPath);
26550
+ const resolvedBase = resolve4(basePath);
26551
+ const resolvedTarget = resolve4(targetPath);
26511
26552
  const relativePath = relative3(resolvedBase, resolvedTarget);
26512
26553
  return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
26513
26554
  }
@@ -27244,10 +27285,10 @@ class Minipass extends EventEmitter2 {
27244
27285
  return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
27245
27286
  }
27246
27287
  async promise() {
27247
- return new Promise((resolve6, reject) => {
27288
+ return new Promise((resolve5, reject) => {
27248
27289
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
27249
27290
  this.on("error", (er) => reject(er));
27250
- this.on("end", () => resolve6());
27291
+ this.on("end", () => resolve5());
27251
27292
  });
27252
27293
  }
27253
27294
  [Symbol.asyncIterator]() {
@@ -27266,7 +27307,7 @@ class Minipass extends EventEmitter2 {
27266
27307
  return Promise.resolve({ done: false, value: res });
27267
27308
  if (this[EOF])
27268
27309
  return stop();
27269
- let resolve6;
27310
+ let resolve5;
27270
27311
  let reject;
27271
27312
  const onerr = (er) => {
27272
27313
  this.off("data", ondata);
@@ -27280,19 +27321,19 @@ class Minipass extends EventEmitter2 {
27280
27321
  this.off("end", onend);
27281
27322
  this.off(DESTROYED, ondestroy);
27282
27323
  this.pause();
27283
- resolve6({ value, done: !!this[EOF] });
27324
+ resolve5({ value, done: !!this[EOF] });
27284
27325
  };
27285
27326
  const onend = () => {
27286
27327
  this.off("error", onerr);
27287
27328
  this.off("data", ondata);
27288
27329
  this.off(DESTROYED, ondestroy);
27289
27330
  stop();
27290
- resolve6({ done: true, value: undefined });
27331
+ resolve5({ done: true, value: undefined });
27291
27332
  };
27292
27333
  const ondestroy = () => onerr(new Error("stream destroyed"));
27293
27334
  return new Promise((res2, rej) => {
27294
27335
  reject = rej;
27295
- resolve6 = res2;
27336
+ resolve5 = res2;
27296
27337
  this.once(DESTROYED, ondestroy);
27297
27338
  this.once("error", onerr);
27298
27339
  this.once("end", onend);
@@ -28398,10 +28439,10 @@ class Minipass2 extends EventEmitter3 {
28398
28439
  return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
28399
28440
  }
28400
28441
  async promise() {
28401
- return new Promise((resolve6, reject) => {
28442
+ return new Promise((resolve5, reject) => {
28402
28443
  this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
28403
28444
  this.on("error", (er) => reject(er));
28404
- this.on("end", () => resolve6());
28445
+ this.on("end", () => resolve5());
28405
28446
  });
28406
28447
  }
28407
28448
  [Symbol.asyncIterator]() {
@@ -28420,7 +28461,7 @@ class Minipass2 extends EventEmitter3 {
28420
28461
  return Promise.resolve({ done: false, value: res });
28421
28462
  if (this[EOF2])
28422
28463
  return stop();
28423
- let resolve6;
28464
+ let resolve5;
28424
28465
  let reject;
28425
28466
  const onerr = (er) => {
28426
28467
  this.off("data", ondata);
@@ -28434,19 +28475,19 @@ class Minipass2 extends EventEmitter3 {
28434
28475
  this.off("end", onend);
28435
28476
  this.off(DESTROYED2, ondestroy);
28436
28477
  this.pause();
28437
- resolve6({ value, done: !!this[EOF2] });
28478
+ resolve5({ value, done: !!this[EOF2] });
28438
28479
  };
28439
28480
  const onend = () => {
28440
28481
  this.off("error", onerr);
28441
28482
  this.off("data", ondata);
28442
28483
  this.off(DESTROYED2, ondestroy);
28443
28484
  stop();
28444
- resolve6({ done: true, value: undefined });
28485
+ resolve5({ done: true, value: undefined });
28445
28486
  };
28446
28487
  const ondestroy = () => onerr(new Error("stream destroyed"));
28447
28488
  return new Promise((res2, rej) => {
28448
28489
  reject = rej;
28449
- resolve6 = res2;
28490
+ resolve5 = res2;
28450
28491
  this.once(DESTROYED2, ondestroy);
28451
28492
  this.once("error", onerr);
28452
28493
  this.once("end", onend);
@@ -29874,10 +29915,10 @@ class Minipass3 extends EventEmitter4 {
29874
29915
  return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
29875
29916
  }
29876
29917
  async promise() {
29877
- return new Promise((resolve6, reject) => {
29918
+ return new Promise((resolve5, reject) => {
29878
29919
  this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
29879
29920
  this.on("error", (er) => reject(er));
29880
- this.on("end", () => resolve6());
29921
+ this.on("end", () => resolve5());
29881
29922
  });
29882
29923
  }
29883
29924
  [Symbol.asyncIterator]() {
@@ -29896,7 +29937,7 @@ class Minipass3 extends EventEmitter4 {
29896
29937
  return Promise.resolve({ done: false, value: res });
29897
29938
  if (this[EOF3])
29898
29939
  return stop();
29899
- let resolve6;
29940
+ let resolve5;
29900
29941
  let reject;
29901
29942
  const onerr = (er) => {
29902
29943
  this.off("data", ondata);
@@ -29910,19 +29951,19 @@ class Minipass3 extends EventEmitter4 {
29910
29951
  this.off("end", onend);
29911
29952
  this.off(DESTROYED3, ondestroy);
29912
29953
  this.pause();
29913
- resolve6({ value, done: !!this[EOF3] });
29954
+ resolve5({ value, done: !!this[EOF3] });
29914
29955
  };
29915
29956
  const onend = () => {
29916
29957
  this.off("error", onerr);
29917
29958
  this.off("data", ondata);
29918
29959
  this.off(DESTROYED3, ondestroy);
29919
29960
  stop();
29920
- resolve6({ done: true, value: undefined });
29961
+ resolve5({ done: true, value: undefined });
29921
29962
  };
29922
29963
  const ondestroy = () => onerr(new Error("stream destroyed"));
29923
29964
  return new Promise((res2, rej) => {
29924
29965
  reject = rej;
29925
- resolve6 = res2;
29966
+ resolve5 = res2;
29926
29967
  this.once(DESTROYED3, ondestroy);
29927
29968
  this.once("error", onerr);
29928
29969
  this.once("end", onend);
@@ -30693,9 +30734,9 @@ var listFile = (opt, _files) => {
30693
30734
  const parse3 = new Parser(opt);
30694
30735
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
30695
30736
  const file = opt.file;
30696
- const p = new Promise((resolve6, reject) => {
30737
+ const p = new Promise((resolve5, reject) => {
30697
30738
  parse3.on("error", reject);
30698
- parse3.on("end", resolve6);
30739
+ parse3.on("end", resolve5);
30699
30740
  fs4.stat(file, (er, stat3) => {
30700
30741
  if (er) {
30701
30742
  reject(er);
@@ -33275,9 +33316,9 @@ var extractFile = (opt, _3) => {
33275
33316
  const u = new Unpack(opt);
33276
33317
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
33277
33318
  const file = opt.file;
33278
- const p = new Promise((resolve6, reject) => {
33319
+ const p = new Promise((resolve5, reject) => {
33279
33320
  u.on("error", reject);
33280
- u.on("close", resolve6);
33321
+ u.on("close", resolve5);
33281
33322
  fs11.stat(file, (er, stat3) => {
33282
33323
  if (er) {
33283
33324
  reject(er);
@@ -33410,7 +33451,7 @@ var replaceAsync = (opt, files) => {
33410
33451
  };
33411
33452
  fs12.read(fd, headBuf, 0, 512, position, onread);
33412
33453
  };
33413
- const promise = new Promise((resolve6, reject) => {
33454
+ const promise = new Promise((resolve5, reject) => {
33414
33455
  p.on("error", reject);
33415
33456
  let flag = "r+";
33416
33457
  const onopen = (er, fd) => {
@@ -33435,7 +33476,7 @@ var replaceAsync = (opt, files) => {
33435
33476
  });
33436
33477
  p.pipe(stream);
33437
33478
  stream.on("error", reject);
33438
- stream.on("close", resolve6);
33479
+ stream.on("close", resolve5);
33439
33480
  addFilesAsync2(p, files);
33440
33481
  });
33441
33482
  });
@@ -33709,20 +33750,20 @@ class ZipExtractor {
33709
33750
  if (!isMacOS()) {
33710
33751
  return false;
33711
33752
  }
33712
- return new Promise((resolve6) => {
33753
+ return new Promise((resolve5) => {
33713
33754
  mkdir13(destDir, { recursive: true }).then(() => {
33714
33755
  execFile2("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
33715
33756
  if (error) {
33716
33757
  logger.debug(`Native unzip failed: ${stderr || error.message}`);
33717
- resolve6(false);
33758
+ resolve5(false);
33718
33759
  return;
33719
33760
  }
33720
33761
  logger.debug("Native unzip succeeded");
33721
- resolve6(true);
33762
+ resolve5(true);
33722
33763
  });
33723
33764
  }).catch((err) => {
33724
33765
  logger.debug(`Failed to create directory for native unzip: ${err.message}`);
33725
- resolve6(false);
33766
+ resolve5(false);
33726
33767
  });
33727
33768
  });
33728
33769
  }
@@ -37352,6 +37393,8 @@ class LegacyMigration {
37352
37393
  for (const entry of entries) {
37353
37394
  if (entry === "metadata.json")
37354
37395
  continue;
37396
+ if (SKIP_DIRS_ALL.includes(entry))
37397
+ continue;
37355
37398
  const fullPath = join44(dir, entry);
37356
37399
  let stats;
37357
37400
  try {
@@ -37578,7 +37621,7 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
37578
37621
  }
37579
37622
 
37580
37623
  // src/services/file-operations/file-scanner.ts
37581
- import { join as join45, relative as relative8, resolve as resolve7 } from "node:path";
37624
+ import { join as join45, relative as relative8, resolve as resolve6 } from "node:path";
37582
37625
  init_logger();
37583
37626
  var import_fs_extra12 = __toESM(require_lib(), 1);
37584
37627
 
@@ -37660,8 +37703,8 @@ class FileScanner2 {
37660
37703
  return customFiles;
37661
37704
  }
37662
37705
  static isSafePath(basePath, targetPath) {
37663
- const resolvedBase = resolve7(basePath);
37664
- const resolvedTarget = resolve7(targetPath);
37706
+ const resolvedBase = resolve6(basePath);
37707
+ const resolvedTarget = resolve6(targetPath);
37665
37708
  return resolvedTarget.startsWith(resolvedBase);
37666
37709
  }
37667
37710
  static toPosixPath(path11) {
@@ -38110,11 +38153,11 @@ init_logger();
38110
38153
 
38111
38154
  // src/domains/skills/skills-manifest.ts
38112
38155
  init_logger();
38113
- init_types2();
38114
- var import_fs_extra17 = __toESM(require_lib(), 1);
38115
38156
  import { createHash as createHash2 } from "node:crypto";
38116
38157
  import { readFile as readFile17, readdir as readdir14, writeFile as writeFile14 } from "node:fs/promises";
38117
38158
  import { join as join50, relative as relative9 } from "node:path";
38159
+ init_types2();
38160
+ var import_fs_extra17 = __toESM(require_lib(), 1);
38118
38161
 
38119
38162
  class SkillsManifestManager {
38120
38163
  static MANIFEST_FILENAME = ".skills-manifest.json";
@@ -38159,7 +38202,7 @@ class SkillsManifestManager {
38159
38202
  }
38160
38203
  static async detectStructure(skillsDir) {
38161
38204
  const entries = await readdir14(skillsDir, { withFileTypes: true });
38162
- const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
38205
+ const dirs = entries.filter((entry) => entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith("."));
38163
38206
  if (dirs.length === 0) {
38164
38207
  return "flat";
38165
38208
  }
@@ -38182,7 +38225,7 @@ class SkillsManifestManager {
38182
38225
  if (structure === "flat") {
38183
38226
  const entries = await readdir14(skillsDir, { withFileTypes: true });
38184
38227
  for (const entry of entries) {
38185
- if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
38228
+ if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
38186
38229
  const skillPath = join50(skillsDir, entry.name);
38187
38230
  const hash = await SkillsManifestManager.hashDirectory(skillPath);
38188
38231
  skills.push({
@@ -38194,7 +38237,7 @@ class SkillsManifestManager {
38194
38237
  } else {
38195
38238
  const categories = await readdir14(skillsDir, { withFileTypes: true });
38196
38239
  for (const category of categories) {
38197
- if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
38240
+ if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
38198
38241
  const categoryPath = join50(skillsDir, category.name);
38199
38242
  const skillEntries = await readdir14(categoryPath, { withFileTypes: true });
38200
38243
  for (const skillEntry of skillEntries) {
@@ -38230,7 +38273,7 @@ class SkillsManifestManager {
38230
38273
  const entries = await readdir14(dirPath, { withFileTypes: true });
38231
38274
  for (const entry of entries) {
38232
38275
  const fullPath = join50(dirPath, entry.name);
38233
- if (entry.name.startsWith(".") || entry.name === "node_modules") {
38276
+ if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
38234
38277
  continue;
38235
38278
  }
38236
38279
  if (entry.isDirectory()) {
@@ -38965,7 +39008,7 @@ async function getAllFiles(dirPath) {
38965
39008
  const entries = await readdir18(dirPath, { withFileTypes: true });
38966
39009
  for (const entry of entries) {
38967
39010
  const fullPath = join54(dirPath, entry.name);
38968
- if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
39011
+ if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
38969
39012
  continue;
38970
39013
  }
38971
39014
  if (entry.isDirectory()) {
@@ -38978,12 +39021,12 @@ async function getAllFiles(dirPath) {
38978
39021
  return files;
38979
39022
  }
38980
39023
  async function hashFile(filePath) {
38981
- return new Promise((resolve8, reject) => {
39024
+ return new Promise((resolve7, reject) => {
38982
39025
  const hash = createHash3("sha256");
38983
39026
  const stream = createReadStream2(filePath);
38984
39027
  stream.on("data", (chunk) => hash.update(chunk));
38985
39028
  stream.on("end", () => {
38986
- resolve8(hash.digest("hex"));
39029
+ resolve7(hash.digest("hex"));
38987
39030
  });
38988
39031
  stream.on("error", (error) => {
38989
39032
  stream.destroy();
@@ -39903,7 +39946,7 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
39903
39946
  }
39904
39947
  // src/commands/init/phases/selection-handler.ts
39905
39948
  import { mkdir as mkdir20 } from "node:fs/promises";
39906
- import { join as join63, resolve as resolve8 } from "node:path";
39949
+ import { join as join63, resolve as resolve7 } from "node:path";
39907
39950
 
39908
39951
  // src/domains/github/kit-access-checker.ts
39909
39952
  init_logger();
@@ -40111,8 +40154,28 @@ async function handleSelection(ctx) {
40111
40154
  }
40112
40155
  }
40113
40156
  }
40114
- const resolvedDir = resolve8(targetDir);
40157
+ const resolvedDir = resolve7(targetDir);
40115
40158
  logger.info(`Target directory: ${resolvedDir}`);
40159
+ if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
40160
+ logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
40161
+ if (!ctx.isNonInteractive) {
40162
+ const choice = await ctx.prompts.selectScope();
40163
+ if (choice === "cancel") {
40164
+ return { ...ctx, cancelled: true };
40165
+ }
40166
+ if (choice === "global") {
40167
+ logger.info("Proceeding with global installation");
40168
+ }
40169
+ if (choice === "different") {
40170
+ logger.info("Please run 'ck init' from a project directory instead.");
40171
+ return { ...ctx, cancelled: true };
40172
+ }
40173
+ } else {
40174
+ logger.error("Cannot use local installation at HOME directory.");
40175
+ logger.info("Use -g/--global flag or run from a project directory.");
40176
+ return { ...ctx, cancelled: true };
40177
+ }
40178
+ }
40116
40179
  if (!await import_fs_extra29.pathExists(resolvedDir)) {
40117
40180
  if (ctx.options.global) {
40118
40181
  await mkdir20(resolvedDir, { recursive: true });
@@ -40244,7 +40307,7 @@ async function handleSelection(ctx) {
40244
40307
  }
40245
40308
  // src/commands/init/phases/sync-handler.ts
40246
40309
  import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile17 } from "node:fs/promises";
40247
- import { dirname as dirname9, join as join64, resolve as resolve9 } from "node:path";
40310
+ import { dirname as dirname9, join as join64, resolve as resolve8 } from "node:path";
40248
40311
  init_logger();
40249
40312
  var import_fs_extra30 = __toESM(require_lib(), 1);
40250
40313
  var import_picocolors19 = __toESM(require_picocolors(), 1);
@@ -40252,7 +40315,7 @@ async function handleSync(ctx) {
40252
40315
  if (!ctx.options.sync) {
40253
40316
  return ctx;
40254
40317
  }
40255
- const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve9(ctx.options.dir || ".");
40318
+ const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve8(ctx.options.dir || ".");
40256
40319
  const claudeDir = ctx.options.global ? resolvedDir : join64(resolvedDir, ".claude");
40257
40320
  if (!await import_fs_extra30.pathExists(claudeDir)) {
40258
40321
  logger.error("Cannot sync: no .claude directory found");
@@ -40386,7 +40449,7 @@ async function acquireSyncLock(global3) {
40386
40449
  }
40387
40450
  logger.debug(`Lock stat failed: ${statError}`);
40388
40451
  }
40389
- await new Promise((resolve10) => setTimeout(resolve10, 100));
40452
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
40390
40453
  continue;
40391
40454
  }
40392
40455
  throw err;
@@ -41250,7 +41313,7 @@ init_types2();
41250
41313
  var import_picocolors20 = __toESM(require_picocolors(), 1);
41251
41314
 
41252
41315
  // src/commands/new/phases/directory-setup.ts
41253
- import { resolve as resolve10 } from "node:path";
41316
+ import { resolve as resolve9 } from "node:path";
41254
41317
  init_logger();
41255
41318
  init_types2();
41256
41319
  var import_fs_extra32 = __toESM(require_lib(), 1);
@@ -41334,8 +41397,24 @@ async function directorySetup(validOptions, prompts) {
41334
41397
  targetDir = await prompts.getDirectory(targetDir);
41335
41398
  }
41336
41399
  }
41337
- const resolvedDir = resolve10(targetDir);
41400
+ const resolvedDir = resolve9(targetDir);
41338
41401
  logger.info(`Target directory: ${resolvedDir}`);
41402
+ if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
41403
+ logger.warning("You're creating a project at HOME directory.");
41404
+ logger.warning("This will install to your GLOBAL ~/.claude/ directory.");
41405
+ if (!isNonInteractive2) {
41406
+ const choice = await prompts.selectScope();
41407
+ if (choice === "cancel" || choice === "different") {
41408
+ logger.info("Please run 'ck new' from or specify a different directory.");
41409
+ return null;
41410
+ }
41411
+ logger.info("Proceeding with global installation");
41412
+ } else {
41413
+ logger.error("Cannot create project at HOME directory in non-interactive mode.");
41414
+ logger.info("Specify a different directory with --dir flag.");
41415
+ return null;
41416
+ }
41417
+ }
41339
41418
  if (await import_fs_extra32.pathExists(resolvedDir)) {
41340
41419
  const files = await import_fs_extra32.readdir(resolvedDir);
41341
41420
  const isEmpty = files.length === 0;
@@ -41624,7 +41703,8 @@ var import_fs_extra33 = __toESM(require_lib(), 1);
41624
41703
  async function detectInstallations() {
41625
41704
  const installations = [];
41626
41705
  const setup = await getClaudeKitSetup(process.cwd());
41627
- if (setup.project.path && setup.project.metadata) {
41706
+ const isLocalSameAsGlobal = PathResolver.isLocalSameAsGlobal();
41707
+ if (setup.project.path && setup.project.metadata && !isLocalSameAsGlobal) {
41628
41708
  installations.push({
41629
41709
  type: "local",
41630
41710
  path: setup.project.path,
@@ -41883,6 +41963,12 @@ async function uninstallCommand(options) {
41883
41963
  return;
41884
41964
  }
41885
41965
  }
41966
+ const isAtHome = PathResolver.isLocalSameAsGlobal();
41967
+ if (validOptions.local && !validOptions.global && isAtHome) {
41968
+ log.warn(import_picocolors22.default.yellow("Cannot use --local at HOME directory (local path equals global path)."));
41969
+ log.info("Use -g/--global or run from a project directory.");
41970
+ return;
41971
+ }
41886
41972
  let scope;
41887
41973
  if (validOptions.all || validOptions.local && validOptions.global) {
41888
41974
  scope = "all";
@@ -41890,6 +41976,9 @@ async function uninstallCommand(options) {
41890
41976
  scope = "local";
41891
41977
  } else if (validOptions.global) {
41892
41978
  scope = "global";
41979
+ } else if (isAtHome) {
41980
+ log.info(import_picocolors22.default.cyan("Running at HOME directory - targeting global installation"));
41981
+ scope = "global";
41893
41982
  } else {
41894
41983
  const promptedScope = await promptScope(allInstallations);
41895
41984
  if (!promptedScope) {
@@ -42358,7 +42447,7 @@ var import_picocolors24 = __toESM(require_picocolors(), 1);
42358
42447
  // package.json
42359
42448
  var package_default = {
42360
42449
  name: "claudekit-cli",
42361
- version: "3.22.0",
42450
+ version: "3.22.1",
42362
42451
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
42363
42452
  type: "module",
42364
42453
  repository: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.22.0",
3
+ "version": "3.22.1",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {