claudekit-cli 3.10.2 → 3.11.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 +1615 -405
  2. package/package.json +4 -3
package/dist/index.js CHANGED
@@ -6600,7 +6600,8 @@ var init_commands = __esm(() => {
6600
6600
  global: exports_external.boolean().default(false),
6601
6601
  all: exports_external.boolean().default(false),
6602
6602
  dryRun: exports_external.boolean().default(false),
6603
- forceOverwrite: exports_external.boolean().default(false)
6603
+ forceOverwrite: exports_external.boolean().default(false),
6604
+ kit: KitType.optional()
6604
6605
  }).merge(GlobalOutputOptionsSchema);
6605
6606
  UpdateCliOptionsSchema = exports_external.object({
6606
6607
  release: exports_external.string().optional(),
@@ -6643,7 +6644,7 @@ var init_github = __esm(() => {
6643
6644
  });
6644
6645
 
6645
6646
  // src/types/metadata.ts
6646
- var TrackedFileSchema, MetadataSchema, ConfigSchema;
6647
+ var TrackedFileSchema, KitMetadataSchema, MultiKitMetadataSchema, LegacyMetadataSchema, MetadataSchema, ConfigSchema;
6647
6648
  var init_metadata = __esm(() => {
6648
6649
  init_zod();
6649
6650
  init_commands();
@@ -6654,7 +6655,22 @@ var init_metadata = __esm(() => {
6654
6655
  ownership: exports_external.enum(["ck", "user", "ck-modified"]),
6655
6656
  installedVersion: exports_external.string()
6656
6657
  });
6657
- MetadataSchema = exports_external.object({
6658
+ KitMetadataSchema = exports_external.object({
6659
+ version: exports_external.string(),
6660
+ installedAt: exports_external.string(),
6661
+ files: exports_external.array(TrackedFileSchema).optional()
6662
+ });
6663
+ MultiKitMetadataSchema = exports_external.object({
6664
+ kits: exports_external.record(KitType, KitMetadataSchema).optional(),
6665
+ scope: exports_external.enum(["local", "global"]).optional(),
6666
+ name: exports_external.string().optional(),
6667
+ version: exports_external.string().optional(),
6668
+ installedAt: exports_external.string().optional(),
6669
+ installedFiles: exports_external.array(exports_external.string()).optional(),
6670
+ userConfigFiles: exports_external.array(exports_external.string()).optional(),
6671
+ files: exports_external.array(TrackedFileSchema).optional()
6672
+ });
6673
+ LegacyMetadataSchema = exports_external.object({
6658
6674
  name: exports_external.string().optional(),
6659
6675
  version: exports_external.string().optional(),
6660
6676
  installedAt: exports_external.string().optional(),
@@ -6663,6 +6679,7 @@ var init_metadata = __esm(() => {
6663
6679
  userConfigFiles: exports_external.array(exports_external.string()).optional(),
6664
6680
  files: exports_external.array(TrackedFileSchema).optional()
6665
6681
  });
6682
+ MetadataSchema = MultiKitMetadataSchema;
6666
6683
  ConfigSchema = exports_external.object({
6667
6684
  defaults: exports_external.object({
6668
6685
  kit: KitType.optional(),
@@ -6747,8 +6764,11 @@ __export(exports_types, {
6747
6764
  PROTECTED_PATTERNS: () => PROTECTED_PATTERNS,
6748
6765
  NewCommandOptionsSchema: () => NewCommandOptionsSchema,
6749
6766
  NEVER_COPY_PATTERNS: () => NEVER_COPY_PATTERNS,
6767
+ MultiKitMetadataSchema: () => MultiKitMetadataSchema,
6750
6768
  MetadataSchema: () => MetadataSchema,
6769
+ LegacyMetadataSchema: () => LegacyMetadataSchema,
6751
6770
  KitType: () => KitType,
6771
+ KitMetadataSchema: () => KitMetadataSchema,
6752
6772
  KitConfigSchema: () => KitConfigSchema,
6753
6773
  GitHubReleaseSchema: () => GitHubReleaseSchema,
6754
6774
  GitHubReleaseAssetSchema: () => GitHubReleaseAssetSchema,
@@ -12253,9 +12273,751 @@ var require_ignore = __commonJS((exports, module) => {
12253
12273
  }
12254
12274
  });
12255
12275
 
12276
+ // node_modules/retry/lib/retry_operation.js
12277
+ var require_retry_operation = __commonJS((exports, module) => {
12278
+ function RetryOperation(timeouts, options) {
12279
+ if (typeof options === "boolean") {
12280
+ options = { forever: options };
12281
+ }
12282
+ this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));
12283
+ this._timeouts = timeouts;
12284
+ this._options = options || {};
12285
+ this._maxRetryTime = options && options.maxRetryTime || Infinity;
12286
+ this._fn = null;
12287
+ this._errors = [];
12288
+ this._attempts = 1;
12289
+ this._operationTimeout = null;
12290
+ this._operationTimeoutCb = null;
12291
+ this._timeout = null;
12292
+ this._operationStart = null;
12293
+ if (this._options.forever) {
12294
+ this._cachedTimeouts = this._timeouts.slice(0);
12295
+ }
12296
+ }
12297
+ module.exports = RetryOperation;
12298
+ RetryOperation.prototype.reset = function() {
12299
+ this._attempts = 1;
12300
+ this._timeouts = this._originalTimeouts;
12301
+ };
12302
+ RetryOperation.prototype.stop = function() {
12303
+ if (this._timeout) {
12304
+ clearTimeout(this._timeout);
12305
+ }
12306
+ this._timeouts = [];
12307
+ this._cachedTimeouts = null;
12308
+ };
12309
+ RetryOperation.prototype.retry = function(err) {
12310
+ if (this._timeout) {
12311
+ clearTimeout(this._timeout);
12312
+ }
12313
+ if (!err) {
12314
+ return false;
12315
+ }
12316
+ var currentTime = new Date().getTime();
12317
+ if (err && currentTime - this._operationStart >= this._maxRetryTime) {
12318
+ this._errors.unshift(new Error("RetryOperation timeout occurred"));
12319
+ return false;
12320
+ }
12321
+ this._errors.push(err);
12322
+ var timeout = this._timeouts.shift();
12323
+ if (timeout === undefined) {
12324
+ if (this._cachedTimeouts) {
12325
+ this._errors.splice(this._errors.length - 1, this._errors.length);
12326
+ this._timeouts = this._cachedTimeouts.slice(0);
12327
+ timeout = this._timeouts.shift();
12328
+ } else {
12329
+ return false;
12330
+ }
12331
+ }
12332
+ var self2 = this;
12333
+ var timer = setTimeout(function() {
12334
+ self2._attempts++;
12335
+ if (self2._operationTimeoutCb) {
12336
+ self2._timeout = setTimeout(function() {
12337
+ self2._operationTimeoutCb(self2._attempts);
12338
+ }, self2._operationTimeout);
12339
+ if (self2._options.unref) {
12340
+ self2._timeout.unref();
12341
+ }
12342
+ }
12343
+ self2._fn(self2._attempts);
12344
+ }, timeout);
12345
+ if (this._options.unref) {
12346
+ timer.unref();
12347
+ }
12348
+ return true;
12349
+ };
12350
+ RetryOperation.prototype.attempt = function(fn, timeoutOps) {
12351
+ this._fn = fn;
12352
+ if (timeoutOps) {
12353
+ if (timeoutOps.timeout) {
12354
+ this._operationTimeout = timeoutOps.timeout;
12355
+ }
12356
+ if (timeoutOps.cb) {
12357
+ this._operationTimeoutCb = timeoutOps.cb;
12358
+ }
12359
+ }
12360
+ var self2 = this;
12361
+ if (this._operationTimeoutCb) {
12362
+ this._timeout = setTimeout(function() {
12363
+ self2._operationTimeoutCb();
12364
+ }, self2._operationTimeout);
12365
+ }
12366
+ this._operationStart = new Date().getTime();
12367
+ this._fn(this._attempts);
12368
+ };
12369
+ RetryOperation.prototype.try = function(fn) {
12370
+ console.log("Using RetryOperation.try() is deprecated");
12371
+ this.attempt(fn);
12372
+ };
12373
+ RetryOperation.prototype.start = function(fn) {
12374
+ console.log("Using RetryOperation.start() is deprecated");
12375
+ this.attempt(fn);
12376
+ };
12377
+ RetryOperation.prototype.start = RetryOperation.prototype.try;
12378
+ RetryOperation.prototype.errors = function() {
12379
+ return this._errors;
12380
+ };
12381
+ RetryOperation.prototype.attempts = function() {
12382
+ return this._attempts;
12383
+ };
12384
+ RetryOperation.prototype.mainError = function() {
12385
+ if (this._errors.length === 0) {
12386
+ return null;
12387
+ }
12388
+ var counts = {};
12389
+ var mainError = null;
12390
+ var mainErrorCount = 0;
12391
+ for (var i = 0;i < this._errors.length; i++) {
12392
+ var error = this._errors[i];
12393
+ var message = error.message;
12394
+ var count = (counts[message] || 0) + 1;
12395
+ counts[message] = count;
12396
+ if (count >= mainErrorCount) {
12397
+ mainError = error;
12398
+ mainErrorCount = count;
12399
+ }
12400
+ }
12401
+ return mainError;
12402
+ };
12403
+ });
12404
+
12405
+ // node_modules/retry/lib/retry.js
12406
+ var require_retry = __commonJS((exports) => {
12407
+ var RetryOperation = require_retry_operation();
12408
+ exports.operation = function(options) {
12409
+ var timeouts = exports.timeouts(options);
12410
+ return new RetryOperation(timeouts, {
12411
+ forever: options && options.forever,
12412
+ unref: options && options.unref,
12413
+ maxRetryTime: options && options.maxRetryTime
12414
+ });
12415
+ };
12416
+ exports.timeouts = function(options) {
12417
+ if (options instanceof Array) {
12418
+ return [].concat(options);
12419
+ }
12420
+ var opts = {
12421
+ retries: 10,
12422
+ factor: 2,
12423
+ minTimeout: 1 * 1000,
12424
+ maxTimeout: Infinity,
12425
+ randomize: false
12426
+ };
12427
+ for (var key in options) {
12428
+ opts[key] = options[key];
12429
+ }
12430
+ if (opts.minTimeout > opts.maxTimeout) {
12431
+ throw new Error("minTimeout is greater than maxTimeout");
12432
+ }
12433
+ var timeouts = [];
12434
+ for (var i = 0;i < opts.retries; i++) {
12435
+ timeouts.push(this.createTimeout(i, opts));
12436
+ }
12437
+ if (options && options.forever && !timeouts.length) {
12438
+ timeouts.push(this.createTimeout(i, opts));
12439
+ }
12440
+ timeouts.sort(function(a3, b3) {
12441
+ return a3 - b3;
12442
+ });
12443
+ return timeouts;
12444
+ };
12445
+ exports.createTimeout = function(attempt, opts) {
12446
+ var random = opts.randomize ? Math.random() + 1 : 1;
12447
+ var timeout = Math.round(random * opts.minTimeout * Math.pow(opts.factor, attempt));
12448
+ timeout = Math.min(timeout, opts.maxTimeout);
12449
+ return timeout;
12450
+ };
12451
+ exports.wrap = function(obj, options, methods) {
12452
+ if (options instanceof Array) {
12453
+ methods = options;
12454
+ options = null;
12455
+ }
12456
+ if (!methods) {
12457
+ methods = [];
12458
+ for (var key in obj) {
12459
+ if (typeof obj[key] === "function") {
12460
+ methods.push(key);
12461
+ }
12462
+ }
12463
+ }
12464
+ for (var i = 0;i < methods.length; i++) {
12465
+ var method = methods[i];
12466
+ var original = obj[method];
12467
+ obj[method] = function retryWrapper(original2) {
12468
+ var op = exports.operation(options);
12469
+ var args = Array.prototype.slice.call(arguments, 1);
12470
+ var callback = args.pop();
12471
+ args.push(function(err) {
12472
+ if (op.retry(err)) {
12473
+ return;
12474
+ }
12475
+ if (err) {
12476
+ arguments[0] = op.mainError();
12477
+ }
12478
+ callback.apply(this, arguments);
12479
+ });
12480
+ op.attempt(function() {
12481
+ original2.apply(obj, args);
12482
+ });
12483
+ }.bind(obj, original);
12484
+ obj[method].options = options;
12485
+ }
12486
+ };
12487
+ });
12488
+
12489
+ // node_modules/signal-exit/signals.js
12490
+ var require_signals = __commonJS((exports, module) => {
12491
+ module.exports = [
12492
+ "SIGABRT",
12493
+ "SIGALRM",
12494
+ "SIGHUP",
12495
+ "SIGINT",
12496
+ "SIGTERM"
12497
+ ];
12498
+ if (process.platform !== "win32") {
12499
+ module.exports.push("SIGVTALRM", "SIGXCPU", "SIGXFSZ", "SIGUSR2", "SIGTRAP", "SIGSYS", "SIGQUIT", "SIGIOT");
12500
+ }
12501
+ if (process.platform === "linux") {
12502
+ module.exports.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT", "SIGUNUSED");
12503
+ }
12504
+ });
12505
+
12506
+ // node_modules/signal-exit/index.js
12507
+ var require_signal_exit = __commonJS((exports, module) => {
12508
+ var process10 = global.process;
12509
+ var processOk2 = function(process11) {
12510
+ return process11 && typeof process11 === "object" && typeof process11.removeListener === "function" && typeof process11.emit === "function" && typeof process11.reallyExit === "function" && typeof process11.listeners === "function" && typeof process11.kill === "function" && typeof process11.pid === "number" && typeof process11.on === "function";
12511
+ };
12512
+ if (!processOk2(process10)) {
12513
+ module.exports = function() {
12514
+ return function() {};
12515
+ };
12516
+ } else {
12517
+ assert3 = __require("assert");
12518
+ signals2 = require_signals();
12519
+ isWin = /^win/i.test(process10.platform);
12520
+ EE3 = __require("events");
12521
+ if (typeof EE3 !== "function") {
12522
+ EE3 = EE3.EventEmitter;
12523
+ }
12524
+ if (process10.__signal_exit_emitter__) {
12525
+ emitter = process10.__signal_exit_emitter__;
12526
+ } else {
12527
+ emitter = process10.__signal_exit_emitter__ = new EE3;
12528
+ emitter.count = 0;
12529
+ emitter.emitted = {};
12530
+ }
12531
+ if (!emitter.infinite) {
12532
+ emitter.setMaxListeners(Infinity);
12533
+ emitter.infinite = true;
12534
+ }
12535
+ module.exports = function(cb, opts) {
12536
+ if (!processOk2(global.process)) {
12537
+ return function() {};
12538
+ }
12539
+ assert3.equal(typeof cb, "function", "a callback must be provided for exit handler");
12540
+ if (loaded === false) {
12541
+ load2();
12542
+ }
12543
+ var ev = "exit";
12544
+ if (opts && opts.alwaysLast) {
12545
+ ev = "afterexit";
12546
+ }
12547
+ var remove = function() {
12548
+ emitter.removeListener(ev, cb);
12549
+ if (emitter.listeners("exit").length === 0 && emitter.listeners("afterexit").length === 0) {
12550
+ unload2();
12551
+ }
12552
+ };
12553
+ emitter.on(ev, cb);
12554
+ return remove;
12555
+ };
12556
+ unload2 = function unload() {
12557
+ if (!loaded || !processOk2(global.process)) {
12558
+ return;
12559
+ }
12560
+ loaded = false;
12561
+ signals2.forEach(function(sig) {
12562
+ try {
12563
+ process10.removeListener(sig, sigListeners[sig]);
12564
+ } catch (er) {}
12565
+ });
12566
+ process10.emit = originalProcessEmit;
12567
+ process10.reallyExit = originalProcessReallyExit;
12568
+ emitter.count -= 1;
12569
+ };
12570
+ module.exports.unload = unload2;
12571
+ emit = function emit(event, code2, signal) {
12572
+ if (emitter.emitted[event]) {
12573
+ return;
12574
+ }
12575
+ emitter.emitted[event] = true;
12576
+ emitter.emit(event, code2, signal);
12577
+ };
12578
+ sigListeners = {};
12579
+ signals2.forEach(function(sig) {
12580
+ sigListeners[sig] = function listener() {
12581
+ if (!processOk2(global.process)) {
12582
+ return;
12583
+ }
12584
+ var listeners = process10.listeners(sig);
12585
+ if (listeners.length === emitter.count) {
12586
+ unload2();
12587
+ emit("exit", null, sig);
12588
+ emit("afterexit", null, sig);
12589
+ if (isWin && sig === "SIGHUP") {
12590
+ sig = "SIGINT";
12591
+ }
12592
+ process10.kill(process10.pid, sig);
12593
+ }
12594
+ };
12595
+ });
12596
+ module.exports.signals = function() {
12597
+ return signals2;
12598
+ };
12599
+ loaded = false;
12600
+ load2 = function load() {
12601
+ if (loaded || !processOk2(global.process)) {
12602
+ return;
12603
+ }
12604
+ loaded = true;
12605
+ emitter.count += 1;
12606
+ signals2 = signals2.filter(function(sig) {
12607
+ try {
12608
+ process10.on(sig, sigListeners[sig]);
12609
+ return true;
12610
+ } catch (er) {
12611
+ return false;
12612
+ }
12613
+ });
12614
+ process10.emit = processEmit;
12615
+ process10.reallyExit = processReallyExit;
12616
+ };
12617
+ module.exports.load = load2;
12618
+ originalProcessReallyExit = process10.reallyExit;
12619
+ processReallyExit = function processReallyExit(code2) {
12620
+ if (!processOk2(global.process)) {
12621
+ return;
12622
+ }
12623
+ process10.exitCode = code2 || 0;
12624
+ emit("exit", process10.exitCode, null);
12625
+ emit("afterexit", process10.exitCode, null);
12626
+ originalProcessReallyExit.call(process10, process10.exitCode);
12627
+ };
12628
+ originalProcessEmit = process10.emit;
12629
+ processEmit = function processEmit(ev, arg) {
12630
+ if (ev === "exit" && processOk2(global.process)) {
12631
+ if (arg !== undefined) {
12632
+ process10.exitCode = arg;
12633
+ }
12634
+ var ret = originalProcessEmit.apply(this, arguments);
12635
+ emit("exit", process10.exitCode, null);
12636
+ emit("afterexit", process10.exitCode, null);
12637
+ return ret;
12638
+ } else {
12639
+ return originalProcessEmit.apply(this, arguments);
12640
+ }
12641
+ };
12642
+ }
12643
+ var assert3;
12644
+ var signals2;
12645
+ var isWin;
12646
+ var EE3;
12647
+ var emitter;
12648
+ var unload2;
12649
+ var emit;
12650
+ var sigListeners;
12651
+ var loaded;
12652
+ var load2;
12653
+ var originalProcessReallyExit;
12654
+ var processReallyExit;
12655
+ var originalProcessEmit;
12656
+ var processEmit;
12657
+ });
12658
+
12659
+ // node_modules/proper-lockfile/lib/mtime-precision.js
12660
+ var require_mtime_precision = __commonJS((exports, module) => {
12661
+ var cacheSymbol = Symbol();
12662
+ function probe(file, fs12, callback) {
12663
+ const cachedPrecision = fs12[cacheSymbol];
12664
+ if (cachedPrecision) {
12665
+ return fs12.stat(file, (err, stat3) => {
12666
+ if (err) {
12667
+ return callback(err);
12668
+ }
12669
+ callback(null, stat3.mtime, cachedPrecision);
12670
+ });
12671
+ }
12672
+ const mtime = new Date(Math.ceil(Date.now() / 1000) * 1000 + 5);
12673
+ fs12.utimes(file, mtime, mtime, (err) => {
12674
+ if (err) {
12675
+ return callback(err);
12676
+ }
12677
+ fs12.stat(file, (err2, stat3) => {
12678
+ if (err2) {
12679
+ return callback(err2);
12680
+ }
12681
+ const precision = stat3.mtime.getTime() % 1000 === 0 ? "s" : "ms";
12682
+ Object.defineProperty(fs12, cacheSymbol, { value: precision });
12683
+ callback(null, stat3.mtime, precision);
12684
+ });
12685
+ });
12686
+ }
12687
+ function getMtime(precision) {
12688
+ let now = Date.now();
12689
+ if (precision === "s") {
12690
+ now = Math.ceil(now / 1000) * 1000;
12691
+ }
12692
+ return new Date(now);
12693
+ }
12694
+ exports.probe = probe;
12695
+ exports.getMtime = getMtime;
12696
+ });
12697
+
12698
+ // node_modules/proper-lockfile/lib/lockfile.js
12699
+ var require_lockfile = __commonJS((exports, module) => {
12700
+ var path9 = __require("path");
12701
+ var fs12 = require_graceful_fs();
12702
+ var retry = require_retry();
12703
+ var onExit2 = require_signal_exit();
12704
+ var mtimePrecision = require_mtime_precision();
12705
+ var locks = {};
12706
+ function getLockFile(file, options) {
12707
+ return options.lockfilePath || `${file}.lock`;
12708
+ }
12709
+ function resolveCanonicalPath(file, options, callback) {
12710
+ if (!options.realpath) {
12711
+ return callback(null, path9.resolve(file));
12712
+ }
12713
+ options.fs.realpath(file, callback);
12714
+ }
12715
+ function acquireLock(file, options, callback) {
12716
+ const lockfilePath = getLockFile(file, options);
12717
+ options.fs.mkdir(lockfilePath, (err) => {
12718
+ if (!err) {
12719
+ return mtimePrecision.probe(lockfilePath, options.fs, (err2, mtime, mtimePrecision2) => {
12720
+ if (err2) {
12721
+ options.fs.rmdir(lockfilePath, () => {});
12722
+ return callback(err2);
12723
+ }
12724
+ callback(null, mtime, mtimePrecision2);
12725
+ });
12726
+ }
12727
+ if (err.code !== "EEXIST") {
12728
+ return callback(err);
12729
+ }
12730
+ if (options.stale <= 0) {
12731
+ return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file }));
12732
+ }
12733
+ options.fs.stat(lockfilePath, (err2, stat3) => {
12734
+ if (err2) {
12735
+ if (err2.code === "ENOENT") {
12736
+ return acquireLock(file, { ...options, stale: 0 }, callback);
12737
+ }
12738
+ return callback(err2);
12739
+ }
12740
+ if (!isLockStale(stat3, options)) {
12741
+ return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file }));
12742
+ }
12743
+ removeLock(file, options, (err3) => {
12744
+ if (err3) {
12745
+ return callback(err3);
12746
+ }
12747
+ acquireLock(file, { ...options, stale: 0 }, callback);
12748
+ });
12749
+ });
12750
+ });
12751
+ }
12752
+ function isLockStale(stat3, options) {
12753
+ return stat3.mtime.getTime() < Date.now() - options.stale;
12754
+ }
12755
+ function removeLock(file, options, callback) {
12756
+ options.fs.rmdir(getLockFile(file, options), (err) => {
12757
+ if (err && err.code !== "ENOENT") {
12758
+ return callback(err);
12759
+ }
12760
+ callback();
12761
+ });
12762
+ }
12763
+ function updateLock(file, options) {
12764
+ const lock2 = locks[file];
12765
+ if (lock2.updateTimeout) {
12766
+ return;
12767
+ }
12768
+ lock2.updateDelay = lock2.updateDelay || options.update;
12769
+ lock2.updateTimeout = setTimeout(() => {
12770
+ lock2.updateTimeout = null;
12771
+ options.fs.stat(lock2.lockfilePath, (err, stat3) => {
12772
+ const isOverThreshold = lock2.lastUpdate + options.stale < Date.now();
12773
+ if (err) {
12774
+ if (err.code === "ENOENT" || isOverThreshold) {
12775
+ return setLockAsCompromised(file, lock2, Object.assign(err, { code: "ECOMPROMISED" }));
12776
+ }
12777
+ lock2.updateDelay = 1000;
12778
+ return updateLock(file, options);
12779
+ }
12780
+ const isMtimeOurs = lock2.mtime.getTime() === stat3.mtime.getTime();
12781
+ if (!isMtimeOurs) {
12782
+ return setLockAsCompromised(file, lock2, Object.assign(new Error("Unable to update lock within the stale threshold"), { code: "ECOMPROMISED" }));
12783
+ }
12784
+ const mtime = mtimePrecision.getMtime(lock2.mtimePrecision);
12785
+ options.fs.utimes(lock2.lockfilePath, mtime, mtime, (err2) => {
12786
+ const isOverThreshold2 = lock2.lastUpdate + options.stale < Date.now();
12787
+ if (lock2.released) {
12788
+ return;
12789
+ }
12790
+ if (err2) {
12791
+ if (err2.code === "ENOENT" || isOverThreshold2) {
12792
+ return setLockAsCompromised(file, lock2, Object.assign(err2, { code: "ECOMPROMISED" }));
12793
+ }
12794
+ lock2.updateDelay = 1000;
12795
+ return updateLock(file, options);
12796
+ }
12797
+ lock2.mtime = mtime;
12798
+ lock2.lastUpdate = Date.now();
12799
+ lock2.updateDelay = null;
12800
+ updateLock(file, options);
12801
+ });
12802
+ });
12803
+ }, lock2.updateDelay);
12804
+ if (lock2.updateTimeout.unref) {
12805
+ lock2.updateTimeout.unref();
12806
+ }
12807
+ }
12808
+ function setLockAsCompromised(file, lock2, err) {
12809
+ lock2.released = true;
12810
+ if (lock2.updateTimeout) {
12811
+ clearTimeout(lock2.updateTimeout);
12812
+ }
12813
+ if (locks[file] === lock2) {
12814
+ delete locks[file];
12815
+ }
12816
+ lock2.options.onCompromised(err);
12817
+ }
12818
+ function lock(file, options, callback) {
12819
+ options = {
12820
+ stale: 1e4,
12821
+ update: null,
12822
+ realpath: true,
12823
+ retries: 0,
12824
+ fs: fs12,
12825
+ onCompromised: (err) => {
12826
+ throw err;
12827
+ },
12828
+ ...options
12829
+ };
12830
+ options.retries = options.retries || 0;
12831
+ options.retries = typeof options.retries === "number" ? { retries: options.retries } : options.retries;
12832
+ options.stale = Math.max(options.stale || 0, 2000);
12833
+ options.update = options.update == null ? options.stale / 2 : options.update || 0;
12834
+ options.update = Math.max(Math.min(options.update, options.stale / 2), 1000);
12835
+ resolveCanonicalPath(file, options, (err, file2) => {
12836
+ if (err) {
12837
+ return callback(err);
12838
+ }
12839
+ const operation = retry.operation(options.retries);
12840
+ operation.attempt(() => {
12841
+ acquireLock(file2, options, (err2, mtime, mtimePrecision2) => {
12842
+ if (operation.retry(err2)) {
12843
+ return;
12844
+ }
12845
+ if (err2) {
12846
+ return callback(operation.mainError());
12847
+ }
12848
+ const lock2 = locks[file2] = {
12849
+ lockfilePath: getLockFile(file2, options),
12850
+ mtime,
12851
+ mtimePrecision: mtimePrecision2,
12852
+ options,
12853
+ lastUpdate: Date.now()
12854
+ };
12855
+ updateLock(file2, options);
12856
+ callback(null, (releasedCallback) => {
12857
+ if (lock2.released) {
12858
+ return releasedCallback && releasedCallback(Object.assign(new Error("Lock is already released"), { code: "ERELEASED" }));
12859
+ }
12860
+ unlock(file2, { ...options, realpath: false }, releasedCallback);
12861
+ });
12862
+ });
12863
+ });
12864
+ });
12865
+ }
12866
+ function unlock(file, options, callback) {
12867
+ options = {
12868
+ fs: fs12,
12869
+ realpath: true,
12870
+ ...options
12871
+ };
12872
+ resolveCanonicalPath(file, options, (err, file2) => {
12873
+ if (err) {
12874
+ return callback(err);
12875
+ }
12876
+ const lock2 = locks[file2];
12877
+ if (!lock2) {
12878
+ return callback(Object.assign(new Error("Lock is not acquired/owned by you"), { code: "ENOTACQUIRED" }));
12879
+ }
12880
+ lock2.updateTimeout && clearTimeout(lock2.updateTimeout);
12881
+ lock2.released = true;
12882
+ delete locks[file2];
12883
+ removeLock(file2, options, callback);
12884
+ });
12885
+ }
12886
+ function check(file, options, callback) {
12887
+ options = {
12888
+ stale: 1e4,
12889
+ realpath: true,
12890
+ fs: fs12,
12891
+ ...options
12892
+ };
12893
+ options.stale = Math.max(options.stale || 0, 2000);
12894
+ resolveCanonicalPath(file, options, (err, file2) => {
12895
+ if (err) {
12896
+ return callback(err);
12897
+ }
12898
+ options.fs.stat(getLockFile(file2, options), (err2, stat3) => {
12899
+ if (err2) {
12900
+ return err2.code === "ENOENT" ? callback(null, false) : callback(err2);
12901
+ }
12902
+ return callback(null, !isLockStale(stat3, options));
12903
+ });
12904
+ });
12905
+ }
12906
+ function getLocks() {
12907
+ return locks;
12908
+ }
12909
+ onExit2(() => {
12910
+ for (const file in locks) {
12911
+ const options = locks[file].options;
12912
+ try {
12913
+ options.fs.rmdirSync(getLockFile(file, options));
12914
+ } catch (e2) {}
12915
+ }
12916
+ });
12917
+ exports.lock = lock;
12918
+ exports.unlock = unlock;
12919
+ exports.check = check;
12920
+ exports.getLocks = getLocks;
12921
+ });
12922
+
12923
+ // node_modules/proper-lockfile/lib/adapter.js
12924
+ var require_adapter = __commonJS((exports, module) => {
12925
+ var fs12 = require_graceful_fs();
12926
+ function createSyncFs(fs13) {
12927
+ const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
12928
+ const newFs = { ...fs13 };
12929
+ methods.forEach((method) => {
12930
+ newFs[method] = (...args) => {
12931
+ const callback = args.pop();
12932
+ let ret;
12933
+ try {
12934
+ ret = fs13[`${method}Sync`](...args);
12935
+ } catch (err) {
12936
+ return callback(err);
12937
+ }
12938
+ callback(null, ret);
12939
+ };
12940
+ });
12941
+ return newFs;
12942
+ }
12943
+ function toPromise(method) {
12944
+ return (...args) => new Promise((resolve3, reject) => {
12945
+ args.push((err, result) => {
12946
+ if (err) {
12947
+ reject(err);
12948
+ } else {
12949
+ resolve3(result);
12950
+ }
12951
+ });
12952
+ method(...args);
12953
+ });
12954
+ }
12955
+ function toSync(method) {
12956
+ return (...args) => {
12957
+ let err;
12958
+ let result;
12959
+ args.push((_err, _result) => {
12960
+ err = _err;
12961
+ result = _result;
12962
+ });
12963
+ method(...args);
12964
+ if (err) {
12965
+ throw err;
12966
+ }
12967
+ return result;
12968
+ };
12969
+ }
12970
+ function toSyncOptions(options) {
12971
+ options = { ...options };
12972
+ options.fs = createSyncFs(options.fs || fs12);
12973
+ if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
12974
+ throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
12975
+ }
12976
+ return options;
12977
+ }
12978
+ module.exports = {
12979
+ toPromise,
12980
+ toSync,
12981
+ toSyncOptions
12982
+ };
12983
+ });
12984
+
12985
+ // node_modules/proper-lockfile/index.js
12986
+ var require_proper_lockfile = __commonJS((exports, module) => {
12987
+ var lockfile = require_lockfile();
12988
+ var { toPromise, toSync, toSyncOptions } = require_adapter();
12989
+ async function lock(file, options) {
12990
+ const release = await toPromise(lockfile.lock)(file, options);
12991
+ return toPromise(release);
12992
+ }
12993
+ function lockSync(file, options) {
12994
+ const release = toSync(lockfile.lock)(file, toSyncOptions(options));
12995
+ return toSync(release);
12996
+ }
12997
+ function unlock(file, options) {
12998
+ return toPromise(lockfile.unlock)(file, options);
12999
+ }
13000
+ function unlockSync(file, options) {
13001
+ return toSync(lockfile.unlock)(file, toSyncOptions(options));
13002
+ }
13003
+ function check(file, options) {
13004
+ return toPromise(lockfile.check)(file, options);
13005
+ }
13006
+ function checkSync(file, options) {
13007
+ return toSync(lockfile.check)(file, toSyncOptions(options));
13008
+ }
13009
+ module.exports = lock;
13010
+ module.exports.lock = lock;
13011
+ module.exports.unlock = unlock;
13012
+ module.exports.lockSync = lockSync;
13013
+ module.exports.unlockSync = unlockSync;
13014
+ module.exports.check = check;
13015
+ module.exports.checkSync = checkSync;
13016
+ });
13017
+
12256
13018
  // src/services/package-installer/install-error-handler.ts
12257
13019
  import { existsSync as existsSync6, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "node:fs";
12258
- import { join as join24 } from "node:path";
13020
+ import { join as join25 } from "node:path";
12259
13021
  function parseNameReason(str) {
12260
13022
  const colonIndex = str.indexOf(":");
12261
13023
  if (colonIndex === -1) {
@@ -12264,7 +13026,7 @@ function parseNameReason(str) {
12264
13026
  return [str.slice(0, colonIndex).trim(), str.slice(colonIndex + 1).trim()];
12265
13027
  }
12266
13028
  function displayInstallErrors(skillsDir) {
12267
- const summaryPath = join24(skillsDir, ".install-error-summary.json");
13029
+ const summaryPath = join25(skillsDir, ".install-error-summary.json");
12268
13030
  if (!existsSync6(summaryPath)) {
12269
13031
  logger.error("Skills installation failed. Run with --verbose for details.");
12270
13032
  return;
@@ -12355,7 +13117,7 @@ async function checkNeedsSudoPackages() {
12355
13117
  }
12356
13118
  }
12357
13119
  function hasInstallState(skillsDir) {
12358
- const stateFilePath = join24(skillsDir, ".install-state.json");
13120
+ const stateFilePath = join25(skillsDir, ".install-state.json");
12359
13121
  return existsSync6(stateFilePath);
12360
13122
  }
12361
13123
  var WHICH_COMMAND_TIMEOUT_MS = 5000;
@@ -12374,14 +13136,14 @@ __export(exports_gemini_mcp_linker, {
12374
13136
  addGeminiToGitignore: () => addGeminiToGitignore
12375
13137
  });
12376
13138
  import { existsSync as existsSync7, lstatSync, readlinkSync } from "node:fs";
12377
- import { mkdir as mkdir9, readFile as readFile14, symlink as symlink2, writeFile as writeFile12 } from "node:fs/promises";
13139
+ import { mkdir as mkdir9, readFile as readFile15, symlink as symlink2, writeFile as writeFile13 } from "node:fs/promises";
12378
13140
  import { homedir as homedir4 } from "node:os";
12379
- import { dirname as dirname6, join as join25, resolve as resolve3 } from "node:path";
13141
+ import { dirname as dirname6, join as join26, resolve as resolve3 } from "node:path";
12380
13142
  function getGlobalMcpConfigPath() {
12381
- return join25(homedir4(), ".claude", ".mcp.json");
13143
+ return join26(homedir4(), ".claude", ".mcp.json");
12382
13144
  }
12383
13145
  function getLocalMcpConfigPath(projectDir) {
12384
- return join25(projectDir, ".mcp.json");
13146
+ return join26(projectDir, ".mcp.json");
12385
13147
  }
12386
13148
  function findMcpConfigPath(projectDir) {
12387
13149
  const localPath = getLocalMcpConfigPath(projectDir);
@@ -12399,9 +13161,9 @@ function findMcpConfigPath(projectDir) {
12399
13161
  }
12400
13162
  function getGeminiSettingsPath(projectDir, isGlobal) {
12401
13163
  if (isGlobal) {
12402
- return join25(homedir4(), ".gemini", "settings.json");
13164
+ return join26(homedir4(), ".gemini", "settings.json");
12403
13165
  }
12404
- return join25(projectDir, ".gemini", "settings.json");
13166
+ return join26(projectDir, ".gemini", "settings.json");
12405
13167
  }
12406
13168
  function checkExistingGeminiConfig(projectDir, isGlobal = false) {
12407
13169
  const geminiSettingsPath = getGeminiSettingsPath(projectDir, isGlobal);
@@ -12426,7 +13188,7 @@ function checkExistingGeminiConfig(projectDir, isGlobal = false) {
12426
13188
  }
12427
13189
  async function readJsonFile(filePath) {
12428
13190
  try {
12429
- const content = await readFile14(filePath, "utf-8");
13191
+ const content = await readFile15(filePath, "utf-8");
12430
13192
  return JSON.parse(content);
12431
13193
  } catch (error) {
12432
13194
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
@@ -12445,7 +13207,7 @@ async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
12445
13207
  if (isGlobal) {
12446
13208
  symlinkTarget = getGlobalMcpConfigPath();
12447
13209
  } else {
12448
- const localMcpPath = join25(projectDir, ".mcp.json");
13210
+ const localMcpPath = join26(projectDir, ".mcp.json");
12449
13211
  const isLocalConfig = targetPath === localMcpPath;
12450
13212
  symlinkTarget = isLocalConfig ? "../.mcp.json" : targetPath;
12451
13213
  }
@@ -12478,7 +13240,7 @@ async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
12478
13240
  }
12479
13241
  const newSettings = { mcpServers };
12480
13242
  try {
12481
- await writeFile12(geminiSettingsPath, JSON.stringify(newSettings, null, 2), "utf-8");
13243
+ await writeFile13(geminiSettingsPath, JSON.stringify(newSettings, null, 2), "utf-8");
12482
13244
  logger.debug(`Created new Gemini settings with mcpServers: ${geminiSettingsPath}`);
12483
13245
  return { success: true, method: "merge", targetPath: mcpConfigPath };
12484
13246
  } catch (error) {
@@ -12508,7 +13270,7 @@ async function mergeGeminiSettings(geminiSettingsPath, mcpConfigPath) {
12508
13270
  mcpServers
12509
13271
  };
12510
13272
  try {
12511
- await writeFile12(geminiSettingsPath, JSON.stringify(mergedSettings, null, 2), "utf-8");
13273
+ await writeFile13(geminiSettingsPath, JSON.stringify(mergedSettings, null, 2), "utf-8");
12512
13274
  logger.debug(`Merged mcpServers into: ${geminiSettingsPath}`);
12513
13275
  return { success: true, method: "merge", targetPath: mcpConfigPath };
12514
13276
  } catch (error) {
@@ -12521,12 +13283,12 @@ async function mergeGeminiSettings(geminiSettingsPath, mcpConfigPath) {
12521
13283
  }
12522
13284
  }
12523
13285
  async function addGeminiToGitignore(projectDir) {
12524
- const gitignorePath = join25(projectDir, ".gitignore");
13286
+ const gitignorePath = join26(projectDir, ".gitignore");
12525
13287
  const geminiPattern = ".gemini/";
12526
13288
  try {
12527
13289
  let content = "";
12528
13290
  if (existsSync7(gitignorePath)) {
12529
- content = await readFile14(gitignorePath, "utf-8");
13291
+ content = await readFile15(gitignorePath, "utf-8");
12530
13292
  const lines = content.split(`
12531
13293
  `).map((line) => line.trim()).filter((line) => !line.startsWith("#"));
12532
13294
  const geminiPatterns = [".gemini/", ".gemini", "/.gemini/", "/.gemini"];
@@ -12539,7 +13301,7 @@ async function addGeminiToGitignore(projectDir) {
12539
13301
  `) || content === "" ? "" : `
12540
13302
  `;
12541
13303
  const comment = "# Gemini CLI settings (contains user-specific config)";
12542
- await writeFile12(gitignorePath, `${content}${newLine}${comment}
13304
+ await writeFile13(gitignorePath, `${content}${newLine}${comment}
12543
13305
  ${geminiPattern}
12544
13306
  `, "utf-8");
12545
13307
  logger.debug(`Added ${geminiPattern} to .gitignore`);
@@ -12631,7 +13393,7 @@ __export(exports_package_installer, {
12631
13393
  getPackageVersion: () => getPackageVersion
12632
13394
  });
12633
13395
  import { exec as exec5, execFile as execFile2, spawn } from "node:child_process";
12634
- import { join as join26, resolve as resolve4 } from "node:path";
13396
+ import { join as join27, resolve as resolve4 } from "node:path";
12635
13397
  import { promisify as promisify5 } from "node:util";
12636
13398
  function executeInteractiveScript(command, args, options) {
12637
13399
  return new Promise((resolve5, reject) => {
@@ -12826,7 +13588,7 @@ async function installOpenCode() {
12826
13588
  logger.info(`Installing ${displayName}...`);
12827
13589
  const { unlink: unlink5 } = await import("node:fs/promises");
12828
13590
  const { tmpdir: tmpdir3 } = await import("node:os");
12829
- const tempScriptPath = join26(tmpdir3(), "opencode-install.sh");
13591
+ const tempScriptPath = join27(tmpdir3(), "opencode-install.sh");
12830
13592
  try {
12831
13593
  logger.info("Downloading OpenCode installation script...");
12832
13594
  await execFileAsync("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
@@ -12945,7 +13707,7 @@ async function installSkillsDependencies(skillsDir) {
12945
13707
  const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
12946
13708
  const platform9 = process.platform;
12947
13709
  const scriptName = platform9 === "win32" ? "install.ps1" : "install.sh";
12948
- const scriptPath = join26(skillsDir, scriptName);
13710
+ const scriptPath = join27(skillsDir, scriptName);
12949
13711
  try {
12950
13712
  validateScriptPath(skillsDir, scriptPath);
12951
13713
  } catch (error) {
@@ -12961,7 +13723,7 @@ async function installSkillsDependencies(skillsDir) {
12961
13723
  logger.warning(`Skills installation script not found: ${scriptPath}`);
12962
13724
  logger.info("");
12963
13725
  logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
12964
- logger.info(` See: ${join26(skillsDir, "INSTALLATION.md")}`);
13726
+ logger.info(` See: ${join27(skillsDir, "INSTALLATION.md")}`);
12965
13727
  logger.info("");
12966
13728
  logger.info("Quick start:");
12967
13729
  logger.info(" cd .claude/skills/ai-multimodal/scripts");
@@ -12977,8 +13739,8 @@ async function installSkillsDependencies(skillsDir) {
12977
13739
  logger.info(` Platform: ${platform9 === "win32" ? "Windows (PowerShell)" : "Unix (bash)"}`);
12978
13740
  if (logger.isVerbose()) {
12979
13741
  try {
12980
- const { readFile: readFile15 } = await import("node:fs/promises");
12981
- const scriptContent = await readFile15(scriptPath, "utf-8");
13742
+ const { readFile: readFile16 } = await import("node:fs/promises");
13743
+ const scriptContent = await readFile16(scriptPath, "utf-8");
12982
13744
  const previewLines = scriptContent.split(`
12983
13745
  `).slice(0, 20);
12984
13746
  logger.verbose("Script preview (first 20 lines):");
@@ -13004,7 +13766,7 @@ async function installSkillsDependencies(skillsDir) {
13004
13766
  logger.info(` ${platform9 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
13005
13767
  logger.info("");
13006
13768
  logger.info("Or see complete guide:");
13007
- logger.info(` ${join26(skillsDir, "INSTALLATION.md")}`);
13769
+ logger.info(` ${join27(skillsDir, "INSTALLATION.md")}`);
13008
13770
  return {
13009
13771
  success: false,
13010
13772
  package: displayName,
@@ -13105,7 +13867,7 @@ async function installSkillsDependencies(skillsDir) {
13105
13867
  logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
13106
13868
  logger.info("");
13107
13869
  logger.info("See complete guide:");
13108
- logger.info(` cat ${join26(skillsDir, "INSTALLATION.md")}`);
13870
+ logger.info(` cat ${join27(skillsDir, "INSTALLATION.md")}`);
13109
13871
  logger.info("");
13110
13872
  logger.info("Quick start:");
13111
13873
  logger.info(" cd .claude/skills/ai-multimodal/scripts");
@@ -14099,7 +14861,7 @@ var init_help_interceptor = __esm(() => {
14099
14861
 
14100
14862
  // src/index.ts
14101
14863
  import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
14102
- import { join as join36 } from "path";
14864
+ import { join as join37 } from "path";
14103
14865
 
14104
14866
  // node_modules/cac/dist/index.mjs
14105
14867
  import { EventEmitter } from "events";
@@ -14704,7 +15466,7 @@ var cac = (name = "") => new CAC(name);
14704
15466
  // package.json
14705
15467
  var package_default = {
14706
15468
  name: "claudekit-cli",
14707
- version: "3.10.2",
15469
+ version: "3.11.1",
14708
15470
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
14709
15471
  type: "module",
14710
15472
  repository: {
@@ -14724,7 +15486,7 @@ var package_default = {
14724
15486
  ],
14725
15487
  scripts: {
14726
15488
  dev: "bun run src/index.ts",
14727
- build: "bun build src/index.ts --outdir dist --target node --external keytar --external @octokit/rest",
15489
+ build: "bun build src/index.ts --outdir dist --target node --external @octokit/rest",
14728
15490
  compile: "bun build src/index.ts --compile --outfile ck",
14729
15491
  "compile:binary": "bun build src/index.ts --compile --outfile bin/ck",
14730
15492
  "compile:binaries": "node scripts/build-all-binaries.js",
@@ -14765,11 +15527,11 @@ var package_default = {
14765
15527
  "extract-zip": "^2.0.1",
14766
15528
  "fs-extra": "^11.2.0",
14767
15529
  ignore: "^5.3.2",
14768
- keytar: "^7.9.0",
14769
15530
  minimatch: "^10.1.1",
14770
15531
  ora: "^8.0.0",
14771
15532
  "p-limit": "^7.2.0",
14772
15533
  picocolors: "^1.1.1",
15534
+ "proper-lockfile": "^4.1.2",
14773
15535
  tar: "^7.4.3",
14774
15536
  tmp: "^0.2.3",
14775
15537
  zod: "^3.23.8"
@@ -14782,6 +15544,7 @@ var package_default = {
14782
15544
  "@types/cli-progress": "^3.11.6",
14783
15545
  "@types/fs-extra": "^11.0.4",
14784
15546
  "@types/node": "^22.10.1",
15547
+ "@types/proper-lockfile": "^4.1.4",
14785
15548
  "@types/tar": "^6.1.13",
14786
15549
  "@types/tmp": "^0.2.6",
14787
15550
  "semantic-release": "^24.2.0",
@@ -18650,7 +19413,7 @@ async function doctorCommand(options = {}) {
18650
19413
  }
18651
19414
 
18652
19415
  // src/commands/init.ts
18653
- import { join as join31, resolve as resolve6 } from "node:path";
19416
+ import { join as join32, resolve as resolve6 } from "node:path";
18654
19417
 
18655
19418
  // src/domains/config/config-manager.ts
18656
19419
  init_logger();
@@ -27647,7 +28410,7 @@ Solutions:
27647
28410
  }
27648
28411
 
27649
28412
  // src/domains/installation/file-merger.ts
27650
- import { dirname as dirname5, join as join12, relative as relative2 } from "node:path";
28413
+ import { dirname as dirname5, join as join13, relative as relative3 } from "node:path";
27651
28414
 
27652
28415
  // src/domains/config/settings-merger.ts
27653
28416
  init_logger();
@@ -27856,7 +28619,7 @@ class SettingsMerger {
27856
28619
  init_logger();
27857
28620
  init_types2();
27858
28621
  init_dist2();
27859
- var import_fs_extra3 = __toESM(require_lib(), 1);
28622
+ var import_fs_extra4 = __toESM(require_lib(), 1);
27860
28623
  var import_ignore2 = __toESM(require_ignore(), 1);
27861
28624
 
27862
28625
  // node_modules/@isaacs/balanced-match/dist/esm/index.js
@@ -29293,6 +30056,280 @@ minimatch.Minimatch = Minimatch;
29293
30056
  minimatch.escape = escape;
29294
30057
  minimatch.unescape = unescape;
29295
30058
 
30059
+ // src/domains/installation/selective-merger.ts
30060
+ import { stat as stat2 } from "node:fs/promises";
30061
+
30062
+ // src/services/file-operations/ownership-checker.ts
30063
+ import { createHash } from "node:crypto";
30064
+ import { createReadStream } from "node:fs";
30065
+ import { stat } from "node:fs/promises";
30066
+ import { relative as relative2 } from "node:path";
30067
+
30068
+ // src/domains/migration/metadata-migration.ts
30069
+ init_logger();
30070
+ var import_fs_extra3 = __toESM(require_lib(), 1);
30071
+ import { join as join12 } from "node:path";
30072
+ async function detectMetadataFormat(claudeDir) {
30073
+ const metadataPath = join12(claudeDir, "metadata.json");
30074
+ if (!await import_fs_extra3.pathExists(metadataPath)) {
30075
+ return { format: "none", metadata: null, detectedKit: null };
30076
+ }
30077
+ try {
30078
+ const content = await import_fs_extra3.readFile(metadataPath, "utf-8");
30079
+ const parsed = JSON.parse(content);
30080
+ if (parsed.kits && Object.keys(parsed.kits).length > 0) {
30081
+ const installedKits = Object.keys(parsed.kits);
30082
+ return {
30083
+ format: "multi-kit",
30084
+ metadata: parsed,
30085
+ detectedKit: installedKits[0] || null
30086
+ };
30087
+ }
30088
+ if (parsed.name || parsed.version || parsed.files) {
30089
+ let detectedKit = null;
30090
+ const nameToCheck = parsed.name || "";
30091
+ if (/\bengineer\b/i.test(nameToCheck)) {
30092
+ detectedKit = "engineer";
30093
+ } else if (/\bmarketing\b/i.test(nameToCheck)) {
30094
+ detectedKit = "marketing";
30095
+ } else {
30096
+ detectedKit = "engineer";
30097
+ }
30098
+ return { format: "legacy", metadata: parsed, detectedKit };
30099
+ }
30100
+ logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
30101
+ return { format: "none", metadata: null, detectedKit: null };
30102
+ } catch (error) {
30103
+ logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
30104
+ return { format: "none", metadata: null, detectedKit: null };
30105
+ }
30106
+ }
30107
+ async function migrateToMultiKit(claudeDir) {
30108
+ const detection = await detectMetadataFormat(claudeDir);
30109
+ if (detection.format === "multi-kit") {
30110
+ return {
30111
+ success: true,
30112
+ migrated: false,
30113
+ fromFormat: "multi-kit",
30114
+ toFormat: "multi-kit"
30115
+ };
30116
+ }
30117
+ if (detection.format === "none") {
30118
+ return {
30119
+ success: true,
30120
+ migrated: false,
30121
+ fromFormat: "none",
30122
+ toFormat: "multi-kit"
30123
+ };
30124
+ }
30125
+ const metadataPath = join12(claudeDir, "metadata.json");
30126
+ const legacy = detection.metadata;
30127
+ if (!legacy) {
30128
+ return {
30129
+ success: false,
30130
+ migrated: false,
30131
+ fromFormat: "legacy",
30132
+ toFormat: "multi-kit",
30133
+ error: "Metadata exists but could not be read"
30134
+ };
30135
+ }
30136
+ const legacyKit = detection.detectedKit || "engineer";
30137
+ try {
30138
+ const kitMetadata = {
30139
+ version: legacy.version || "unknown",
30140
+ installedAt: legacy.installedAt || new Date().toISOString(),
30141
+ files: legacy.files || []
30142
+ };
30143
+ const multiKit = {
30144
+ kits: {
30145
+ [legacyKit]: kitMetadata
30146
+ },
30147
+ scope: legacy.scope,
30148
+ name: legacy.name,
30149
+ version: legacy.version,
30150
+ installedAt: legacy.installedAt,
30151
+ installedFiles: legacy.installedFiles,
30152
+ userConfigFiles: legacy.userConfigFiles,
30153
+ files: legacy.files
30154
+ };
30155
+ await import_fs_extra3.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
30156
+ logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
30157
+ return {
30158
+ success: true,
30159
+ migrated: true,
30160
+ fromFormat: "legacy",
30161
+ toFormat: "multi-kit"
30162
+ };
30163
+ } catch (error) {
30164
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
30165
+ logger.error(`Metadata migration failed: ${errorMsg}`);
30166
+ return {
30167
+ success: false,
30168
+ migrated: false,
30169
+ fromFormat: "legacy",
30170
+ toFormat: "multi-kit",
30171
+ error: errorMsg
30172
+ };
30173
+ }
30174
+ }
30175
+ function getKitMetadata(metadata, kit) {
30176
+ if (metadata.kits?.[kit]) {
30177
+ return metadata.kits[kit];
30178
+ }
30179
+ if (!metadata.kits && metadata.version) {
30180
+ return {
30181
+ version: metadata.version,
30182
+ installedAt: metadata.installedAt || "",
30183
+ files: metadata.files
30184
+ };
30185
+ }
30186
+ return null;
30187
+ }
30188
+ function getAllTrackedFiles(metadata) {
30189
+ if (metadata.kits) {
30190
+ const allFiles = [];
30191
+ for (const kit of Object.values(metadata.kits)) {
30192
+ if (kit.files) {
30193
+ allFiles.push(...kit.files);
30194
+ }
30195
+ }
30196
+ return allFiles;
30197
+ }
30198
+ return metadata.files || [];
30199
+ }
30200
+ function getInstalledKits(metadata) {
30201
+ if (metadata.kits) {
30202
+ return Object.keys(metadata.kits);
30203
+ }
30204
+ const nameToCheck = metadata.name || "";
30205
+ if (/\bengineer\b/i.test(nameToCheck)) {
30206
+ return ["engineer"];
30207
+ }
30208
+ if (/\bmarketing\b/i.test(nameToCheck)) {
30209
+ return ["marketing"];
30210
+ }
30211
+ if (metadata.version) {
30212
+ return ["engineer"];
30213
+ }
30214
+ return [];
30215
+ }
30216
+
30217
+ // src/services/file-operations/ownership-checker.ts
30218
+ class OwnershipChecker {
30219
+ static async calculateChecksum(filePath) {
30220
+ return new Promise((resolve3, reject) => {
30221
+ const hash = createHash("sha256");
30222
+ const stream = createReadStream(filePath);
30223
+ stream.on("data", (chunk) => hash.update(chunk));
30224
+ stream.on("end", () => {
30225
+ resolve3(hash.digest("hex"));
30226
+ });
30227
+ stream.on("error", (err) => {
30228
+ stream.destroy();
30229
+ reject(new Error(`Failed to calculate checksum for "${filePath}": ${err.message}`));
30230
+ });
30231
+ });
30232
+ }
30233
+ static async checkOwnership(filePath, metadata, claudeDir) {
30234
+ try {
30235
+ await stat(filePath);
30236
+ } catch {
30237
+ return { path: filePath, ownership: "user", exists: false };
30238
+ }
30239
+ const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
30240
+ if (!metadata || allTrackedFiles.length === 0) {
30241
+ return { path: filePath, ownership: "user", exists: true };
30242
+ }
30243
+ const relativePath = relative2(claudeDir, filePath).replace(/\\/g, "/");
30244
+ const tracked = allTrackedFiles.find((f3) => f3.path === relativePath);
30245
+ if (!tracked) {
30246
+ return { path: filePath, ownership: "user", exists: true };
30247
+ }
30248
+ const actualChecksum = await OwnershipChecker.calculateChecksum(filePath);
30249
+ if (actualChecksum === tracked.checksum) {
30250
+ return {
30251
+ path: filePath,
30252
+ ownership: "ck",
30253
+ expectedChecksum: tracked.checksum,
30254
+ actualChecksum,
30255
+ exists: true
30256
+ };
30257
+ }
30258
+ return {
30259
+ path: filePath,
30260
+ ownership: "ck-modified",
30261
+ expectedChecksum: tracked.checksum,
30262
+ actualChecksum,
30263
+ exists: true
30264
+ };
30265
+ }
30266
+ static async checkBatch(filePaths, metadata, claudeDir) {
30267
+ const results = await Promise.all(filePaths.map((path9) => OwnershipChecker.checkOwnership(path9, metadata, claudeDir)));
30268
+ return new Map(results.map((r2) => [r2.path, r2]));
30269
+ }
30270
+ }
30271
+
30272
+ // src/domains/installation/selective-merger.ts
30273
+ init_logger();
30274
+
30275
+ class SelectiveMerger {
30276
+ manifest;
30277
+ manifestMap;
30278
+ constructor(manifest) {
30279
+ this.manifest = manifest;
30280
+ this.manifestMap = new Map;
30281
+ if (manifest) {
30282
+ for (const file of manifest.files) {
30283
+ this.manifestMap.set(file.path, file);
30284
+ }
30285
+ }
30286
+ }
30287
+ async shouldCopyFile(destPath, relativePath) {
30288
+ let destStat;
30289
+ try {
30290
+ destStat = await stat2(destPath);
30291
+ } catch {
30292
+ return { changed: true, reason: "new" };
30293
+ }
30294
+ const manifestEntry = this.manifestMap.get(relativePath);
30295
+ if (!manifestEntry) {
30296
+ logger.debug(`No manifest entry for ${relativePath}, will copy`);
30297
+ return { changed: true, reason: "new" };
30298
+ }
30299
+ if (destStat.size !== manifestEntry.size) {
30300
+ logger.debug(`Size differs for ${relativePath}: ${destStat.size} vs ${manifestEntry.size}`);
30301
+ return {
30302
+ changed: true,
30303
+ reason: "size-differ",
30304
+ sourceChecksum: manifestEntry.checksum
30305
+ };
30306
+ }
30307
+ const destChecksum = await OwnershipChecker.calculateChecksum(destPath);
30308
+ if (destChecksum !== manifestEntry.checksum) {
30309
+ logger.debug(`Checksum differs for ${relativePath}`);
30310
+ return {
30311
+ changed: true,
30312
+ reason: "checksum-differ",
30313
+ sourceChecksum: manifestEntry.checksum,
30314
+ destChecksum
30315
+ };
30316
+ }
30317
+ logger.debug(`Unchanged: ${relativePath}`);
30318
+ return {
30319
+ changed: false,
30320
+ reason: "unchanged",
30321
+ sourceChecksum: manifestEntry.checksum,
30322
+ destChecksum
30323
+ };
30324
+ }
30325
+ hasManifest() {
30326
+ return this.manifest !== null && this.manifestMap.size > 0;
30327
+ }
30328
+ getManifestFileCount() {
30329
+ return this.manifestMap.size;
30330
+ }
30331
+ }
30332
+
29296
30333
  // src/domains/installation/file-merger.ts
29297
30334
  class FileMerger {
29298
30335
  neverCopyChecker = import_ignore2.default().add(NEVER_COPY_PATTERNS);
@@ -29302,6 +30339,8 @@ class FileMerger {
29302
30339
  forceOverwriteSettings = false;
29303
30340
  installedFiles = new Set;
29304
30341
  installedDirectories = new Set;
30342
+ selectiveMerger = null;
30343
+ unchangedSkipped = 0;
29305
30344
  setIncludePatterns(patterns) {
29306
30345
  this.includePatterns = patterns;
29307
30346
  }
@@ -29311,6 +30350,12 @@ class FileMerger {
29311
30350
  setForceOverwriteSettings(force) {
29312
30351
  this.forceOverwriteSettings = force;
29313
30352
  }
30353
+ setManifest(manifest) {
30354
+ this.selectiveMerger = manifest ? new SelectiveMerger(manifest) : null;
30355
+ if (manifest && this.selectiveMerger?.hasManifest()) {
30356
+ logger.debug(`Selective merge enabled with ${this.selectiveMerger.getManifestFileCount()} tracked files`);
30357
+ }
30358
+ }
29314
30359
  async merge(sourceDir, destDir, skipConfirmation = false) {
29315
30360
  const conflicts = await this.detectConflicts(sourceDir, destDir);
29316
30361
  if (conflicts.length > 0 && !skipConfirmation) {
@@ -29332,10 +30377,10 @@ class FileMerger {
29332
30377
  const conflicts = [];
29333
30378
  const files = await this.getFiles(sourceDir, sourceDir);
29334
30379
  for (const file of files) {
29335
- const relativePath = relative2(sourceDir, file);
30380
+ const relativePath = relative3(sourceDir, file);
29336
30381
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
29337
- const destPath = join12(destDir, relativePath);
29338
- if (await import_fs_extra3.pathExists(destPath)) {
30382
+ const destPath = join13(destDir, relativePath);
30383
+ if (await import_fs_extra4.pathExists(destPath)) {
29339
30384
  if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
29340
30385
  logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
29341
30386
  continue;
@@ -29354,16 +30399,16 @@ class FileMerger {
29354
30399
  let copiedCount = 0;
29355
30400
  let skippedCount = 0;
29356
30401
  for (const file of files) {
29357
- const relativePath = relative2(sourceDir, file);
30402
+ const relativePath = relative3(sourceDir, file);
29358
30403
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
29359
- const destPath = join12(destDir, relativePath);
30404
+ const destPath = join13(destDir, relativePath);
29360
30405
  if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
29361
30406
  logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
29362
30407
  skippedCount++;
29363
30408
  continue;
29364
30409
  }
29365
30410
  if (this.userConfigChecker.ignores(normalizedRelativePath)) {
29366
- const fileExists = await import_fs_extra3.pathExists(destPath);
30411
+ const fileExists = await import_fs_extra4.pathExists(destPath);
29367
30412
  if (fileExists) {
29368
30413
  logger.debug(`Preserving user config: ${normalizedRelativePath}`);
29369
30414
  skippedCount++;
@@ -29377,15 +30422,28 @@ class FileMerger {
29377
30422
  copiedCount++;
29378
30423
  continue;
29379
30424
  }
29380
- await import_fs_extra3.copy(file, destPath, { overwrite: true });
30425
+ if (this.selectiveMerger?.hasManifest()) {
30426
+ const compareResult = await this.selectiveMerger.shouldCopyFile(destPath, normalizedRelativePath);
30427
+ if (!compareResult.changed) {
30428
+ logger.debug(`Skipping unchanged: ${normalizedRelativePath}`);
30429
+ this.unchangedSkipped++;
30430
+ this.trackInstalledFile(normalizedRelativePath);
30431
+ continue;
30432
+ }
30433
+ }
30434
+ await import_fs_extra4.copy(file, destPath, { overwrite: true });
29381
30435
  this.trackInstalledFile(normalizedRelativePath);
29382
30436
  copiedCount++;
29383
30437
  }
29384
- logger.success(`Copied ${copiedCount} file(s), skipped ${skippedCount} protected file(s)`);
30438
+ if (this.unchangedSkipped > 0) {
30439
+ logger.success(`Updated ${copiedCount} file(s), skipped ${this.unchangedSkipped} unchanged, skipped ${skippedCount} protected`);
30440
+ } else {
30441
+ logger.success(`Copied ${copiedCount} file(s), skipped ${skippedCount} protected file(s)`);
30442
+ }
29385
30443
  }
29386
30444
  async processSettingsJson(sourceFile, destFile) {
29387
30445
  try {
29388
- const sourceContent = await import_fs_extra3.readFile(sourceFile, "utf-8");
30446
+ const sourceContent = await import_fs_extra4.readFile(sourceFile, "utf-8");
29389
30447
  const isWindows5 = process.platform === "win32";
29390
30448
  let transformedSource = sourceContent;
29391
30449
  if (this.isGlobal) {
@@ -29401,19 +30459,19 @@ class FileMerger {
29401
30459
  logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
29402
30460
  }
29403
30461
  }
29404
- const destExists = await import_fs_extra3.pathExists(destFile);
30462
+ const destExists = await import_fs_extra4.pathExists(destFile);
29405
30463
  if (destExists && !this.forceOverwriteSettings) {
29406
30464
  await this.selectiveMergeSettings(transformedSource, destFile);
29407
30465
  } else {
29408
30466
  const formattedContent = this.formatJsonContent(transformedSource);
29409
- await import_fs_extra3.writeFile(destFile, formattedContent, "utf-8");
30467
+ await import_fs_extra4.writeFile(destFile, formattedContent, "utf-8");
29410
30468
  if (this.forceOverwriteSettings && destExists) {
29411
30469
  logger.debug("Force overwrite enabled, replaced settings.json completely");
29412
30470
  }
29413
30471
  }
29414
30472
  } catch (error) {
29415
30473
  logger.error(`Failed to process settings.json: ${error}`);
29416
- await import_fs_extra3.copy(sourceFile, destFile, { overwrite: true });
30474
+ await import_fs_extra4.copy(sourceFile, destFile, { overwrite: true });
29417
30475
  }
29418
30476
  }
29419
30477
  async selectiveMergeSettings(transformedSourceContent, destFile) {
@@ -29423,7 +30481,7 @@ class FileMerger {
29423
30481
  } catch {
29424
30482
  logger.warning("Failed to parse source settings.json, falling back to overwrite");
29425
30483
  const formattedContent = this.formatJsonContent(transformedSourceContent);
29426
- await import_fs_extra3.writeFile(destFile, formattedContent, "utf-8");
30484
+ await import_fs_extra4.writeFile(destFile, formattedContent, "utf-8");
29427
30485
  return;
29428
30486
  }
29429
30487
  const destSettings = await SettingsMerger.readSettingsFile(destFile);
@@ -29469,12 +30527,12 @@ class FileMerger {
29469
30527
  }
29470
30528
  async getFiles(dir, baseDir = dir) {
29471
30529
  const files = [];
29472
- const entries = await import_fs_extra3.readdir(dir, { encoding: "utf8" });
30530
+ const entries = await import_fs_extra4.readdir(dir, { encoding: "utf8" });
29473
30531
  for (const entry of entries) {
29474
- const fullPath = join12(dir, entry);
29475
- const relativePath = relative2(baseDir, fullPath);
30532
+ const fullPath = join13(dir, entry);
30533
+ const relativePath = relative3(baseDir, fullPath);
29476
30534
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
29477
- const stats = await import_fs_extra3.lstat(fullPath);
30535
+ const stats = await import_fs_extra4.lstat(fullPath);
29478
30536
  if (stats.isSymbolicLink()) {
29479
30537
  logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
29480
30538
  continue;
@@ -29532,11 +30590,11 @@ class FileMerger {
29532
30590
 
29533
30591
  // src/domains/installation/fresh-installer.ts
29534
30592
  init_logger();
29535
- import { join as join13 } from "node:path";
29536
- var import_fs_extra4 = __toESM(require_lib(), 1);
30593
+ import { join as join14 } from "node:path";
30594
+ var import_fs_extra5 = __toESM(require_lib(), 1);
29537
30595
  var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
29538
30596
  async function handleFreshInstallation(claudeDir, prompts) {
29539
- if (!await import_fs_extra4.pathExists(claudeDir)) {
30597
+ if (!await import_fs_extra5.pathExists(claudeDir)) {
29540
30598
  logger.info(".claude directory does not exist, proceeding with fresh installation");
29541
30599
  return true;
29542
30600
  }
@@ -29551,8 +30609,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
29551
30609
  const { rmSync } = await import("node:fs");
29552
30610
  let removedCount = 0;
29553
30611
  for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
29554
- const subdirPath = join13(claudeDir, subdir);
29555
- if (await import_fs_extra4.pathExists(subdirPath)) {
30612
+ const subdirPath = join14(claudeDir, subdir);
30613
+ if (await import_fs_extra5.pathExists(subdirPath)) {
29556
30614
  rmSync(subdirPath, { recursive: true, force: true });
29557
30615
  removedCount++;
29558
30616
  logger.debug(`Removed subdirectory: ${subdir}/`);
@@ -29567,11 +30625,11 @@ async function handleFreshInstallation(claudeDir, prompts) {
29567
30625
  }
29568
30626
 
29569
30627
  // src/domains/installation/setup-wizard.ts
29570
- import { join as join15 } from "node:path";
30628
+ import { join as join16 } from "node:path";
29571
30629
 
29572
30630
  // src/domains/config/config-generator.ts
29573
- var import_fs_extra5 = __toESM(require_lib(), 1);
29574
- import { join as join14 } from "node:path";
30631
+ var import_fs_extra6 = __toESM(require_lib(), 1);
30632
+ import { join as join15 } from "node:path";
29575
30633
  async function generateEnvFile(targetDir, values) {
29576
30634
  const lines = [
29577
30635
  "# Generated by ClaudeKit CLI setup wizard",
@@ -29583,8 +30641,8 @@ async function generateEnvFile(targetDir, values) {
29583
30641
  lines.push(`${key}=${value}`);
29584
30642
  }
29585
30643
  }
29586
- const envPath = join14(targetDir, ".env");
29587
- await import_fs_extra5.writeFile(envPath, `${lines.join(`
30644
+ const envPath = join15(targetDir, ".env");
30645
+ await import_fs_extra6.writeFile(envPath, `${lines.join(`
29588
30646
  `)}
29589
30647
  `, { mode: 384 });
29590
30648
  }
@@ -29602,7 +30660,7 @@ function validateApiKey(value, pattern) {
29602
30660
  // src/domains/installation/setup-wizard.ts
29603
30661
  init_logger();
29604
30662
  init_dist2();
29605
- var import_fs_extra6 = __toESM(require_lib(), 1);
30663
+ var import_fs_extra7 = __toESM(require_lib(), 1);
29606
30664
  var ESSENTIAL_CONFIGS = [
29607
30665
  {
29608
30666
  key: "GEMINI_API_KEY",
@@ -29631,7 +30689,7 @@ var ESSENTIAL_CONFIGS = [
29631
30689
  ];
29632
30690
  async function parseEnvFile(path9) {
29633
30691
  try {
29634
- const content = await import_fs_extra6.readFile(path9, "utf-8");
30692
+ const content = await import_fs_extra7.readFile(path9, "utf-8");
29635
30693
  const env2 = {};
29636
30694
  for (const line of content.split(`
29637
30695
  `)) {
@@ -29657,8 +30715,8 @@ async function parseEnvFile(path9) {
29657
30715
  }
29658
30716
  }
29659
30717
  async function checkGlobalConfig() {
29660
- const globalEnvPath = join15(PathResolver.getGlobalKitDir(), ".env");
29661
- if (!await import_fs_extra6.pathExists(globalEnvPath))
30718
+ const globalEnvPath = join16(PathResolver.getGlobalKitDir(), ".env");
30719
+ if (!await import_fs_extra7.pathExists(globalEnvPath))
29662
30720
  return false;
29663
30721
  const env2 = await parseEnvFile(globalEnvPath);
29664
30722
  return Object.keys(env2).length > 0;
@@ -29673,8 +30731,8 @@ async function runSetupWizard(options) {
29673
30731
  let globalEnv = {};
29674
30732
  const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
29675
30733
  if (!isGlobal) {
29676
- const globalEnvPath = join15(PathResolver.getGlobalKitDir(), ".env");
29677
- if (await import_fs_extra6.pathExists(globalEnvPath)) {
30734
+ const globalEnvPath = join16(PathResolver.getGlobalKitDir(), ".env");
30735
+ if (await import_fs_extra7.pathExists(globalEnvPath)) {
29678
30736
  globalEnv = await parseEnvFile(globalEnvPath);
29679
30737
  }
29680
30738
  }
@@ -29726,19 +30784,19 @@ async function runSetupWizard(options) {
29726
30784
  }
29727
30785
  }
29728
30786
  await generateEnvFile(targetDir, values);
29729
- f2.success(`Configuration saved to ${join15(targetDir, ".env")}`);
30787
+ f2.success(`Configuration saved to ${join16(targetDir, ".env")}`);
29730
30788
  return true;
29731
30789
  }
29732
30790
 
29733
30791
  // src/domains/migration/legacy-migration.ts
29734
- import { readdir as readdir4, stat as stat2 } from "node:fs/promises";
29735
- import { join as join18, relative as relative4 } from "node:path";
30792
+ import { readdir as readdir4, stat as stat3 } from "node:fs/promises";
30793
+ import { join as join19, relative as relative4 } from "node:path";
29736
30794
 
29737
30795
  // src/services/file-operations/manifest-writer.ts
30796
+ import { join as join17 } from "node:path";
29738
30797
  init_logger();
29739
30798
  init_types2();
29740
- var import_fs_extra7 = __toESM(require_lib(), 1);
29741
- import { join as join16 } from "node:path";
30799
+ var import_fs_extra8 = __toESM(require_lib(), 1);
29742
30800
 
29743
30801
  // node_modules/yocto-queue/index.js
29744
30802
  class Node2 {
@@ -29880,66 +30938,8 @@ function validateConcurrency(concurrency) {
29880
30938
  }
29881
30939
  }
29882
30940
 
29883
- // src/services/file-operations/ownership-checker.ts
29884
- import { createHash } from "node:crypto";
29885
- import { createReadStream } from "node:fs";
29886
- import { stat } from "node:fs/promises";
29887
- import { relative as relative3 } from "node:path";
29888
-
29889
- class OwnershipChecker {
29890
- static async calculateChecksum(filePath) {
29891
- return new Promise((resolve3, reject) => {
29892
- const hash = createHash("sha256");
29893
- const stream = createReadStream(filePath);
29894
- stream.on("data", (chunk) => hash.update(chunk));
29895
- stream.on("end", () => {
29896
- resolve3(hash.digest("hex"));
29897
- });
29898
- stream.on("error", (err) => {
29899
- stream.destroy();
29900
- reject(new Error(`Failed to calculate checksum for "${filePath}": ${err.message}`));
29901
- });
29902
- });
29903
- }
29904
- static async checkOwnership(filePath, metadata, claudeDir) {
29905
- try {
29906
- await stat(filePath);
29907
- } catch {
29908
- return { path: filePath, ownership: "user", exists: false };
29909
- }
29910
- if (!metadata || !metadata.files || metadata.files.length === 0) {
29911
- return { path: filePath, ownership: "user", exists: true };
29912
- }
29913
- const relativePath = relative3(claudeDir, filePath).replace(/\\/g, "/");
29914
- const tracked = metadata.files.find((f3) => f3.path === relativePath);
29915
- if (!tracked) {
29916
- return { path: filePath, ownership: "user", exists: true };
29917
- }
29918
- const actualChecksum = await OwnershipChecker.calculateChecksum(filePath);
29919
- if (actualChecksum === tracked.checksum) {
29920
- return {
29921
- path: filePath,
29922
- ownership: "ck",
29923
- expectedChecksum: tracked.checksum,
29924
- actualChecksum,
29925
- exists: true
29926
- };
29927
- }
29928
- return {
29929
- path: filePath,
29930
- ownership: "ck-modified",
29931
- expectedChecksum: tracked.checksum,
29932
- actualChecksum,
29933
- exists: true
29934
- };
29935
- }
29936
- static async checkBatch(filePaths, metadata, claudeDir) {
29937
- const results = await Promise.all(filePaths.map((path9) => OwnershipChecker.checkOwnership(path9, metadata, claudeDir)));
29938
- return new Map(results.map((r2) => [r2.path, r2]));
29939
- }
29940
- }
29941
-
29942
30941
  // src/services/file-operations/manifest-writer.ts
30942
+ var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
29943
30943
  class ManifestWriter {
29944
30944
  installedFiles = new Set;
29945
30945
  userConfigFiles = new Set;
@@ -29995,13 +30995,16 @@ class ManifestWriter {
29995
30995
  return false;
29996
30996
  }
29997
30997
  }));
29998
- let completed = 0;
29999
30998
  const progressInterval = Math.max(1, Math.floor(total / 20));
30000
- const results = await Promise.all(tasks.map(async (task) => {
30999
+ let reportedProgress = 0;
31000
+ const results = await Promise.all(tasks.map(async (task, index) => {
30001
31001
  const result = await task;
30002
- completed++;
31002
+ const completed = index + 1;
30003
31003
  if (completed % progressInterval === 0 || completed === total) {
30004
- onProgress?.(completed, total);
31004
+ if (completed > reportedProgress) {
31005
+ reportedProgress = completed;
31006
+ onProgress?.(completed, total);
31007
+ }
30005
31008
  }
30006
31009
  return result;
30007
31010
  }));
@@ -30015,39 +31018,68 @@ class ManifestWriter {
30015
31018
  getTrackedFiles() {
30016
31019
  return Array.from(this.trackedFiles.values()).sort((a3, b3) => a3.path.localeCompare(b3.path));
30017
31020
  }
30018
- async writeManifest(claudeDir, kitName, version, scope) {
30019
- const metadataPath = join16(claudeDir, "metadata.json");
30020
- let existingMetadata = {};
30021
- if (await import_fs_extra7.pathExists(metadataPath)) {
30022
- try {
30023
- const content = await import_fs_extra7.readFile(metadataPath, "utf-8");
30024
- existingMetadata = JSON.parse(content);
30025
- } catch (error) {
30026
- logger.debug(`Could not read existing metadata: ${error}`);
31021
+ async writeManifest(claudeDir, kitName, version, scope, kitType) {
31022
+ const metadataPath = join17(claudeDir, "metadata.json");
31023
+ const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
31024
+ await import_fs_extra8.ensureFile(metadataPath);
31025
+ let release = null;
31026
+ try {
31027
+ release = await import_proper_lockfile.lock(metadataPath, {
31028
+ retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
31029
+ stale: 60000
31030
+ });
31031
+ logger.debug(`Acquired lock on ${metadataPath}`);
31032
+ const migrationResult = await migrateToMultiKit(claudeDir);
31033
+ if (!migrationResult.success) {
31034
+ logger.warning(`Metadata migration warning: ${migrationResult.error}`);
31035
+ }
31036
+ let existingMetadata = { kits: {} };
31037
+ if (await import_fs_extra8.pathExists(metadataPath)) {
31038
+ try {
31039
+ const content = await import_fs_extra8.readFile(metadataPath, "utf-8");
31040
+ const parsed = JSON.parse(content);
31041
+ if (parsed && typeof parsed === "object" && Object.keys(parsed).length > 0) {
31042
+ existingMetadata = parsed;
31043
+ }
31044
+ } catch (error) {
31045
+ logger.debug(`Could not read existing metadata: ${error}`);
31046
+ }
31047
+ }
31048
+ const trackedFiles = this.getTrackedFiles();
31049
+ const installedAt = new Date().toISOString();
31050
+ const kitMetadata = {
31051
+ version,
31052
+ installedAt,
31053
+ files: trackedFiles.length > 0 ? trackedFiles : undefined
31054
+ };
31055
+ const metadata = {
31056
+ kits: {
31057
+ ...existingMetadata.kits || {},
31058
+ [kit]: kitMetadata
31059
+ },
31060
+ scope,
31061
+ name: kitName,
31062
+ version,
31063
+ installedAt,
31064
+ userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()]
31065
+ };
31066
+ const validated = MetadataSchema.parse(metadata);
31067
+ await import_fs_extra8.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
31068
+ logger.debug(`Wrote manifest for kit "${kit}" with ${trackedFiles.length} tracked files`);
31069
+ } finally {
31070
+ if (release) {
31071
+ await release();
31072
+ logger.debug(`Released lock on ${metadataPath}`);
30027
31073
  }
30028
31074
  }
30029
- const trackedFiles = this.getTrackedFiles();
30030
- const metadata = {
30031
- ...existingMetadata,
30032
- name: kitName,
30033
- version,
30034
- installedAt: new Date().toISOString(),
30035
- scope,
30036
- installedFiles: this.getInstalledFiles(),
30037
- userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()],
30038
- files: trackedFiles.length > 0 ? trackedFiles : undefined
30039
- };
30040
- const validated = MetadataSchema.parse(metadata);
30041
- await import_fs_extra7.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
30042
- logger.debug(`Wrote manifest with ${this.installedFiles.size} installed files, ${trackedFiles.length} tracked`);
30043
31075
  }
30044
31076
  static async readManifest(claudeDir) {
30045
- const metadataPath = join16(claudeDir, "metadata.json");
30046
- if (!await import_fs_extra7.pathExists(metadataPath)) {
31077
+ const metadataPath = join17(claudeDir, "metadata.json");
31078
+ if (!await import_fs_extra8.pathExists(metadataPath)) {
30047
31079
  return null;
30048
31080
  }
30049
31081
  try {
30050
- const content = await import_fs_extra7.readFile(metadataPath, "utf-8");
31082
+ const content = await import_fs_extra8.readFile(metadataPath, "utf-8");
30051
31083
  const parsed = JSON.parse(content);
30052
31084
  return MetadataSchema.parse(parsed);
30053
31085
  } catch (error) {
@@ -30055,13 +31087,82 @@ class ManifestWriter {
30055
31087
  return null;
30056
31088
  }
30057
31089
  }
30058
- static async getUninstallManifest(claudeDir) {
31090
+ static async readKitManifest(claudeDir, kit) {
30059
31091
  const metadata = await ManifestWriter.readManifest(claudeDir);
30060
- if (metadata?.installedFiles && metadata.installedFiles.length > 0) {
31092
+ if (!metadata)
31093
+ return null;
31094
+ return getKitMetadata(metadata, kit);
31095
+ }
31096
+ static async getUninstallManifest(claudeDir, kit) {
31097
+ const detection = await detectMetadataFormat(claudeDir);
31098
+ if (detection.format === "multi-kit" && detection.metadata?.kits) {
31099
+ const installedKits = Object.keys(detection.metadata.kits);
31100
+ if (kit) {
31101
+ const kitMeta = detection.metadata.kits[kit];
31102
+ if (!kitMeta?.files) {
31103
+ return {
31104
+ filesToRemove: [],
31105
+ filesToPreserve: USER_CONFIG_PATTERNS,
31106
+ hasManifest: true,
31107
+ isMultiKit: true,
31108
+ remainingKits: installedKits.filter((k2) => k2 !== kit)
31109
+ };
31110
+ }
31111
+ const kitFiles = kitMeta.files.map((f3) => f3.path);
31112
+ const sharedFiles = new Set;
31113
+ for (const otherKit of installedKits) {
31114
+ if (otherKit !== kit) {
31115
+ const otherMeta = detection.metadata.kits[otherKit];
31116
+ if (otherMeta?.files) {
31117
+ for (const f3 of otherMeta.files) {
31118
+ sharedFiles.add(f3.path);
31119
+ }
31120
+ }
31121
+ }
31122
+ }
31123
+ const filesToRemove = kitFiles.filter((f3) => !sharedFiles.has(f3));
31124
+ const filesToPreserve = [
31125
+ ...USER_CONFIG_PATTERNS,
31126
+ ...kitFiles.filter((f3) => sharedFiles.has(f3))
31127
+ ];
31128
+ return {
31129
+ filesToRemove,
31130
+ filesToPreserve,
31131
+ hasManifest: true,
31132
+ isMultiKit: true,
31133
+ remainingKits: installedKits.filter((k2) => k2 !== kit)
31134
+ };
31135
+ }
31136
+ const allFiles = getAllTrackedFiles(detection.metadata);
30061
31137
  return {
30062
- filesToRemove: metadata.installedFiles,
30063
- filesToPreserve: metadata.userConfigFiles || USER_CONFIG_PATTERNS,
30064
- hasManifest: true
31138
+ filesToRemove: allFiles.map((f3) => f3.path),
31139
+ filesToPreserve: USER_CONFIG_PATTERNS,
31140
+ hasManifest: true,
31141
+ isMultiKit: true,
31142
+ remainingKits: []
31143
+ };
31144
+ }
31145
+ if (detection.format === "legacy" && detection.metadata) {
31146
+ const legacyFiles2 = detection.metadata.files?.map((f3) => f3.path) || [];
31147
+ const installedFiles = detection.metadata.installedFiles || [];
31148
+ const hasFiles = legacyFiles2.length > 0 || installedFiles.length > 0;
31149
+ if (!hasFiles) {
31150
+ const legacyDirs2 = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
31151
+ const legacyFileList = ["metadata.json"];
31152
+ return {
31153
+ filesToRemove: [...legacyDirs2, ...legacyFileList],
31154
+ filesToPreserve: USER_CONFIG_PATTERNS,
31155
+ hasManifest: false,
31156
+ isMultiKit: false,
31157
+ remainingKits: []
31158
+ };
31159
+ }
31160
+ return {
31161
+ filesToRemove: legacyFiles2.length > 0 ? legacyFiles2 : installedFiles,
31162
+ filesToPreserve: detection.metadata.userConfigFiles || USER_CONFIG_PATTERNS,
31163
+ hasManifest: true,
31164
+ isMultiKit: false,
31165
+ remainingKits: []
30065
31166
  };
30066
31167
  }
30067
31168
  const legacyDirs = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
@@ -30069,20 +31170,55 @@ class ManifestWriter {
30069
31170
  return {
30070
31171
  filesToRemove: [...legacyDirs, ...legacyFiles],
30071
31172
  filesToPreserve: USER_CONFIG_PATTERNS,
30072
- hasManifest: false
31173
+ hasManifest: false,
31174
+ isMultiKit: false,
31175
+ remainingKits: []
30073
31176
  };
30074
31177
  }
31178
+ static async removeKitFromManifest(claudeDir, kit) {
31179
+ const metadataPath = join17(claudeDir, "metadata.json");
31180
+ if (!await import_fs_extra8.pathExists(metadataPath))
31181
+ return false;
31182
+ let release = null;
31183
+ try {
31184
+ release = await import_proper_lockfile.lock(metadataPath, {
31185
+ retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
31186
+ stale: 60000
31187
+ });
31188
+ logger.debug(`Acquired lock on ${metadataPath} for kit removal`);
31189
+ const metadata = await ManifestWriter.readManifest(claudeDir);
31190
+ if (!metadata?.kits?.[kit])
31191
+ return false;
31192
+ const { [kit]: _removed, ...remainingKits } = metadata.kits;
31193
+ if (Object.keys(remainingKits).length === 0) {
31194
+ logger.debug("No kits remaining, metadata.json will be cleaned up");
31195
+ return true;
31196
+ }
31197
+ const updated = {
31198
+ ...metadata,
31199
+ kits: remainingKits
31200
+ };
31201
+ await import_fs_extra8.writeFile(metadataPath, JSON.stringify(updated, null, 2), "utf-8");
31202
+ logger.debug(`Removed kit "${kit}" from metadata, ${Object.keys(remainingKits).length} kit(s) remaining`);
31203
+ return true;
31204
+ } finally {
31205
+ if (release) {
31206
+ await release();
31207
+ logger.debug(`Released lock on ${metadataPath}`);
31208
+ }
31209
+ }
31210
+ }
30075
31211
  }
30076
31212
 
30077
31213
  // src/domains/migration/legacy-migration.ts
30078
31214
  init_logger();
30079
- var import_fs_extra9 = __toESM(require_lib(), 1);
31215
+ var import_fs_extra10 = __toESM(require_lib(), 1);
30080
31216
 
30081
31217
  // src/domains/migration/release-manifest.ts
30082
31218
  init_logger();
30083
31219
  init_zod();
30084
- var import_fs_extra8 = __toESM(require_lib(), 1);
30085
- import { join as join17 } from "node:path";
31220
+ var import_fs_extra9 = __toESM(require_lib(), 1);
31221
+ import { join as join18 } from "node:path";
30086
31222
  var ReleaseManifestFileSchema = exports_external.object({
30087
31223
  path: exports_external.string(),
30088
31224
  checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
@@ -30096,9 +31232,9 @@ var ReleaseManifestSchema = exports_external.object({
30096
31232
 
30097
31233
  class ReleaseManifestLoader {
30098
31234
  static async load(extractDir) {
30099
- const manifestPath = join17(extractDir, "release-manifest.json");
31235
+ const manifestPath = join18(extractDir, "release-manifest.json");
30100
31236
  try {
30101
- const content = await import_fs_extra8.readFile(manifestPath, "utf-8");
31237
+ const content = await import_fs_extra9.readFile(manifestPath, "utf-8");
30102
31238
  const parsed = JSON.parse(content);
30103
31239
  return ReleaseManifestSchema.parse(parsed);
30104
31240
  } catch (error) {
@@ -30142,10 +31278,10 @@ class LegacyMigration {
30142
31278
  for (const entry of entries) {
30143
31279
  if (entry === "metadata.json")
30144
31280
  continue;
30145
- const fullPath = join18(dir, entry);
31281
+ const fullPath = join19(dir, entry);
30146
31282
  let stats;
30147
31283
  try {
30148
- stats = await stat2(fullPath);
31284
+ stats = await stat3(fullPath);
30149
31285
  } catch (err) {
30150
31286
  const error = err;
30151
31287
  if (error.code === "ENOENT") {
@@ -30244,7 +31380,7 @@ User-created files (sample):`);
30244
31380
  ];
30245
31381
  if (filesToChecksum.length > 0) {
30246
31382
  const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
30247
- const fullPath = join18(claudeDir, relativePath);
31383
+ const fullPath = join19(claudeDir, relativePath);
30248
31384
  const checksum = await OwnershipChecker.calculateChecksum(fullPath);
30249
31385
  return { relativePath, checksum, ownership };
30250
31386
  }));
@@ -30265,8 +31401,8 @@ User-created files (sample):`);
30265
31401
  installedAt: new Date().toISOString(),
30266
31402
  files: trackedFiles
30267
31403
  };
30268
- const metadataPath = join18(claudeDir, "metadata.json");
30269
- await import_fs_extra9.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
31404
+ const metadataPath = join19(claudeDir, "metadata.json");
31405
+ await import_fs_extra10.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
30270
31406
  logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
30271
31407
  return true;
30272
31408
  }
@@ -30274,24 +31410,24 @@ User-created files (sample):`);
30274
31410
 
30275
31411
  // src/domains/skills/skills-detector.ts
30276
31412
  init_logger();
30277
- var import_fs_extra11 = __toESM(require_lib(), 1);
31413
+ var import_fs_extra12 = __toESM(require_lib(), 1);
30278
31414
  import { readdir as readdir6 } from "node:fs/promises";
30279
- import { join as join20 } from "node:path";
31415
+ import { join as join21 } from "node:path";
30280
31416
 
30281
31417
  // src/domains/skills/skills-manifest.ts
30282
31418
  init_logger();
30283
31419
  init_types2();
30284
- var import_fs_extra10 = __toESM(require_lib(), 1);
31420
+ var import_fs_extra11 = __toESM(require_lib(), 1);
30285
31421
  import { createHash as createHash2 } from "node:crypto";
30286
- import { readFile as readFile12, readdir as readdir5, writeFile as writeFile11 } from "node:fs/promises";
30287
- import { join as join19, relative as relative5 } from "node:path";
31422
+ import { readFile as readFile13, readdir as readdir5, writeFile as writeFile12 } from "node:fs/promises";
31423
+ import { join as join20, relative as relative5 } from "node:path";
30288
31424
 
30289
31425
  class SkillsManifestManager {
30290
31426
  static MANIFEST_FILENAME = ".skills-manifest.json";
30291
31427
  static MANIFEST_VERSION = "1.0.0";
30292
31428
  static async generateManifest(skillsDir) {
30293
31429
  logger.debug(`Generating manifest for: ${skillsDir}`);
30294
- if (!await import_fs_extra10.pathExists(skillsDir)) {
31430
+ if (!await import_fs_extra11.pathExists(skillsDir)) {
30295
31431
  throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
30296
31432
  }
30297
31433
  const structure = await SkillsManifestManager.detectStructure(skillsDir);
@@ -30306,18 +31442,18 @@ class SkillsManifestManager {
30306
31442
  return manifest;
30307
31443
  }
30308
31444
  static async writeManifest(skillsDir, manifest) {
30309
- const manifestPath = join19(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
30310
- await writeFile11(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
31445
+ const manifestPath = join20(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
31446
+ await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
30311
31447
  logger.debug(`Wrote manifest to: ${manifestPath}`);
30312
31448
  }
30313
31449
  static async readManifest(skillsDir) {
30314
- const manifestPath = join19(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
30315
- if (!await import_fs_extra10.pathExists(manifestPath)) {
31450
+ const manifestPath = join20(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
31451
+ if (!await import_fs_extra11.pathExists(manifestPath)) {
30316
31452
  logger.debug(`No manifest found at: ${manifestPath}`);
30317
31453
  return null;
30318
31454
  }
30319
31455
  try {
30320
- const content = await readFile12(manifestPath, "utf-8");
31456
+ const content = await readFile13(manifestPath, "utf-8");
30321
31457
  const data = JSON.parse(content);
30322
31458
  const manifest = SkillsManifestSchema.parse(data);
30323
31459
  logger.debug(`Read manifest from: ${manifestPath}`);
@@ -30334,7 +31470,7 @@ class SkillsManifestManager {
30334
31470
  return "flat";
30335
31471
  }
30336
31472
  for (const dir of dirs.slice(0, 3)) {
30337
- const dirPath = join19(skillsDir, dir.name);
31473
+ const dirPath = join20(skillsDir, dir.name);
30338
31474
  const subEntries = await readdir5(dirPath, { withFileTypes: true });
30339
31475
  const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
30340
31476
  if (hasSubdirs) {
@@ -30353,7 +31489,7 @@ class SkillsManifestManager {
30353
31489
  const entries = await readdir5(skillsDir, { withFileTypes: true });
30354
31490
  for (const entry of entries) {
30355
31491
  if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
30356
- const skillPath = join19(skillsDir, entry.name);
31492
+ const skillPath = join20(skillsDir, entry.name);
30357
31493
  const hash = await SkillsManifestManager.hashDirectory(skillPath);
30358
31494
  skills.push({
30359
31495
  name: entry.name,
@@ -30365,11 +31501,11 @@ class SkillsManifestManager {
30365
31501
  const categories = await readdir5(skillsDir, { withFileTypes: true });
30366
31502
  for (const category of categories) {
30367
31503
  if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
30368
- const categoryPath = join19(skillsDir, category.name);
31504
+ const categoryPath = join20(skillsDir, category.name);
30369
31505
  const skillEntries = await readdir5(categoryPath, { withFileTypes: true });
30370
31506
  for (const skillEntry of skillEntries) {
30371
31507
  if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
30372
- const skillPath = join19(categoryPath, skillEntry.name);
31508
+ const skillPath = join20(categoryPath, skillEntry.name);
30373
31509
  const hash = await SkillsManifestManager.hashDirectory(skillPath);
30374
31510
  skills.push({
30375
31511
  name: skillEntry.name,
@@ -30389,7 +31525,7 @@ class SkillsManifestManager {
30389
31525
  files.sort();
30390
31526
  for (const file of files) {
30391
31527
  const relativePath = relative5(dirPath, file);
30392
- const content = await readFile12(file);
31528
+ const content = await readFile13(file);
30393
31529
  hash.update(relativePath);
30394
31530
  hash.update(content);
30395
31531
  }
@@ -30399,7 +31535,7 @@ class SkillsManifestManager {
30399
31535
  const files = [];
30400
31536
  const entries = await readdir5(dirPath, { withFileTypes: true });
30401
31537
  for (const entry of entries) {
30402
- const fullPath = join19(dirPath, entry.name);
31538
+ const fullPath = join20(dirPath, entry.name);
30403
31539
  if (entry.name.startsWith(".") || entry.name === "node_modules") {
30404
31540
  continue;
30405
31541
  }
@@ -30519,8 +31655,8 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
30519
31655
  class SkillsMigrationDetector {
30520
31656
  static async detectMigration(oldSkillsDir, currentSkillsDir) {
30521
31657
  logger.debug("Detecting skills migration need...");
30522
- const oldExists = await import_fs_extra11.pathExists(oldSkillsDir);
30523
- const currentExists = await import_fs_extra11.pathExists(currentSkillsDir);
31658
+ const oldExists = await import_fs_extra12.pathExists(oldSkillsDir);
31659
+ const currentExists = await import_fs_extra12.pathExists(currentSkillsDir);
30524
31660
  if (!oldExists && !currentExists) {
30525
31661
  logger.debug("No skills directories found, migration not needed");
30526
31662
  return {
@@ -30631,7 +31767,7 @@ class SkillsMigrationDetector {
30631
31767
  };
30632
31768
  }
30633
31769
  static async scanDirectory(skillsDir) {
30634
- if (!await import_fs_extra11.pathExists(skillsDir)) {
31770
+ if (!await import_fs_extra12.pathExists(skillsDir)) {
30635
31771
  return ["flat", []];
30636
31772
  }
30637
31773
  const entries = await readdir6(skillsDir, { withFileTypes: true });
@@ -30642,12 +31778,12 @@ class SkillsMigrationDetector {
30642
31778
  let totalSkillLikeCount = 0;
30643
31779
  const allSkills = [];
30644
31780
  for (const dir of dirs) {
30645
- const dirPath = join20(skillsDir, dir.name);
31781
+ const dirPath = join21(skillsDir, dir.name);
30646
31782
  const subEntries = await readdir6(dirPath, { withFileTypes: true });
30647
31783
  const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
30648
31784
  if (subdirs.length > 0) {
30649
31785
  for (const subdir of subdirs.slice(0, 3)) {
30650
- const subdirPath = join20(dirPath, subdir.name);
31786
+ const subdirPath = join21(dirPath, subdir.name);
30651
31787
  const subdirFiles = await readdir6(subdirPath, { withFileTypes: true });
30652
31788
  const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
30653
31789
  if (hasSkillMarker) {
@@ -30684,16 +31820,16 @@ class SkillsMigrationDetector {
30684
31820
  // src/domains/skills/skills-migrator.ts
30685
31821
  init_logger();
30686
31822
  init_types2();
30687
- var import_fs_extra14 = __toESM(require_lib(), 1);
31823
+ var import_fs_extra15 = __toESM(require_lib(), 1);
30688
31824
  import { copyFile as copyFile2, mkdir as mkdir8, readdir as readdir9, rm as rm3 } from "node:fs/promises";
30689
- import { join as join23 } from "node:path";
31825
+ import { join as join24 } from "node:path";
30690
31826
 
30691
31827
  // src/domains/skills/skills-backup-manager.ts
30692
31828
  init_logger();
30693
31829
  init_types2();
30694
- var import_fs_extra12 = __toESM(require_lib(), 1);
30695
- import { copyFile, mkdir as mkdir7, readdir as readdir7, rm as rm2, stat as stat3 } from "node:fs/promises";
30696
- import { basename as basename2, join as join21, normalize as normalize4 } from "node:path";
31830
+ var import_fs_extra13 = __toESM(require_lib(), 1);
31831
+ import { copyFile, mkdir as mkdir7, readdir as readdir7, rm as rm2, stat as stat4 } from "node:fs/promises";
31832
+ import { basename as basename2, join as join22, normalize as normalize4 } from "node:path";
30697
31833
  function validatePath(path9, paramName) {
30698
31834
  if (!path9 || typeof path9 !== "string") {
30699
31835
  throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
@@ -30713,13 +31849,13 @@ class SkillsBackupManager {
30713
31849
  if (parentDir) {
30714
31850
  validatePath(parentDir, "parentDir");
30715
31851
  }
30716
- if (!await import_fs_extra12.pathExists(skillsDir)) {
31852
+ if (!await import_fs_extra13.pathExists(skillsDir)) {
30717
31853
  throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
30718
31854
  }
30719
31855
  const timestamp = Date.now();
30720
31856
  const randomSuffix = Math.random().toString(36).substring(2, 8);
30721
31857
  const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
30722
- const backupDir = parentDir ? join21(parentDir, backupDirName) : join21(skillsDir, "..", backupDirName);
31858
+ const backupDir = parentDir ? join22(parentDir, backupDirName) : join22(skillsDir, "..", backupDirName);
30723
31859
  logger.info(`Creating backup at: ${backupDir}`);
30724
31860
  try {
30725
31861
  await mkdir7(backupDir, { recursive: true });
@@ -30736,12 +31872,12 @@ class SkillsBackupManager {
30736
31872
  static async restoreBackup(backupDir, targetDir) {
30737
31873
  validatePath(backupDir, "backupDir");
30738
31874
  validatePath(targetDir, "targetDir");
30739
- if (!await import_fs_extra12.pathExists(backupDir)) {
31875
+ if (!await import_fs_extra13.pathExists(backupDir)) {
30740
31876
  throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
30741
31877
  }
30742
31878
  logger.info(`Restoring from backup: ${backupDir}`);
30743
31879
  try {
30744
- if (await import_fs_extra12.pathExists(targetDir)) {
31880
+ if (await import_fs_extra13.pathExists(targetDir)) {
30745
31881
  await rm2(targetDir, { recursive: true, force: true });
30746
31882
  }
30747
31883
  await mkdir7(targetDir, { recursive: true });
@@ -30752,7 +31888,7 @@ class SkillsBackupManager {
30752
31888
  }
30753
31889
  }
30754
31890
  static async deleteBackup(backupDir) {
30755
- if (!await import_fs_extra12.pathExists(backupDir)) {
31891
+ if (!await import_fs_extra13.pathExists(backupDir)) {
30756
31892
  logger.warning(`Backup directory does not exist: ${backupDir}`);
30757
31893
  return;
30758
31894
  }
@@ -30765,12 +31901,12 @@ class SkillsBackupManager {
30765
31901
  }
30766
31902
  }
30767
31903
  static async listBackups(parentDir) {
30768
- if (!await import_fs_extra12.pathExists(parentDir)) {
31904
+ if (!await import_fs_extra13.pathExists(parentDir)) {
30769
31905
  return [];
30770
31906
  }
30771
31907
  try {
30772
31908
  const entries = await readdir7(parentDir, { withFileTypes: true });
30773
- const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join21(parentDir, entry.name));
31909
+ const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join22(parentDir, entry.name));
30774
31910
  backups.sort().reverse();
30775
31911
  return backups;
30776
31912
  } catch (error) {
@@ -30790,7 +31926,7 @@ class SkillsBackupManager {
30790
31926
  }
30791
31927
  }
30792
31928
  static async getBackupSize(backupDir) {
30793
- if (!await import_fs_extra12.pathExists(backupDir)) {
31929
+ if (!await import_fs_extra13.pathExists(backupDir)) {
30794
31930
  return 0;
30795
31931
  }
30796
31932
  return await SkillsBackupManager.getDirectorySize(backupDir);
@@ -30798,8 +31934,8 @@ class SkillsBackupManager {
30798
31934
  static async copyDirectory(sourceDir, destDir) {
30799
31935
  const entries = await readdir7(sourceDir, { withFileTypes: true });
30800
31936
  for (const entry of entries) {
30801
- const sourcePath = join21(sourceDir, entry.name);
30802
- const destPath = join21(destDir, entry.name);
31937
+ const sourcePath = join22(sourceDir, entry.name);
31938
+ const destPath = join22(destDir, entry.name);
30803
31939
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
30804
31940
  continue;
30805
31941
  }
@@ -30815,14 +31951,14 @@ class SkillsBackupManager {
30815
31951
  let size = 0;
30816
31952
  const entries = await readdir7(dirPath, { withFileTypes: true });
30817
31953
  for (const entry of entries) {
30818
- const fullPath = join21(dirPath, entry.name);
31954
+ const fullPath = join22(dirPath, entry.name);
30819
31955
  if (entry.isSymbolicLink()) {
30820
31956
  continue;
30821
31957
  }
30822
31958
  if (entry.isDirectory()) {
30823
31959
  size += await SkillsBackupManager.getDirectorySize(fullPath);
30824
31960
  } else if (entry.isFile()) {
30825
- const stats = await stat3(fullPath);
31961
+ const stats = await stat4(fullPath);
30826
31962
  size += stats.size;
30827
31963
  }
30828
31964
  }
@@ -30842,11 +31978,11 @@ class SkillsBackupManager {
30842
31978
  // src/domains/skills/skills-customization-scanner.ts
30843
31979
  init_logger();
30844
31980
  init_types2();
30845
- var import_fs_extra13 = __toESM(require_lib(), 1);
31981
+ var import_fs_extra14 = __toESM(require_lib(), 1);
30846
31982
  import { createHash as createHash3 } from "node:crypto";
30847
31983
  import { createReadStream as createReadStream2 } from "node:fs";
30848
- import { readFile as readFile13, readdir as readdir8 } from "node:fs/promises";
30849
- import { join as join22, normalize as normalize5, relative as relative6 } from "node:path";
31984
+ import { readFile as readFile14, readdir as readdir8 } from "node:fs/promises";
31985
+ import { join as join23, normalize as normalize5, relative as relative6 } from "node:path";
30850
31986
  function validatePath2(path9, paramName) {
30851
31987
  if (!path9 || typeof path9 !== "string") {
30852
31988
  throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
@@ -30925,7 +32061,7 @@ class SkillsCustomizationScanner {
30925
32061
  static async detectFileChanges(currentSkillPath, baselineSkillPath) {
30926
32062
  const changes = [];
30927
32063
  const currentFiles = await SkillsCustomizationScanner.getAllFiles(currentSkillPath);
30928
- const baselineFiles = await import_fs_extra13.pathExists(baselineSkillPath) ? await SkillsCustomizationScanner.getAllFiles(baselineSkillPath) : [];
32064
+ const baselineFiles = await import_fs_extra14.pathExists(baselineSkillPath) ? await SkillsCustomizationScanner.getAllFiles(baselineSkillPath) : [];
30929
32065
  const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
30930
32066
  const relPath = relative6(currentSkillPath, f3);
30931
32067
  const hash = await SkillsCustomizationScanner.hashFile(f3);
@@ -30985,7 +32121,7 @@ class SkillsCustomizationScanner {
30985
32121
  return false;
30986
32122
  }
30987
32123
  static async scanSkillsDirectory(skillsDir) {
30988
- if (!await import_fs_extra13.pathExists(skillsDir)) {
32124
+ if (!await import_fs_extra14.pathExists(skillsDir)) {
30989
32125
  return ["flat", []];
30990
32126
  }
30991
32127
  const entries = await readdir8(skillsDir, { withFileTypes: true });
@@ -30993,13 +32129,13 @@ class SkillsCustomizationScanner {
30993
32129
  if (dirs.length === 0) {
30994
32130
  return ["flat", []];
30995
32131
  }
30996
- const firstDirPath = join22(skillsDir, dirs[0].name);
32132
+ const firstDirPath = join23(skillsDir, dirs[0].name);
30997
32133
  const subEntries = await readdir8(firstDirPath, { withFileTypes: true });
30998
32134
  const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
30999
32135
  if (subdirs.length > 0) {
31000
32136
  let skillLikeCount = 0;
31001
32137
  for (const subdir of subdirs.slice(0, 3)) {
31002
- const subdirPath = join22(firstDirPath, subdir.name);
32138
+ const subdirPath = join23(firstDirPath, subdir.name);
31003
32139
  const subdirFiles = await readdir8(subdirPath, { withFileTypes: true });
31004
32140
  const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
31005
32141
  if (hasSkillMarker) {
@@ -31009,7 +32145,7 @@ class SkillsCustomizationScanner {
31009
32145
  if (skillLikeCount > 0) {
31010
32146
  const skills = [];
31011
32147
  for (const dir of dirs) {
31012
- const categoryPath = join22(skillsDir, dir.name);
32148
+ const categoryPath = join23(skillsDir, dir.name);
31013
32149
  const skillDirs = await readdir8(categoryPath, { withFileTypes: true });
31014
32150
  skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
31015
32151
  }
@@ -31019,8 +32155,8 @@ class SkillsCustomizationScanner {
31019
32155
  return ["flat", dirs.map((dir) => dir.name)];
31020
32156
  }
31021
32157
  static async findSkillPath(skillsDir, skillName) {
31022
- const flatPath = join22(skillsDir, skillName);
31023
- if (await import_fs_extra13.pathExists(flatPath)) {
32158
+ const flatPath = join23(skillsDir, skillName);
32159
+ if (await import_fs_extra14.pathExists(flatPath)) {
31024
32160
  return { path: flatPath, category: undefined };
31025
32161
  }
31026
32162
  const entries = await readdir8(skillsDir, { withFileTypes: true });
@@ -31028,9 +32164,9 @@ class SkillsCustomizationScanner {
31028
32164
  if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
31029
32165
  continue;
31030
32166
  }
31031
- const categoryPath = join22(skillsDir, entry.name);
31032
- const skillPath = join22(categoryPath, skillName);
31033
- if (await import_fs_extra13.pathExists(skillPath)) {
32167
+ const categoryPath = join23(skillsDir, entry.name);
32168
+ const skillPath = join23(categoryPath, skillName);
32169
+ if (await import_fs_extra14.pathExists(skillPath)) {
31034
32170
  return { path: skillPath, category: entry.name };
31035
32171
  }
31036
32172
  }
@@ -31040,7 +32176,7 @@ class SkillsCustomizationScanner {
31040
32176
  const files = [];
31041
32177
  const entries = await readdir8(dirPath, { withFileTypes: true });
31042
32178
  for (const entry of entries) {
31043
- const fullPath = join22(dirPath, entry.name);
32179
+ const fullPath = join23(dirPath, entry.name);
31044
32180
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
31045
32181
  continue;
31046
32182
  }
@@ -31073,7 +32209,7 @@ class SkillsCustomizationScanner {
31073
32209
  files.sort();
31074
32210
  for (const file of files) {
31075
32211
  const relativePath = relative6(dirPath, file);
31076
- const content = await readFile13(file);
32212
+ const content = await readFile14(file);
31077
32213
  hash.update(relativePath);
31078
32214
  hash.update(content);
31079
32215
  }
@@ -31283,7 +32419,7 @@ class SkillsMigrator {
31283
32419
  }
31284
32420
  }
31285
32421
  if (options.backup && !options.dryRun) {
31286
- const claudeDir = join23(currentSkillsDir, "..");
32422
+ const claudeDir = join24(currentSkillsDir, "..");
31287
32423
  result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
31288
32424
  logger.success(`Backup created at: ${result.backupPath}`);
31289
32425
  }
@@ -31335,14 +32471,14 @@ class SkillsMigrator {
31335
32471
  const migrated = [];
31336
32472
  const preserved = [];
31337
32473
  const errors2 = [];
31338
- const tempDir = join23(currentSkillsDir, "..", ".skills-migration-temp");
32474
+ const tempDir = join24(currentSkillsDir, "..", ".skills-migration-temp");
31339
32475
  await mkdir8(tempDir, { recursive: true });
31340
32476
  try {
31341
32477
  for (const mapping of mappings) {
31342
32478
  try {
31343
32479
  const skillName = mapping.skillName;
31344
32480
  const currentSkillPath = mapping.oldPath;
31345
- if (!await import_fs_extra14.pathExists(currentSkillPath)) {
32481
+ if (!await import_fs_extra15.pathExists(currentSkillPath)) {
31346
32482
  logger.warning(`Skill not found, skipping: ${skillName}`);
31347
32483
  continue;
31348
32484
  }
@@ -31356,9 +32492,9 @@ class SkillsMigrator {
31356
32492
  }
31357
32493
  }
31358
32494
  const category = mapping.category;
31359
- const targetPath = category ? join23(tempDir, category, skillName) : join23(tempDir, skillName);
32495
+ const targetPath = category ? join24(tempDir, category, skillName) : join24(tempDir, skillName);
31360
32496
  if (category) {
31361
- await mkdir8(join23(tempDir, category), { recursive: true });
32497
+ await mkdir8(join24(tempDir, category), { recursive: true });
31362
32498
  }
31363
32499
  await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
31364
32500
  migrated.push(skillName);
@@ -31392,8 +32528,8 @@ class SkillsMigrator {
31392
32528
  await mkdir8(destDir, { recursive: true });
31393
32529
  const entries = await readdir9(sourceDir, { withFileTypes: true });
31394
32530
  for (const entry of entries) {
31395
- const sourcePath = join23(sourceDir, entry.name);
31396
- const destPath = join23(destDir, entry.name);
32531
+ const sourcePath = join24(sourceDir, entry.name);
32532
+ const destPath = join24(destDir, entry.name);
31397
32533
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
31398
32534
  continue;
31399
32535
  }
@@ -31981,31 +33117,31 @@ class PromptsManager {
31981
33117
 
31982
33118
  // src/services/file-operations/file-scanner.ts
31983
33119
  init_logger();
31984
- import { join as join27, relative as relative7, resolve as resolve5 } from "node:path";
31985
- var import_fs_extra15 = __toESM(require_lib(), 1);
33120
+ import { join as join28, relative as relative7, resolve as resolve5 } from "node:path";
33121
+ var import_fs_extra16 = __toESM(require_lib(), 1);
31986
33122
 
31987
33123
  class FileScanner {
31988
33124
  static async getFiles(dirPath, relativeTo) {
31989
33125
  const basePath = relativeTo || dirPath;
31990
33126
  const files = [];
31991
- if (!await import_fs_extra15.pathExists(dirPath)) {
33127
+ if (!await import_fs_extra16.pathExists(dirPath)) {
31992
33128
  return files;
31993
33129
  }
31994
33130
  try {
31995
- const entries = await import_fs_extra15.readdir(dirPath, { encoding: "utf8" });
33131
+ const entries = await import_fs_extra16.readdir(dirPath, { encoding: "utf8" });
31996
33132
  for (const entry of entries) {
31997
33133
  if (SKIP_DIRS_ALL.includes(entry)) {
31998
33134
  logger.debug(`Skipping directory: ${entry}`);
31999
33135
  continue;
32000
33136
  }
32001
- const fullPath = join27(dirPath, entry);
33137
+ const fullPath = join28(dirPath, entry);
32002
33138
  if (!FileScanner.isSafePath(basePath, fullPath)) {
32003
33139
  logger.warning(`Skipping potentially unsafe path: ${entry}`);
32004
33140
  continue;
32005
33141
  }
32006
33142
  let stats;
32007
33143
  try {
32008
- stats = await import_fs_extra15.lstat(fullPath);
33144
+ stats = await import_fs_extra16.lstat(fullPath);
32009
33145
  } catch (error) {
32010
33146
  if (error instanceof Error && "code" in error && (error.code === "EACCES" || error.code === "EPERM")) {
32011
33147
  logger.warning(`Skipping inaccessible path: ${entry}`);
@@ -32033,8 +33169,8 @@ class FileScanner {
32033
33169
  return files;
32034
33170
  }
32035
33171
  static async findCustomFiles(destDir, sourceDir, subPath) {
32036
- const destSubDir = join27(destDir, subPath);
32037
- const sourceSubDir = join27(sourceDir, subPath);
33172
+ const destSubDir = join28(destDir, subPath);
33173
+ const sourceSubDir = join28(sourceDir, subPath);
32038
33174
  logger.debug(`findCustomFiles - destDir: ${destDir}`);
32039
33175
  logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
32040
33176
  logger.debug(`findCustomFiles - subPath: "${subPath}"`);
@@ -32044,7 +33180,7 @@ class FileScanner {
32044
33180
  const sourceFiles = await FileScanner.getFiles(sourceSubDir, sourceDir);
32045
33181
  logger.debug(`findCustomFiles - destFiles count: ${destFiles.length}`);
32046
33182
  logger.debug(`findCustomFiles - sourceFiles count: ${sourceFiles.length}`);
32047
- const sourceExists = await import_fs_extra15.pathExists(sourceSubDir);
33183
+ const sourceExists = await import_fs_extra16.pathExists(sourceSubDir);
32048
33184
  if (sourceExists && sourceFiles.length === 0 && destFiles.length > 100) {
32049
33185
  logger.warning(`Source directory exists but is empty while destination has ${destFiles.length} files. This may indicate an extraction issue. Skipping custom file detection.`);
32050
33186
  return [];
@@ -32072,10 +33208,10 @@ class FileScanner {
32072
33208
  }
32073
33209
 
32074
33210
  // src/services/transformers/commands-prefix.ts
32075
- import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as stat4 } from "node:fs/promises";
32076
- import { join as join28 } from "node:path";
33211
+ import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as stat5 } from "node:fs/promises";
33212
+ import { join as join29 } from "node:path";
32077
33213
  init_logger();
32078
- var import_fs_extra16 = __toESM(require_lib(), 1);
33214
+ var import_fs_extra17 = __toESM(require_lib(), 1);
32079
33215
  function stripWindowsDrivePrefix(path9) {
32080
33216
  if (path9.length >= 2 && /[a-zA-Z]/.test(path9[0]) && path9[1] === ":") {
32081
33217
  return path9.slice(2);
@@ -32114,14 +33250,14 @@ function validatePath4(path9, paramName) {
32114
33250
  class CommandsPrefix {
32115
33251
  static async applyPrefix(extractDir) {
32116
33252
  validatePath4(extractDir, "extractDir");
32117
- const commandsDir = join28(extractDir, ".claude", "commands");
32118
- if (!await import_fs_extra16.pathExists(commandsDir)) {
33253
+ const commandsDir = join29(extractDir, ".claude", "commands");
33254
+ if (!await import_fs_extra17.pathExists(commandsDir)) {
32119
33255
  logger.verbose("No commands directory found, skipping prefix application");
32120
33256
  return;
32121
33257
  }
32122
33258
  logger.info("Applying /ck: prefix to slash commands...");
32123
- const backupDir = join28(extractDir, ".commands-backup");
32124
- const tempDir = join28(extractDir, ".commands-prefix-temp");
33259
+ const backupDir = join29(extractDir, ".commands-backup");
33260
+ const tempDir = join29(extractDir, ".commands-prefix-temp");
32125
33261
  try {
32126
33262
  const entries = await readdir11(commandsDir);
32127
33263
  if (entries.length === 0) {
@@ -32129,28 +33265,28 @@ class CommandsPrefix {
32129
33265
  return;
32130
33266
  }
32131
33267
  if (entries.length === 1 && entries[0] === "ck") {
32132
- const ckDir2 = join28(commandsDir, "ck");
32133
- const ckStat = await stat4(ckDir2);
33268
+ const ckDir2 = join29(commandsDir, "ck");
33269
+ const ckStat = await stat5(ckDir2);
32134
33270
  if (ckStat.isDirectory()) {
32135
33271
  logger.verbose("Commands already have /ck: prefix, skipping");
32136
33272
  return;
32137
33273
  }
32138
33274
  }
32139
- await import_fs_extra16.copy(commandsDir, backupDir);
33275
+ await import_fs_extra17.copy(commandsDir, backupDir);
32140
33276
  logger.verbose("Created backup of commands directory");
32141
33277
  await mkdir10(tempDir, { recursive: true });
32142
- const ckDir = join28(tempDir, "ck");
33278
+ const ckDir = join29(tempDir, "ck");
32143
33279
  await mkdir10(ckDir, { recursive: true });
32144
33280
  let processedCount = 0;
32145
33281
  for (const entry of entries) {
32146
- const sourcePath = join28(commandsDir, entry);
33282
+ const sourcePath = join29(commandsDir, entry);
32147
33283
  const stats = await lstat3(sourcePath);
32148
33284
  if (stats.isSymbolicLink()) {
32149
33285
  logger.warning(`Skipping symlink for security: ${entry}`);
32150
33286
  continue;
32151
33287
  }
32152
- const destPath = join28(ckDir, entry);
32153
- await import_fs_extra16.copy(sourcePath, destPath, {
33288
+ const destPath = join29(ckDir, entry);
33289
+ await import_fs_extra17.copy(sourcePath, destPath, {
32154
33290
  overwrite: false,
32155
33291
  errorOnExist: true
32156
33292
  });
@@ -32159,35 +33295,35 @@ class CommandsPrefix {
32159
33295
  }
32160
33296
  if (processedCount === 0) {
32161
33297
  logger.warning("No files to move (all were symlinks or invalid)");
32162
- await import_fs_extra16.remove(backupDir);
32163
- await import_fs_extra16.remove(tempDir);
33298
+ await import_fs_extra17.remove(backupDir);
33299
+ await import_fs_extra17.remove(tempDir);
32164
33300
  return;
32165
33301
  }
32166
- await import_fs_extra16.remove(commandsDir);
32167
- await import_fs_extra16.move(tempDir, commandsDir);
32168
- await import_fs_extra16.remove(backupDir);
33302
+ await import_fs_extra17.remove(commandsDir);
33303
+ await import_fs_extra17.move(tempDir, commandsDir);
33304
+ await import_fs_extra17.remove(backupDir);
32169
33305
  logger.success("Successfully applied /ck: prefix to all commands");
32170
33306
  } catch (error) {
32171
- if (await import_fs_extra16.pathExists(backupDir)) {
33307
+ if (await import_fs_extra17.pathExists(backupDir)) {
32172
33308
  try {
32173
- await import_fs_extra16.remove(commandsDir).catch(() => {});
32174
- await import_fs_extra16.move(backupDir, commandsDir);
33309
+ await import_fs_extra17.remove(commandsDir).catch(() => {});
33310
+ await import_fs_extra17.move(backupDir, commandsDir);
32175
33311
  logger.info("Restored original commands directory from backup");
32176
33312
  } catch (rollbackError) {
32177
33313
  logger.error(`Rollback failed: ${rollbackError}`);
32178
33314
  }
32179
33315
  }
32180
- if (await import_fs_extra16.pathExists(tempDir)) {
32181
- await import_fs_extra16.remove(tempDir).catch(() => {});
33316
+ if (await import_fs_extra17.pathExists(tempDir)) {
33317
+ await import_fs_extra17.remove(tempDir).catch(() => {});
32182
33318
  }
32183
33319
  logger.error("Failed to apply /ck: prefix to commands");
32184
33320
  throw error;
32185
33321
  } finally {
32186
- if (await import_fs_extra16.pathExists(backupDir)) {
32187
- await import_fs_extra16.remove(backupDir).catch(() => {});
33322
+ if (await import_fs_extra17.pathExists(backupDir)) {
33323
+ await import_fs_extra17.remove(backupDir).catch(() => {});
32188
33324
  }
32189
- if (await import_fs_extra16.pathExists(tempDir)) {
32190
- await import_fs_extra16.remove(tempDir).catch(() => {});
33325
+ if (await import_fs_extra17.pathExists(tempDir)) {
33326
+ await import_fs_extra17.remove(tempDir).catch(() => {});
32191
33327
  }
32192
33328
  }
32193
33329
  }
@@ -32197,15 +33333,15 @@ class CommandsPrefix {
32197
33333
  static async cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
32198
33334
  const { dryRun = false, forceOverwrite = false } = options;
32199
33335
  validatePath4(targetDir, "targetDir");
32200
- const claudeDir = isGlobal ? targetDir : join28(targetDir, ".claude");
32201
- const commandsDir = join28(claudeDir, "commands");
33336
+ const claudeDir = isGlobal ? targetDir : join29(targetDir, ".claude");
33337
+ const commandsDir = join29(claudeDir, "commands");
32202
33338
  const result = {
32203
33339
  results: [],
32204
33340
  deletedCount: 0,
32205
33341
  preservedCount: 0,
32206
33342
  wasDryRun: dryRun
32207
33343
  };
32208
- if (!await import_fs_extra16.pathExists(commandsDir)) {
33344
+ if (!await import_fs_extra17.pathExists(commandsDir)) {
32209
33345
  logger.verbose(`Commands directory does not exist: ${commandsDir}`);
32210
33346
  return result;
32211
33347
  }
@@ -32215,7 +33351,8 @@ class CommandsPrefix {
32215
33351
  logger.info("Checking ownership before cleanup...");
32216
33352
  }
32217
33353
  const metadata = await ManifestWriter.readManifest(claudeDir);
32218
- if (!metadata || !metadata.files || metadata.files.length === 0) {
33354
+ const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
33355
+ if (!metadata || allTrackedFiles.length === 0) {
32219
33356
  logger.verbose("No ownership metadata found - skipping cleanup (legacy/fresh install)");
32220
33357
  logger.verbose("All existing files will be preserved as user-owned");
32221
33358
  return result;
@@ -32226,7 +33363,7 @@ class CommandsPrefix {
32226
33363
  return result;
32227
33364
  }
32228
33365
  for (const entry of entries) {
32229
- const entryPath = join28(commandsDir, entry);
33366
+ const entryPath = join29(commandsDir, entry);
32230
33367
  const stats = await lstat3(entryPath);
32231
33368
  if (stats.isSymbolicLink()) {
32232
33369
  logger.warning(`Skipping symlink: ${entry}`);
@@ -32252,7 +33389,7 @@ class CommandsPrefix {
32252
33389
  action: "delete"
32253
33390
  });
32254
33391
  if (!dryRun) {
32255
- await import_fs_extra16.remove(file);
33392
+ await import_fs_extra17.remove(file);
32256
33393
  logger.verbose(`Deleted CK file: ${relativePath}`);
32257
33394
  }
32258
33395
  result.deletedCount++;
@@ -32265,7 +33402,7 @@ class CommandsPrefix {
32265
33402
  reason: "force overwrite"
32266
33403
  });
32267
33404
  if (!dryRun) {
32268
- await import_fs_extra16.remove(file);
33405
+ await import_fs_extra17.remove(file);
32269
33406
  logger.verbose(`Force-deleted modified file: ${relativePath}`);
32270
33407
  }
32271
33408
  result.deletedCount++;
@@ -32289,7 +33426,7 @@ class CommandsPrefix {
32289
33426
  reason: "force overwrite"
32290
33427
  });
32291
33428
  if (!dryRun) {
32292
- await import_fs_extra16.remove(file);
33429
+ await import_fs_extra17.remove(file);
32293
33430
  logger.verbose(`Force-deleted user file: ${relativePath}`);
32294
33431
  }
32295
33432
  result.deletedCount++;
@@ -32307,7 +33444,7 @@ class CommandsPrefix {
32307
33444
  }
32308
33445
  }
32309
33446
  if (canDeleteDir && !dryRun) {
32310
- await import_fs_extra16.remove(entryPath);
33447
+ await import_fs_extra17.remove(entryPath);
32311
33448
  logger.verbose(`Removed directory: ${entry}`);
32312
33449
  }
32313
33450
  } else {
@@ -32320,7 +33457,7 @@ class CommandsPrefix {
32320
33457
  action: "delete"
32321
33458
  });
32322
33459
  if (!dryRun) {
32323
- await import_fs_extra16.remove(entryPath);
33460
+ await import_fs_extra17.remove(entryPath);
32324
33461
  logger.verbose(`Deleted CK file: ${entry}`);
32325
33462
  }
32326
33463
  result.deletedCount++;
@@ -32333,7 +33470,7 @@ class CommandsPrefix {
32333
33470
  reason: "force overwrite"
32334
33471
  });
32335
33472
  if (!dryRun) {
32336
- await import_fs_extra16.remove(entryPath);
33473
+ await import_fs_extra17.remove(entryPath);
32337
33474
  logger.verbose(`Force-deleted modified file: ${entry}`);
32338
33475
  }
32339
33476
  result.deletedCount++;
@@ -32356,7 +33493,7 @@ class CommandsPrefix {
32356
33493
  reason: "force overwrite"
32357
33494
  });
32358
33495
  if (!dryRun) {
32359
- await import_fs_extra16.remove(entryPath);
33496
+ await import_fs_extra17.remove(entryPath);
32360
33497
  logger.verbose(`Force-deleted user file: ${entry}`);
32361
33498
  }
32362
33499
  result.deletedCount++;
@@ -32392,7 +33529,7 @@ class CommandsPrefix {
32392
33529
  const files = [];
32393
33530
  const entries = await readdir11(dir);
32394
33531
  for (const entry of entries) {
32395
- const fullPath = join28(dir, entry);
33532
+ const fullPath = join29(dir, entry);
32396
33533
  const stats = await lstat3(fullPath);
32397
33534
  if (stats.isSymbolicLink()) {
32398
33535
  continue;
@@ -32410,9 +33547,9 @@ class CommandsPrefix {
32410
33547
  // src/services/transformers/folder-path-transformer.ts
32411
33548
  init_logger();
32412
33549
  init_types2();
32413
- var import_fs_extra17 = __toESM(require_lib(), 1);
32414
- import { readFile as readFile15, readdir as readdir12, rename as rename3, writeFile as writeFile13 } from "node:fs/promises";
32415
- import { join as join29, relative as relative8 } from "node:path";
33550
+ var import_fs_extra18 = __toESM(require_lib(), 1);
33551
+ import { readFile as readFile16, readdir as readdir12, rename as rename3, writeFile as writeFile14 } from "node:fs/promises";
33552
+ import { join as join30, relative as relative8 } from "node:path";
32416
33553
  var TRANSFORMABLE_FILE_PATTERNS = [
32417
33554
  ".md",
32418
33555
  ".txt",
@@ -32458,34 +33595,34 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
32458
33595
  }
32459
33596
  const dirsToRename = [];
32460
33597
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
32461
- const docsPath = join29(extractDir, DEFAULT_FOLDERS.docs);
32462
- if (await import_fs_extra17.pathExists(docsPath)) {
33598
+ const docsPath = join30(extractDir, DEFAULT_FOLDERS.docs);
33599
+ if (await import_fs_extra18.pathExists(docsPath)) {
32463
33600
  dirsToRename.push({
32464
33601
  from: docsPath,
32465
- to: join29(extractDir, folders.docs)
33602
+ to: join30(extractDir, folders.docs)
32466
33603
  });
32467
33604
  }
32468
- const claudeDocsPath = join29(extractDir, ".claude", DEFAULT_FOLDERS.docs);
32469
- if (await import_fs_extra17.pathExists(claudeDocsPath)) {
33605
+ const claudeDocsPath = join30(extractDir, ".claude", DEFAULT_FOLDERS.docs);
33606
+ if (await import_fs_extra18.pathExists(claudeDocsPath)) {
32470
33607
  dirsToRename.push({
32471
33608
  from: claudeDocsPath,
32472
- to: join29(extractDir, ".claude", folders.docs)
33609
+ to: join30(extractDir, ".claude", folders.docs)
32473
33610
  });
32474
33611
  }
32475
33612
  }
32476
33613
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
32477
- const plansPath = join29(extractDir, DEFAULT_FOLDERS.plans);
32478
- if (await import_fs_extra17.pathExists(plansPath)) {
33614
+ const plansPath = join30(extractDir, DEFAULT_FOLDERS.plans);
33615
+ if (await import_fs_extra18.pathExists(plansPath)) {
32479
33616
  dirsToRename.push({
32480
33617
  from: plansPath,
32481
- to: join29(extractDir, folders.plans)
33618
+ to: join30(extractDir, folders.plans)
32482
33619
  });
32483
33620
  }
32484
- const claudePlansPath = join29(extractDir, ".claude", DEFAULT_FOLDERS.plans);
32485
- if (await import_fs_extra17.pathExists(claudePlansPath)) {
33621
+ const claudePlansPath = join30(extractDir, ".claude", DEFAULT_FOLDERS.plans);
33622
+ if (await import_fs_extra18.pathExists(claudePlansPath)) {
32486
33623
  dirsToRename.push({
32487
33624
  from: claudePlansPath,
32488
- to: join29(extractDir, ".claude", folders.plans)
33625
+ to: join30(extractDir, ".claude", folders.plans)
32489
33626
  });
32490
33627
  }
32491
33628
  }
@@ -32522,7 +33659,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
32522
33659
  let replacementsCount = 0;
32523
33660
  const entries = await readdir12(dir, { withFileTypes: true });
32524
33661
  for (const entry of entries) {
32525
- const fullPath = join29(dir, entry.name);
33662
+ const fullPath = join30(dir, entry.name);
32526
33663
  if (entry.isDirectory()) {
32527
33664
  if (entry.name === "node_modules" || entry.name === ".git") {
32528
33665
  continue;
@@ -32535,7 +33672,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
32535
33672
  if (!shouldTransform)
32536
33673
  continue;
32537
33674
  try {
32538
- const content = await readFile15(fullPath, "utf-8");
33675
+ const content = await readFile16(fullPath, "utf-8");
32539
33676
  let newContent = content;
32540
33677
  let changeCount = 0;
32541
33678
  for (const { regex: regex2, replacement } of compiledReplacements) {
@@ -32551,7 +33688,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
32551
33688
  if (options.dryRun) {
32552
33689
  logger.debug(`[dry-run] Would update ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
32553
33690
  } else {
32554
- await writeFile13(fullPath, newContent, "utf-8");
33691
+ await writeFile14(fullPath, newContent, "utf-8");
32555
33692
  logger.debug(`Updated ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
32556
33693
  }
32557
33694
  filesChanged++;
@@ -32631,9 +33768,9 @@ function validateFolderName(name2) {
32631
33768
 
32632
33769
  // src/services/transformers/global-path-transformer.ts
32633
33770
  init_logger();
32634
- import { readFile as readFile16, readdir as readdir13, writeFile as writeFile14 } from "node:fs/promises";
33771
+ import { readFile as readFile17, readdir as readdir13, writeFile as writeFile15 } from "node:fs/promises";
32635
33772
  import { platform as platform9 } from "node:os";
32636
- import { extname, join as join30 } from "node:path";
33773
+ import { extname, join as join31 } from "node:path";
32637
33774
  var IS_WINDOWS2 = platform9() === "win32";
32638
33775
  var HOME_PREFIX = IS_WINDOWS2 ? "%USERPROFILE%" : "$HOME";
32639
33776
  function getHomeDirPrefix() {
@@ -32725,7 +33862,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
32725
33862
  async function processDirectory(dir) {
32726
33863
  const entries = await readdir13(dir, { withFileTypes: true });
32727
33864
  for (const entry of entries) {
32728
- const fullPath = join30(dir, entry.name);
33865
+ const fullPath = join31(dir, entry.name);
32729
33866
  if (entry.isDirectory()) {
32730
33867
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
32731
33868
  continue;
@@ -32733,10 +33870,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
32733
33870
  await processDirectory(fullPath);
32734
33871
  } else if (entry.isFile() && shouldTransformFile(entry.name)) {
32735
33872
  try {
32736
- const content = await readFile16(fullPath, "utf-8");
33873
+ const content = await readFile17(fullPath, "utf-8");
32737
33874
  const { transformed, changes } = transformContent(content);
32738
33875
  if (changes > 0) {
32739
- await writeFile14(fullPath, transformed, "utf-8");
33876
+ await writeFile15(fullPath, transformed, "utf-8");
32740
33877
  filesTransformed++;
32741
33878
  totalChanges += changes;
32742
33879
  if (options.verbose) {
@@ -32767,7 +33904,7 @@ init_environment();
32767
33904
  init_logger();
32768
33905
  init_output_manager();
32769
33906
  init_types2();
32770
- var import_fs_extra18 = __toESM(require_lib(), 1);
33907
+ var import_fs_extra19 = __toESM(require_lib(), 1);
32771
33908
  async function initCommand(options) {
32772
33909
  const prompts = new PromptsManager;
32773
33910
  prompts.intro("\uD83D\uDD27 ClaudeKit - Initialize/Update Project");
@@ -32786,8 +33923,8 @@ async function initCommand(options) {
32786
33923
  const globalKitDir = PathResolver.getGlobalKitDir();
32787
33924
  const cwdResolved = resolve6(process.cwd());
32788
33925
  const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve6(globalKitDir, "..");
32789
- const localSettingsPath = join31(process.cwd(), ".claude", "settings.json");
32790
- if (!isInGlobalDir && await import_fs_extra18.pathExists(localSettingsPath)) {
33926
+ const localSettingsPath = join32(process.cwd(), ".claude", "settings.json");
33927
+ if (!isInGlobalDir && await import_fs_extra19.pathExists(localSettingsPath)) {
32791
33928
  if (isNonInteractive2) {
32792
33929
  logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
32793
33930
  logger.warning("Consider removing local installation: rm -rf .claude");
@@ -32798,9 +33935,9 @@ async function initCommand(options) {
32798
33935
  return;
32799
33936
  }
32800
33937
  if (choice === "remove") {
32801
- const localClaudeDir = join31(process.cwd(), ".claude");
33938
+ const localClaudeDir = join32(process.cwd(), ".claude");
32802
33939
  try {
32803
- await import_fs_extra18.remove(localClaudeDir);
33940
+ await import_fs_extra19.remove(localClaudeDir);
32804
33941
  logger.success("Removed local .claude/ directory");
32805
33942
  } catch (error) {
32806
33943
  logger.error(`Failed to remove local installation: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -32844,7 +33981,7 @@ async function initCommand(options) {
32844
33981
  }
32845
33982
  const resolvedDir = resolve6(targetDir);
32846
33983
  logger.info(`Target directory: ${resolvedDir}`);
32847
- if (!await import_fs_extra18.pathExists(resolvedDir)) {
33984
+ if (!await import_fs_extra19.pathExists(resolvedDir)) {
32848
33985
  if (validOptions.global) {
32849
33986
  const { mkdir: mkdir11 } = await import("node:fs/promises");
32850
33987
  await mkdir11(resolvedDir, { recursive: true });
@@ -32857,7 +33994,7 @@ async function initCommand(options) {
32857
33994
  }
32858
33995
  if (validOptions.fresh) {
32859
33996
  const prefix = PathResolver.getPathPrefix(validOptions.global);
32860
- const claudeDir2 = prefix ? join31(resolvedDir, prefix) : resolvedDir;
33997
+ const claudeDir2 = prefix ? join32(resolvedDir, prefix) : resolvedDir;
32861
33998
  const canProceed = await handleFreshInstallation(claudeDir2, prompts);
32862
33999
  if (!canProceed) {
32863
34000
  return;
@@ -32885,7 +34022,7 @@ async function initCommand(options) {
32885
34022
  logger.info("Fetching available versions...");
32886
34023
  let currentVersion = null;
32887
34024
  try {
32888
- const metadataPath = validOptions.global ? join31(PathResolver.getGlobalKitDir(), "metadata.json") : join31(resolvedDir, ".claude", "metadata.json");
34025
+ const metadataPath = validOptions.global ? join32(PathResolver.getGlobalKitDir(), "metadata.json") : join32(resolvedDir, ".claude", "metadata.json");
32889
34026
  const metadata = await readClaudeKitMetadata(metadataPath);
32890
34027
  currentVersion = metadata?.version || null;
32891
34028
  if (currentVersion) {
@@ -33010,9 +34147,9 @@ async function initCommand(options) {
33010
34147
  }
33011
34148
  }
33012
34149
  if (!validOptions.fresh) {
33013
- const newSkillsDir = join31(extractDir, ".claude", "skills");
34150
+ const newSkillsDir = join32(extractDir, ".claude", "skills");
33014
34151
  const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
33015
- if (await import_fs_extra18.pathExists(newSkillsDir) && await import_fs_extra18.pathExists(currentSkillsDir)) {
34152
+ if (await import_fs_extra19.pathExists(newSkillsDir) && await import_fs_extra19.pathExists(currentSkillsDir)) {
33016
34153
  logger.info("Checking for skills directory migration...");
33017
34154
  const migrationDetection = await SkillsMigrationDetector.detectMigration(newSkillsDir, currentSkillsDir);
33018
34155
  if (migrationDetection.status === "recommended" || migrationDetection.status === "required") {
@@ -33035,7 +34172,7 @@ async function initCommand(options) {
33035
34172
  let customClaudeFiles = [];
33036
34173
  if (!validOptions.fresh) {
33037
34174
  logger.info("Scanning for custom .claude files...");
33038
- const scanSourceDir = validOptions.global ? join31(extractDir, ".claude") : extractDir;
34175
+ const scanSourceDir = validOptions.global ? join32(extractDir, ".claude") : extractDir;
33039
34176
  const scanTargetSubdir = validOptions.global ? "" : ".claude";
33040
34177
  customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
33041
34178
  } else {
@@ -33070,9 +34207,12 @@ async function initCommand(options) {
33070
34207
  }
33071
34208
  merger.setGlobalFlag(validOptions.global);
33072
34209
  merger.setForceOverwriteSettings(validOptions.forceOverwriteSettings);
33073
- const claudeDir = validOptions.global ? resolvedDir : join31(resolvedDir, ".claude");
34210
+ const claudeDir = validOptions.global ? resolvedDir : join32(resolvedDir, ".claude");
33074
34211
  const releaseManifest = await ReleaseManifestLoader.load(extractDir);
33075
- if (!validOptions.fresh && await import_fs_extra18.pathExists(claudeDir)) {
34212
+ if (releaseManifest) {
34213
+ merger.setManifest(releaseManifest);
34214
+ }
34215
+ if (!validOptions.fresh && await import_fs_extra19.pathExists(claudeDir)) {
33076
34216
  const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
33077
34217
  if (legacyDetection.isLegacy && releaseManifest) {
33078
34218
  logger.info("Legacy installation detected - migrating to ownership tracking...");
@@ -33092,7 +34232,7 @@ async function initCommand(options) {
33092
34232
  return;
33093
34233
  }
33094
34234
  }
33095
- const sourceDir = validOptions.global ? join31(extractDir, ".claude") : extractDir;
34235
+ const sourceDir = validOptions.global ? join32(extractDir, ".claude") : extractDir;
33096
34236
  await merger.merge(sourceDir, resolvedDir, false);
33097
34237
  const manifestWriter = new ManifestWriter;
33098
34238
  const installedFiles = merger.getAllInstalledFiles();
@@ -33101,7 +34241,7 @@ async function initCommand(options) {
33101
34241
  if (!validOptions.global && !installedPath.startsWith(".claude/"))
33102
34242
  continue;
33103
34243
  const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
33104
- const filePath = join31(claudeDir, relativePath);
34244
+ const filePath = join32(claudeDir, relativePath);
33105
34245
  const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
33106
34246
  const ownership = manifestEntry ? "ck" : "user";
33107
34247
  filesToTrack.push({
@@ -33120,13 +34260,13 @@ async function initCommand(options) {
33120
34260
  }
33121
34261
  });
33122
34262
  trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
33123
- await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
34263
+ await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local", kit);
33124
34264
  if (validOptions.global) {
33125
- const claudeMdSource = join31(extractDir, "CLAUDE.md");
33126
- const claudeMdDest = join31(resolvedDir, "CLAUDE.md");
33127
- if (await import_fs_extra18.pathExists(claudeMdSource)) {
33128
- if (!await import_fs_extra18.pathExists(claudeMdDest)) {
33129
- await import_fs_extra18.copy(claudeMdSource, claudeMdDest);
34265
+ const claudeMdSource = join32(extractDir, "CLAUDE.md");
34266
+ const claudeMdDest = join32(resolvedDir, "CLAUDE.md");
34267
+ if (await import_fs_extra19.pathExists(claudeMdSource)) {
34268
+ if (!await import_fs_extra19.pathExists(claudeMdDest)) {
34269
+ await import_fs_extra19.copy(claudeMdSource, claudeMdDest);
33130
34270
  logger.success("Copied CLAUDE.md to global directory");
33131
34271
  } else {
33132
34272
  logger.debug("CLAUDE.md already exists in global directory (preserved)");
@@ -33165,8 +34305,8 @@ async function initCommand(options) {
33165
34305
  }
33166
34306
  }
33167
34307
  if (!validOptions.skipSetup && !isNonInteractive2) {
33168
- const envPath = join31(claudeDir, ".env");
33169
- if (!await import_fs_extra18.pathExists(envPath)) {
34308
+ const envPath = join32(claudeDir, ".env");
34309
+ if (!await import_fs_extra19.pathExists(envPath)) {
33170
34310
  const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
33171
34311
  if (shouldSetup) {
33172
34312
  await runSetupWizard({
@@ -33196,13 +34336,13 @@ Protected files (.env, etc.) were not modified.`;
33196
34336
  }
33197
34337
 
33198
34338
  // src/commands/new.ts
33199
- import { join as join32, resolve as resolve7 } from "node:path";
34339
+ import { join as join33, resolve as resolve7 } from "node:path";
33200
34340
  init_package_installer();
33201
34341
  init_environment();
33202
34342
  init_logger();
33203
34343
  init_output_manager();
33204
34344
  init_types2();
33205
- var import_fs_extra19 = __toESM(require_lib(), 1);
34345
+ var import_fs_extra20 = __toESM(require_lib(), 1);
33206
34346
  async function newCommand(options) {
33207
34347
  const prompts = new PromptsManager;
33208
34348
  prompts.intro("\uD83D\uDE80 ClaudeKit - Create New Project");
@@ -33229,8 +34369,8 @@ async function newCommand(options) {
33229
34369
  }
33230
34370
  const resolvedDir = resolve7(targetDir);
33231
34371
  logger.info(`Target directory: ${resolvedDir}`);
33232
- if (await import_fs_extra19.pathExists(resolvedDir)) {
33233
- const files = await import_fs_extra19.readdir(resolvedDir);
34372
+ if (await import_fs_extra20.pathExists(resolvedDir)) {
34373
+ const files = await import_fs_extra20.readdir(resolvedDir);
33234
34374
  const isEmpty = files.length === 0;
33235
34375
  if (!isEmpty) {
33236
34376
  if (isNonInteractive2) {
@@ -33377,7 +34517,7 @@ async function newCommand(options) {
33377
34517
  await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
33378
34518
  }
33379
34519
  await merger.merge(extractDir, resolvedDir, true);
33380
- const claudeDir = join32(resolvedDir, ".claude");
34520
+ const claudeDir = join33(resolvedDir, ".claude");
33381
34521
  const manifestWriter = new ManifestWriter;
33382
34522
  const releaseManifest = await ReleaseManifestLoader.load(extractDir);
33383
34523
  const installedFiles = merger.getAllInstalledFiles();
@@ -33386,7 +34526,7 @@ async function newCommand(options) {
33386
34526
  if (!installedPath.startsWith(".claude/"))
33387
34527
  continue;
33388
34528
  const relativePath = installedPath.replace(/^\.claude\//, "");
33389
- const filePath = join32(claudeDir, relativePath);
34529
+ const filePath = join33(claudeDir, relativePath);
33390
34530
  const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
33391
34531
  const ownership = manifestEntry ? "ck" : "user";
33392
34532
  filesToTrack.push({
@@ -33439,10 +34579,10 @@ async function newCommand(options) {
33439
34579
 
33440
34580
  // src/commands/uninstall.ts
33441
34581
  import { readdirSync, rmSync } from "node:fs";
33442
- import { dirname as dirname7, join as join33 } from "node:path";
34582
+ import { dirname as dirname7, join as join34 } from "node:path";
33443
34583
  init_logger();
33444
34584
  init_types2();
33445
- var import_fs_extra20 = __toESM(require_lib(), 1);
34585
+ var import_fs_extra21 = __toESM(require_lib(), 1);
33446
34586
  var import_picocolors13 = __toESM(require_picocolors(), 1);
33447
34587
  async function detectInstallations() {
33448
34588
  const installations = [];
@@ -33451,14 +34591,14 @@ async function detectInstallations() {
33451
34591
  installations.push({
33452
34592
  type: "local",
33453
34593
  path: setup.project.path,
33454
- exists: await import_fs_extra20.pathExists(setup.project.path)
34594
+ exists: await import_fs_extra21.pathExists(setup.project.path)
33455
34595
  });
33456
34596
  }
33457
34597
  if (setup.global.path && setup.global.metadata) {
33458
34598
  installations.push({
33459
34599
  type: "global",
33460
34600
  path: setup.global.path,
33461
- exists: await import_fs_extra20.pathExists(setup.global.path)
34601
+ exists: await import_fs_extra21.pathExists(setup.global.path)
33462
34602
  });
33463
34603
  }
33464
34604
  return installations.filter((i) => i.exists);
@@ -33491,14 +34631,26 @@ async function promptScope(installations) {
33491
34631
  }
33492
34632
  return selected;
33493
34633
  }
33494
- async function confirmUninstall(scope) {
34634
+ async function confirmUninstall(scope, kitLabel = "") {
33495
34635
  const scopeText = scope === "all" ? "all ClaudeKit installations" : scope === "local" ? "local ClaudeKit installation" : "global ClaudeKit installation";
33496
34636
  const confirmed = await se({
33497
- message: `Continue with uninstalling ${scopeText}?`,
34637
+ message: `Continue with uninstalling ${scopeText}${kitLabel}?`,
33498
34638
  initialValue: false
33499
34639
  });
33500
34640
  return confirmed === true;
33501
34641
  }
34642
+ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
34643
+ if (ownership === "ck") {
34644
+ return { action: "delete", reason: deleteReason };
34645
+ }
34646
+ if (ownership === "ck-modified") {
34647
+ if (forceOverwrite) {
34648
+ return { action: "delete", reason: "force overwrite" };
34649
+ }
34650
+ return { action: "preserve", reason: "modified by user" };
34651
+ }
34652
+ return { action: "preserve", reason: "user-created" };
34653
+ }
33502
34654
  async function cleanupEmptyDirectories(filePath, installationRoot) {
33503
34655
  let cleaned = 0;
33504
34656
  let currentDir = dirname7(filePath);
@@ -33519,33 +34671,57 @@ async function cleanupEmptyDirectories(filePath, installationRoot) {
33519
34671
  }
33520
34672
  return cleaned;
33521
34673
  }
33522
- async function analyzeInstallation(installation, forceOverwrite) {
33523
- const result = { toDelete: [], toPreserve: [] };
34674
+ async function analyzeInstallation(installation, forceOverwrite, kit) {
34675
+ const result = {
34676
+ toDelete: [],
34677
+ toPreserve: [],
34678
+ remainingKits: []
34679
+ };
33524
34680
  const metadata = await ManifestWriter.readManifest(installation.path);
33525
- if (!metadata?.files || metadata.files.length === 0) {
33526
- const { filesToRemove, filesToPreserve } = await ManifestWriter.getUninstallManifest(installation.path);
33527
- for (const item of filesToRemove) {
33528
- if (!filesToPreserve.includes(item)) {
34681
+ const uninstallManifest = await ManifestWriter.getUninstallManifest(installation.path, kit);
34682
+ result.remainingKits = uninstallManifest.remainingKits;
34683
+ if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
34684
+ const kitFiles = metadata.kits[kit].files || [];
34685
+ for (const trackedFile of kitFiles) {
34686
+ const filePath = join34(installation.path, trackedFile.path);
34687
+ if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
34688
+ result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
34689
+ continue;
34690
+ }
34691
+ const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
34692
+ if (!ownershipResult.exists)
34693
+ continue;
34694
+ const classification = classifyFileByOwnership(ownershipResult.ownership, forceOverwrite, `${kit} kit (pristine)`);
34695
+ if (classification.action === "delete") {
34696
+ result.toDelete.push({ path: trackedFile.path, reason: classification.reason });
34697
+ } else {
34698
+ result.toPreserve.push({ path: trackedFile.path, reason: classification.reason });
34699
+ }
34700
+ }
34701
+ if (result.remainingKits.length === 0) {
34702
+ result.toDelete.push({ path: "metadata.json", reason: "metadata file" });
34703
+ }
34704
+ return result;
34705
+ }
34706
+ const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
34707
+ if (!metadata || allTrackedFiles.length === 0) {
34708
+ for (const item of uninstallManifest.filesToRemove) {
34709
+ if (!uninstallManifest.filesToPreserve.includes(item)) {
33529
34710
  result.toDelete.push({ path: item, reason: "legacy installation" });
33530
34711
  }
33531
34712
  }
33532
34713
  return result;
33533
34714
  }
33534
- for (const trackedFile of metadata.files) {
33535
- const filePath = join33(installation.path, trackedFile.path);
34715
+ for (const trackedFile of allTrackedFiles) {
34716
+ const filePath = join34(installation.path, trackedFile.path);
33536
34717
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
33537
34718
  if (!ownershipResult.exists)
33538
34719
  continue;
33539
- if (ownershipResult.ownership === "ck") {
33540
- result.toDelete.push({ path: trackedFile.path, reason: "CK-owned (pristine)" });
33541
- } else if (ownershipResult.ownership === "ck-modified") {
33542
- if (forceOverwrite) {
33543
- result.toDelete.push({ path: trackedFile.path, reason: "force overwrite" });
33544
- } else {
33545
- result.toPreserve.push({ path: trackedFile.path, reason: "modified by user" });
33546
- }
34720
+ const classification = classifyFileByOwnership(ownershipResult.ownership, forceOverwrite, "CK-owned (pristine)");
34721
+ if (classification.action === "delete") {
34722
+ result.toDelete.push({ path: trackedFile.path, reason: classification.reason });
33547
34723
  } else {
33548
- result.toPreserve.push({ path: trackedFile.path, reason: "user-created" });
34724
+ result.toPreserve.push({ path: trackedFile.path, reason: classification.reason });
33549
34725
  }
33550
34726
  }
33551
34727
  result.toDelete.push({ path: "metadata.json", reason: "metadata file" });
@@ -33580,24 +34756,32 @@ function displayDryRunPreview(analysis, installationType) {
33580
34756
  }
33581
34757
  async function removeInstallations(installations, options) {
33582
34758
  for (const installation of installations) {
33583
- const analysis = await analyzeInstallation(installation, options.forceOverwrite);
34759
+ const analysis = await analyzeInstallation(installation, options.forceOverwrite, options.kit);
33584
34760
  if (options.dryRun) {
33585
- displayDryRunPreview(analysis, installation.type);
34761
+ const label = options.kit ? `${installation.type} (${options.kit} kit)` : installation.type;
34762
+ displayDryRunPreview(analysis, label);
34763
+ if (analysis.remainingKits.length > 0) {
34764
+ log.info(`Remaining kits after uninstall: ${analysis.remainingKits.join(", ")}`);
34765
+ }
33586
34766
  continue;
33587
34767
  }
33588
- const spinner = createSpinner(`Removing ${installation.type} ClaudeKit files...`).start();
34768
+ const kitLabel = options.kit ? ` ${options.kit} kit` : "";
34769
+ const spinner = createSpinner(`Removing ${installation.type}${kitLabel} ClaudeKit files...`).start();
33589
34770
  try {
33590
34771
  let removedCount = 0;
33591
34772
  let cleanedDirs = 0;
33592
34773
  for (const item of analysis.toDelete) {
33593
- const filePath = join33(installation.path, item.path);
33594
- if (await import_fs_extra20.pathExists(filePath)) {
33595
- await import_fs_extra20.remove(filePath);
34774
+ const filePath = join34(installation.path, item.path);
34775
+ if (await import_fs_extra21.pathExists(filePath)) {
34776
+ await import_fs_extra21.remove(filePath);
33596
34777
  removedCount++;
33597
34778
  logger.debug(`Removed: ${item.path}`);
33598
34779
  cleanedDirs += await cleanupEmptyDirectories(filePath, installation.path);
33599
34780
  }
33600
34781
  }
34782
+ if (options.kit && analysis.remainingKits.length > 0) {
34783
+ await ManifestWriter.removeKitFromManifest(installation.path, options.kit);
34784
+ }
33601
34785
  try {
33602
34786
  const remaining = readdirSync(installation.path);
33603
34787
  if (remaining.length === 0) {
@@ -33605,7 +34789,8 @@ async function removeInstallations(installations, options) {
33605
34789
  logger.debug(`Removed empty installation directory: ${installation.path}`);
33606
34790
  }
33607
34791
  } catch {}
33608
- spinner.succeed(`Removed ${removedCount} files${cleanedDirs > 0 ? `, cleaned ${cleanedDirs} empty directories` : ""}, preserved ${analysis.toPreserve.length} customizations`);
34792
+ const kitsInfo = analysis.remainingKits.length > 0 ? `, ${analysis.remainingKits.join(", ")} kit(s) preserved` : "";
34793
+ spinner.succeed(`Removed ${removedCount} files${cleanedDirs > 0 ? `, cleaned ${cleanedDirs} empty directories` : ""}, preserved ${analysis.toPreserve.length} customizations${kitsInfo}`);
33609
34794
  if (analysis.toPreserve.length > 0) {
33610
34795
  log.info("Preserved customizations:");
33611
34796
  analysis.toPreserve.slice(0, 5).forEach((f3) => log.message(` - ${f3.path} (${f3.reason})`));
@@ -33627,6 +34812,23 @@ async function uninstallCommand(options) {
33627
34812
  logger.info("No ClaudeKit installations found.");
33628
34813
  return;
33629
34814
  }
34815
+ if (validOptions.kit) {
34816
+ let kitFound = false;
34817
+ for (const inst of allInstallations) {
34818
+ const metadata = await ManifestWriter.readManifest(inst.path);
34819
+ if (metadata) {
34820
+ const installedKits = getInstalledKits(metadata);
34821
+ if (installedKits.includes(validOptions.kit)) {
34822
+ kitFound = true;
34823
+ break;
34824
+ }
34825
+ }
34826
+ }
34827
+ if (!kitFound) {
34828
+ logger.info(`Kit "${validOptions.kit}" is not installed.`);
34829
+ return;
34830
+ }
34831
+ }
33630
34832
  let scope;
33631
34833
  if (validOptions.all || validOptions.local && validOptions.global) {
33632
34834
  scope = "all";
@@ -33653,11 +34855,15 @@ async function uninstallCommand(options) {
33653
34855
  return;
33654
34856
  }
33655
34857
  displayInstallations(installations, scope);
34858
+ if (validOptions.kit) {
34859
+ log.info(import_picocolors13.default.cyan(`Kit-scoped uninstall: ${validOptions.kit} kit only`));
34860
+ }
33656
34861
  if (validOptions.dryRun) {
33657
34862
  log.info(import_picocolors13.default.yellow("DRY RUN MODE - No files will be deleted"));
33658
34863
  await removeInstallations(installations, {
33659
34864
  dryRun: true,
33660
- forceOverwrite: validOptions.forceOverwrite
34865
+ forceOverwrite: validOptions.forceOverwrite,
34866
+ kit: validOptions.kit
33661
34867
  });
33662
34868
  outro("Dry-run complete. No changes were made.");
33663
34869
  return;
@@ -33667,7 +34873,8 @@ async function uninstallCommand(options) {
33667
34873
  ${import_picocolors13.default.yellow("User modifications will be permanently deleted!")}`);
33668
34874
  }
33669
34875
  if (!validOptions.yes) {
33670
- const confirmed = await confirmUninstall(scope);
34876
+ const kitLabel = validOptions.kit ? ` (${validOptions.kit} kit only)` : "";
34877
+ const confirmed = await confirmUninstall(scope, kitLabel);
33671
34878
  if (!confirmed) {
33672
34879
  logger.info("Uninstall cancelled.");
33673
34880
  return;
@@ -33675,9 +34882,11 @@ ${import_picocolors13.default.yellow("User modifications will be permanently del
33675
34882
  }
33676
34883
  await removeInstallations(installations, {
33677
34884
  dryRun: false,
33678
- forceOverwrite: validOptions.forceOverwrite
34885
+ forceOverwrite: validOptions.forceOverwrite,
34886
+ kit: validOptions.kit
33679
34887
  });
33680
- outro("ClaudeKit uninstalled successfully!");
34888
+ const kitMsg = validOptions.kit ? ` (${validOptions.kit} kit)` : "";
34889
+ outro(`ClaudeKit${kitMsg} uninstalled successfully!`);
33681
34890
  } catch (error) {
33682
34891
  logger.error(error instanceof Error ? error.message : "Unknown error");
33683
34892
  process.exit(1);
@@ -33831,7 +35040,7 @@ var import_compare_versions2 = __toESM(require_umd(), 1);
33831
35040
  // package.json
33832
35041
  var package_default2 = {
33833
35042
  name: "claudekit-cli",
33834
- version: "3.10.2",
35043
+ version: "3.11.1",
33835
35044
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
33836
35045
  type: "module",
33837
35046
  repository: {
@@ -33851,7 +35060,7 @@ var package_default2 = {
33851
35060
  ],
33852
35061
  scripts: {
33853
35062
  dev: "bun run src/index.ts",
33854
- build: "bun build src/index.ts --outdir dist --target node --external keytar --external @octokit/rest",
35063
+ build: "bun build src/index.ts --outdir dist --target node --external @octokit/rest",
33855
35064
  compile: "bun build src/index.ts --compile --outfile ck",
33856
35065
  "compile:binary": "bun build src/index.ts --compile --outfile bin/ck",
33857
35066
  "compile:binaries": "node scripts/build-all-binaries.js",
@@ -33892,11 +35101,11 @@ var package_default2 = {
33892
35101
  "extract-zip": "^2.0.1",
33893
35102
  "fs-extra": "^11.2.0",
33894
35103
  ignore: "^5.3.2",
33895
- keytar: "^7.9.0",
33896
35104
  minimatch: "^10.1.1",
33897
35105
  ora: "^8.0.0",
33898
35106
  "p-limit": "^7.2.0",
33899
35107
  picocolors: "^1.1.1",
35108
+ "proper-lockfile": "^4.1.2",
33900
35109
  tar: "^7.4.3",
33901
35110
  tmp: "^0.2.3",
33902
35111
  zod: "^3.23.8"
@@ -33909,6 +35118,7 @@ var package_default2 = {
33909
35118
  "@types/cli-progress": "^3.11.6",
33910
35119
  "@types/fs-extra": "^11.0.4",
33911
35120
  "@types/node": "^22.10.1",
35121
+ "@types/proper-lockfile": "^4.1.4",
33912
35122
  "@types/tar": "^6.1.13",
33913
35123
  "@types/tmp": "^0.2.6",
33914
35124
  "semantic-release": "^24.2.0",
@@ -34139,14 +35349,14 @@ var import_picocolors15 = __toESM(require_picocolors(), 1);
34139
35349
  // src/domains/versioning/version-cache.ts
34140
35350
  init_logger();
34141
35351
  import { existsSync as existsSync8 } from "node:fs";
34142
- import { mkdir as mkdir11, readFile as readFile17, writeFile as writeFile15 } from "node:fs/promises";
34143
- import { join as join34 } from "node:path";
35352
+ import { mkdir as mkdir11, readFile as readFile18, writeFile as writeFile16 } from "node:fs/promises";
35353
+ import { join as join35 } from "node:path";
34144
35354
  class VersionCacheManager {
34145
35355
  static CACHE_FILENAME = "version-check.json";
34146
35356
  static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
34147
35357
  static getCacheFile() {
34148
35358
  const cacheDir = PathResolver.getCacheDir(false);
34149
- return join34(cacheDir, VersionCacheManager.CACHE_FILENAME);
35359
+ return join35(cacheDir, VersionCacheManager.CACHE_FILENAME);
34150
35360
  }
34151
35361
  static async load() {
34152
35362
  const cacheFile = VersionCacheManager.getCacheFile();
@@ -34155,7 +35365,7 @@ class VersionCacheManager {
34155
35365
  logger.debug("Version check cache not found");
34156
35366
  return null;
34157
35367
  }
34158
- const content = await readFile17(cacheFile, "utf-8");
35368
+ const content = await readFile18(cacheFile, "utf-8");
34159
35369
  const cache2 = JSON.parse(content);
34160
35370
  if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
34161
35371
  logger.debug("Invalid cache structure, ignoring");
@@ -34175,7 +35385,7 @@ class VersionCacheManager {
34175
35385
  if (!existsSync8(cacheDir)) {
34176
35386
  await mkdir11(cacheDir, { recursive: true, mode: 448 });
34177
35387
  }
34178
- await writeFile15(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
35388
+ await writeFile16(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
34179
35389
  logger.debug(`Version check cache saved to ${cacheFile}`);
34180
35390
  } catch (error) {
34181
35391
  logger.debug(`Failed to save version check cache: ${error}`);
@@ -34658,7 +35868,7 @@ var output2 = new OutputManager2;
34658
35868
 
34659
35869
  // src/shared/path-resolver.ts
34660
35870
  import { homedir as homedir5, platform as platform10 } from "node:os";
34661
- import { join as join35, normalize as normalize6 } from "node:path";
35871
+ import { join as join36, normalize as normalize6 } from "node:path";
34662
35872
 
34663
35873
  class PathResolver2 {
34664
35874
  static getTestHomeDir() {
@@ -34691,50 +35901,50 @@ class PathResolver2 {
34691
35901
  static getConfigDir(global3 = false) {
34692
35902
  const testHome = PathResolver2.getTestHomeDir();
34693
35903
  if (testHome) {
34694
- return global3 ? join35(testHome, ".config", "claude") : join35(testHome, ".claudekit");
35904
+ return global3 ? join36(testHome, ".config", "claude") : join36(testHome, ".claudekit");
34695
35905
  }
34696
35906
  if (!global3) {
34697
- return join35(homedir5(), ".claudekit");
35907
+ return join36(homedir5(), ".claudekit");
34698
35908
  }
34699
35909
  const os2 = platform10();
34700
35910
  if (os2 === "win32") {
34701
- const localAppData = process.env.LOCALAPPDATA || join35(homedir5(), "AppData", "Local");
34702
- return join35(localAppData, "claude");
35911
+ const localAppData = process.env.LOCALAPPDATA || join36(homedir5(), "AppData", "Local");
35912
+ return join36(localAppData, "claude");
34703
35913
  }
34704
35914
  const xdgConfigHome = process.env.XDG_CONFIG_HOME;
34705
35915
  if (xdgConfigHome) {
34706
- return join35(xdgConfigHome, "claude");
35916
+ return join36(xdgConfigHome, "claude");
34707
35917
  }
34708
- return join35(homedir5(), ".config", "claude");
35918
+ return join36(homedir5(), ".config", "claude");
34709
35919
  }
34710
35920
  static getConfigFile(global3 = false) {
34711
- return join35(PathResolver2.getConfigDir(global3), "config.json");
35921
+ return join36(PathResolver2.getConfigDir(global3), "config.json");
34712
35922
  }
34713
35923
  static getCacheDir(global3 = false) {
34714
35924
  const testHome = PathResolver2.getTestHomeDir();
34715
35925
  if (testHome) {
34716
- return global3 ? join35(testHome, ".cache", "claude") : join35(testHome, ".claudekit", "cache");
35926
+ return global3 ? join36(testHome, ".cache", "claude") : join36(testHome, ".claudekit", "cache");
34717
35927
  }
34718
35928
  if (!global3) {
34719
- return join35(homedir5(), ".claudekit", "cache");
35929
+ return join36(homedir5(), ".claudekit", "cache");
34720
35930
  }
34721
35931
  const os2 = platform10();
34722
35932
  if (os2 === "win32") {
34723
- const localAppData = process.env.LOCALAPPDATA || join35(homedir5(), "AppData", "Local");
34724
- return join35(localAppData, "claude", "cache");
35933
+ const localAppData = process.env.LOCALAPPDATA || join36(homedir5(), "AppData", "Local");
35934
+ return join36(localAppData, "claude", "cache");
34725
35935
  }
34726
35936
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
34727
35937
  if (xdgCacheHome) {
34728
- return join35(xdgCacheHome, "claude");
35938
+ return join36(xdgCacheHome, "claude");
34729
35939
  }
34730
- return join35(homedir5(), ".cache", "claude");
35940
+ return join36(homedir5(), ".cache", "claude");
34731
35941
  }
34732
35942
  static getGlobalKitDir() {
34733
35943
  const testHome = PathResolver2.getTestHomeDir();
34734
35944
  if (testHome) {
34735
- return join35(testHome, ".claude");
35945
+ return join36(testHome, ".claude");
34736
35946
  }
34737
- return join35(homedir5(), ".claude");
35947
+ return join36(homedir5(), ".claude");
34738
35948
  }
34739
35949
  static getPathPrefix(global3) {
34740
35950
  return global3 ? "" : ".claude";
@@ -34742,9 +35952,9 @@ class PathResolver2 {
34742
35952
  static buildSkillsPath(baseDir, global3) {
34743
35953
  const prefix = PathResolver2.getPathPrefix(global3);
34744
35954
  if (prefix) {
34745
- return join35(baseDir, prefix, "skills");
35955
+ return join36(baseDir, prefix, "skills");
34746
35956
  }
34747
- return join35(baseDir, "skills");
35957
+ return join36(baseDir, "skills");
34748
35958
  }
34749
35959
  static buildComponentPath(baseDir, component, global3) {
34750
35960
  if (!PathResolver2.isPathSafe(component)) {
@@ -34752,9 +35962,9 @@ class PathResolver2 {
34752
35962
  }
34753
35963
  const prefix = PathResolver2.getPathPrefix(global3);
34754
35964
  if (prefix) {
34755
- return join35(baseDir, prefix, component);
35965
+ return join36(baseDir, prefix, component);
34756
35966
  }
34757
- return join35(baseDir, component);
35967
+ return join36(baseDir, component);
34758
35968
  }
34759
35969
  }
34760
35970
 
@@ -34786,9 +35996,9 @@ async function displayVersion() {
34786
35996
  let localKitVersion = null;
34787
35997
  let isGlobalOnlyKit = false;
34788
35998
  const globalKitDir = PathResolver2.getGlobalKitDir();
34789
- const globalMetadataPath = join36(globalKitDir, "metadata.json");
35999
+ const globalMetadataPath = join37(globalKitDir, "metadata.json");
34790
36000
  const prefix = PathResolver2.getPathPrefix(false);
34791
- const localMetadataPath = prefix ? join36(process.cwd(), prefix, "metadata.json") : join36(process.cwd(), "metadata.json");
36001
+ const localMetadataPath = prefix ? join37(process.cwd(), prefix, "metadata.json") : join37(process.cwd(), "metadata.json");
34792
36002
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
34793
36003
  if (!isLocalSameAsGlobal && existsSync9(localMetadataPath)) {
34794
36004
  try {
@@ -34892,7 +36102,7 @@ cli.command("versions", "List available versions of ClaudeKit repositories").opt
34892
36102
  cli.command("doctor", "Comprehensive health check for ClaudeKit").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options) => {
34893
36103
  await doctorCommand(options);
34894
36104
  });
34895
- cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "Skip confirmation prompt").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("--dry-run", "Preview what would be removed without deleting").option("--force-overwrite", "Delete even user-modified files (requires confirmation)").action(async (options) => {
36105
+ cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "Skip confirmation prompt").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("-k, --kit <type>", "Uninstall specific kit only (engineer, marketing)").option("--dry-run", "Preview what would be removed without deleting").option("--force-overwrite", "Delete even user-modified files (requires confirmation)").action(async (options) => {
34896
36106
  await uninstallCommand(options);
34897
36107
  });
34898
36108
  cli.option("-V, --version", "Display version number");