claudekit-cli 3.10.2 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1582 -372
- 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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
13141
|
+
import { dirname as dirname6, join as join26, resolve as resolve3 } from "node:path";
|
|
12380
13142
|
function getGlobalMcpConfigPath() {
|
|
12381
|
-
return
|
|
13143
|
+
return join26(homedir4(), ".claude", ".mcp.json");
|
|
12382
13144
|
}
|
|
12383
13145
|
function getLocalMcpConfigPath(projectDir) {
|
|
12384
|
-
return
|
|
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
|
|
13164
|
+
return join26(homedir4(), ".gemini", "settings.json");
|
|
12403
13165
|
}
|
|
12404
|
-
return
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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: ${
|
|
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:
|
|
12981
|
-
const scriptContent = await
|
|
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(` ${
|
|
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 ${
|
|
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
|
|
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.
|
|
15469
|
+
version: "3.11.0",
|
|
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
|
|
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
|
|
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
|
|
28413
|
+
import { dirname as dirname5, join as join12, relative as relative3 } from "node:path";
|
|
27651
28414
|
|
|
27652
28415
|
// src/domains/config/settings-merger.ts
|
|
27653
28416
|
init_logger();
|
|
@@ -29293,7 +30056,130 @@ minimatch.Minimatch = Minimatch;
|
|
|
29293
30056
|
minimatch.escape = escape;
|
|
29294
30057
|
minimatch.unescape = unescape;
|
|
29295
30058
|
|
|
29296
|
-
// src/domains/installation/
|
|
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
|
+
class OwnershipChecker {
|
|
30069
|
+
static async calculateChecksum(filePath) {
|
|
30070
|
+
return new Promise((resolve3, reject) => {
|
|
30071
|
+
const hash = createHash("sha256");
|
|
30072
|
+
const stream = createReadStream(filePath);
|
|
30073
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
30074
|
+
stream.on("end", () => {
|
|
30075
|
+
resolve3(hash.digest("hex"));
|
|
30076
|
+
});
|
|
30077
|
+
stream.on("error", (err) => {
|
|
30078
|
+
stream.destroy();
|
|
30079
|
+
reject(new Error(`Failed to calculate checksum for "${filePath}": ${err.message}`));
|
|
30080
|
+
});
|
|
30081
|
+
});
|
|
30082
|
+
}
|
|
30083
|
+
static async checkOwnership(filePath, metadata, claudeDir) {
|
|
30084
|
+
try {
|
|
30085
|
+
await stat(filePath);
|
|
30086
|
+
} catch {
|
|
30087
|
+
return { path: filePath, ownership: "user", exists: false };
|
|
30088
|
+
}
|
|
30089
|
+
if (!metadata || !metadata.files || metadata.files.length === 0) {
|
|
30090
|
+
return { path: filePath, ownership: "user", exists: true };
|
|
30091
|
+
}
|
|
30092
|
+
const relativePath = relative2(claudeDir, filePath).replace(/\\/g, "/");
|
|
30093
|
+
const tracked = metadata.files.find((f3) => f3.path === relativePath);
|
|
30094
|
+
if (!tracked) {
|
|
30095
|
+
return { path: filePath, ownership: "user", exists: true };
|
|
30096
|
+
}
|
|
30097
|
+
const actualChecksum = await OwnershipChecker.calculateChecksum(filePath);
|
|
30098
|
+
if (actualChecksum === tracked.checksum) {
|
|
30099
|
+
return {
|
|
30100
|
+
path: filePath,
|
|
30101
|
+
ownership: "ck",
|
|
30102
|
+
expectedChecksum: tracked.checksum,
|
|
30103
|
+
actualChecksum,
|
|
30104
|
+
exists: true
|
|
30105
|
+
};
|
|
30106
|
+
}
|
|
30107
|
+
return {
|
|
30108
|
+
path: filePath,
|
|
30109
|
+
ownership: "ck-modified",
|
|
30110
|
+
expectedChecksum: tracked.checksum,
|
|
30111
|
+
actualChecksum,
|
|
30112
|
+
exists: true
|
|
30113
|
+
};
|
|
30114
|
+
}
|
|
30115
|
+
static async checkBatch(filePaths, metadata, claudeDir) {
|
|
30116
|
+
const results = await Promise.all(filePaths.map((path9) => OwnershipChecker.checkOwnership(path9, metadata, claudeDir)));
|
|
30117
|
+
return new Map(results.map((r2) => [r2.path, r2]));
|
|
30118
|
+
}
|
|
30119
|
+
}
|
|
30120
|
+
|
|
30121
|
+
// src/domains/installation/selective-merger.ts
|
|
30122
|
+
init_logger();
|
|
30123
|
+
|
|
30124
|
+
class SelectiveMerger {
|
|
30125
|
+
manifest;
|
|
30126
|
+
manifestMap;
|
|
30127
|
+
constructor(manifest) {
|
|
30128
|
+
this.manifest = manifest;
|
|
30129
|
+
this.manifestMap = new Map;
|
|
30130
|
+
if (manifest) {
|
|
30131
|
+
for (const file of manifest.files) {
|
|
30132
|
+
this.manifestMap.set(file.path, file);
|
|
30133
|
+
}
|
|
30134
|
+
}
|
|
30135
|
+
}
|
|
30136
|
+
async shouldCopyFile(destPath, relativePath) {
|
|
30137
|
+
let destStat;
|
|
30138
|
+
try {
|
|
30139
|
+
destStat = await stat2(destPath);
|
|
30140
|
+
} catch {
|
|
30141
|
+
return { changed: true, reason: "new" };
|
|
30142
|
+
}
|
|
30143
|
+
const manifestEntry = this.manifestMap.get(relativePath);
|
|
30144
|
+
if (!manifestEntry) {
|
|
30145
|
+
logger.debug(`No manifest entry for ${relativePath}, will copy`);
|
|
30146
|
+
return { changed: true, reason: "new" };
|
|
30147
|
+
}
|
|
30148
|
+
if (destStat.size !== manifestEntry.size) {
|
|
30149
|
+
logger.debug(`Size differs for ${relativePath}: ${destStat.size} vs ${manifestEntry.size}`);
|
|
30150
|
+
return {
|
|
30151
|
+
changed: true,
|
|
30152
|
+
reason: "size-differ",
|
|
30153
|
+
sourceChecksum: manifestEntry.checksum
|
|
30154
|
+
};
|
|
30155
|
+
}
|
|
30156
|
+
const destChecksum = await OwnershipChecker.calculateChecksum(destPath);
|
|
30157
|
+
if (destChecksum !== manifestEntry.checksum) {
|
|
30158
|
+
logger.debug(`Checksum differs for ${relativePath}`);
|
|
30159
|
+
return {
|
|
30160
|
+
changed: true,
|
|
30161
|
+
reason: "checksum-differ",
|
|
30162
|
+
sourceChecksum: manifestEntry.checksum,
|
|
30163
|
+
destChecksum
|
|
30164
|
+
};
|
|
30165
|
+
}
|
|
30166
|
+
logger.debug(`Unchanged: ${relativePath}`);
|
|
30167
|
+
return {
|
|
30168
|
+
changed: false,
|
|
30169
|
+
reason: "unchanged",
|
|
30170
|
+
sourceChecksum: manifestEntry.checksum,
|
|
30171
|
+
destChecksum
|
|
30172
|
+
};
|
|
30173
|
+
}
|
|
30174
|
+
hasManifest() {
|
|
30175
|
+
return this.manifest !== null && this.manifestMap.size > 0;
|
|
30176
|
+
}
|
|
30177
|
+
getManifestFileCount() {
|
|
30178
|
+
return this.manifestMap.size;
|
|
30179
|
+
}
|
|
30180
|
+
}
|
|
30181
|
+
|
|
30182
|
+
// src/domains/installation/file-merger.ts
|
|
29297
30183
|
class FileMerger {
|
|
29298
30184
|
neverCopyChecker = import_ignore2.default().add(NEVER_COPY_PATTERNS);
|
|
29299
30185
|
userConfigChecker = import_ignore2.default().add(USER_CONFIG_PATTERNS);
|
|
@@ -29302,6 +30188,8 @@ class FileMerger {
|
|
|
29302
30188
|
forceOverwriteSettings = false;
|
|
29303
30189
|
installedFiles = new Set;
|
|
29304
30190
|
installedDirectories = new Set;
|
|
30191
|
+
selectiveMerger = null;
|
|
30192
|
+
unchangedSkipped = 0;
|
|
29305
30193
|
setIncludePatterns(patterns) {
|
|
29306
30194
|
this.includePatterns = patterns;
|
|
29307
30195
|
}
|
|
@@ -29311,6 +30199,12 @@ class FileMerger {
|
|
|
29311
30199
|
setForceOverwriteSettings(force) {
|
|
29312
30200
|
this.forceOverwriteSettings = force;
|
|
29313
30201
|
}
|
|
30202
|
+
setManifest(manifest) {
|
|
30203
|
+
this.selectiveMerger = manifest ? new SelectiveMerger(manifest) : null;
|
|
30204
|
+
if (manifest && this.selectiveMerger?.hasManifest()) {
|
|
30205
|
+
logger.debug(`Selective merge enabled with ${this.selectiveMerger.getManifestFileCount()} tracked files`);
|
|
30206
|
+
}
|
|
30207
|
+
}
|
|
29314
30208
|
async merge(sourceDir, destDir, skipConfirmation = false) {
|
|
29315
30209
|
const conflicts = await this.detectConflicts(sourceDir, destDir);
|
|
29316
30210
|
if (conflicts.length > 0 && !skipConfirmation) {
|
|
@@ -29332,7 +30226,7 @@ class FileMerger {
|
|
|
29332
30226
|
const conflicts = [];
|
|
29333
30227
|
const files = await this.getFiles(sourceDir, sourceDir);
|
|
29334
30228
|
for (const file of files) {
|
|
29335
|
-
const relativePath =
|
|
30229
|
+
const relativePath = relative3(sourceDir, file);
|
|
29336
30230
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29337
30231
|
const destPath = join12(destDir, relativePath);
|
|
29338
30232
|
if (await import_fs_extra3.pathExists(destPath)) {
|
|
@@ -29354,7 +30248,7 @@ class FileMerger {
|
|
|
29354
30248
|
let copiedCount = 0;
|
|
29355
30249
|
let skippedCount = 0;
|
|
29356
30250
|
for (const file of files) {
|
|
29357
|
-
const relativePath =
|
|
30251
|
+
const relativePath = relative3(sourceDir, file);
|
|
29358
30252
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29359
30253
|
const destPath = join12(destDir, relativePath);
|
|
29360
30254
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
@@ -29377,11 +30271,24 @@ class FileMerger {
|
|
|
29377
30271
|
copiedCount++;
|
|
29378
30272
|
continue;
|
|
29379
30273
|
}
|
|
30274
|
+
if (this.selectiveMerger?.hasManifest()) {
|
|
30275
|
+
const compareResult = await this.selectiveMerger.shouldCopyFile(destPath, normalizedRelativePath);
|
|
30276
|
+
if (!compareResult.changed) {
|
|
30277
|
+
logger.debug(`Skipping unchanged: ${normalizedRelativePath}`);
|
|
30278
|
+
this.unchangedSkipped++;
|
|
30279
|
+
this.trackInstalledFile(normalizedRelativePath);
|
|
30280
|
+
continue;
|
|
30281
|
+
}
|
|
30282
|
+
}
|
|
29380
30283
|
await import_fs_extra3.copy(file, destPath, { overwrite: true });
|
|
29381
30284
|
this.trackInstalledFile(normalizedRelativePath);
|
|
29382
30285
|
copiedCount++;
|
|
29383
30286
|
}
|
|
29384
|
-
|
|
30287
|
+
if (this.unchangedSkipped > 0) {
|
|
30288
|
+
logger.success(`Updated ${copiedCount} file(s), skipped ${this.unchangedSkipped} unchanged, skipped ${skippedCount} protected`);
|
|
30289
|
+
} else {
|
|
30290
|
+
logger.success(`Copied ${copiedCount} file(s), skipped ${skippedCount} protected file(s)`);
|
|
30291
|
+
}
|
|
29385
30292
|
}
|
|
29386
30293
|
async processSettingsJson(sourceFile, destFile) {
|
|
29387
30294
|
try {
|
|
@@ -29472,7 +30379,7 @@ class FileMerger {
|
|
|
29472
30379
|
const entries = await import_fs_extra3.readdir(dir, { encoding: "utf8" });
|
|
29473
30380
|
for (const entry of entries) {
|
|
29474
30381
|
const fullPath = join12(dir, entry);
|
|
29475
|
-
const relativePath =
|
|
30382
|
+
const relativePath = relative3(baseDir, fullPath);
|
|
29476
30383
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29477
30384
|
const stats = await import_fs_extra3.lstat(fullPath);
|
|
29478
30385
|
if (stats.isSymbolicLink()) {
|
|
@@ -29731,14 +30638,165 @@ async function runSetupWizard(options) {
|
|
|
29731
30638
|
}
|
|
29732
30639
|
|
|
29733
30640
|
// src/domains/migration/legacy-migration.ts
|
|
29734
|
-
import { readdir as readdir4, stat as
|
|
29735
|
-
import { join as
|
|
30641
|
+
import { readdir as readdir4, stat as stat3 } from "node:fs/promises";
|
|
30642
|
+
import { join as join19, relative as relative4 } from "node:path";
|
|
29736
30643
|
|
|
29737
30644
|
// src/services/file-operations/manifest-writer.ts
|
|
30645
|
+
import { join as join17 } from "node:path";
|
|
30646
|
+
|
|
30647
|
+
// src/domains/migration/metadata-migration.ts
|
|
29738
30648
|
init_logger();
|
|
29739
|
-
init_types2();
|
|
29740
30649
|
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
29741
30650
|
import { join as join16 } from "node:path";
|
|
30651
|
+
async function detectMetadataFormat(claudeDir) {
|
|
30652
|
+
const metadataPath = join16(claudeDir, "metadata.json");
|
|
30653
|
+
if (!await import_fs_extra7.pathExists(metadataPath)) {
|
|
30654
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30655
|
+
}
|
|
30656
|
+
try {
|
|
30657
|
+
const content = await import_fs_extra7.readFile(metadataPath, "utf-8");
|
|
30658
|
+
const parsed = JSON.parse(content);
|
|
30659
|
+
if (parsed.kits && Object.keys(parsed.kits).length > 0) {
|
|
30660
|
+
const installedKits = Object.keys(parsed.kits);
|
|
30661
|
+
return {
|
|
30662
|
+
format: "multi-kit",
|
|
30663
|
+
metadata: parsed,
|
|
30664
|
+
detectedKit: installedKits[0] || null
|
|
30665
|
+
};
|
|
30666
|
+
}
|
|
30667
|
+
if (parsed.name || parsed.version || parsed.files) {
|
|
30668
|
+
let detectedKit = null;
|
|
30669
|
+
const nameToCheck = parsed.name || "";
|
|
30670
|
+
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30671
|
+
detectedKit = "engineer";
|
|
30672
|
+
} else if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30673
|
+
detectedKit = "marketing";
|
|
30674
|
+
} else {
|
|
30675
|
+
detectedKit = "engineer";
|
|
30676
|
+
}
|
|
30677
|
+
return { format: "legacy", metadata: parsed, detectedKit };
|
|
30678
|
+
}
|
|
30679
|
+
logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
|
|
30680
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30681
|
+
} catch (error) {
|
|
30682
|
+
logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
|
|
30683
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30684
|
+
}
|
|
30685
|
+
}
|
|
30686
|
+
async function migrateToMultiKit(claudeDir) {
|
|
30687
|
+
const detection = await detectMetadataFormat(claudeDir);
|
|
30688
|
+
if (detection.format === "multi-kit") {
|
|
30689
|
+
return {
|
|
30690
|
+
success: true,
|
|
30691
|
+
migrated: false,
|
|
30692
|
+
fromFormat: "multi-kit",
|
|
30693
|
+
toFormat: "multi-kit"
|
|
30694
|
+
};
|
|
30695
|
+
}
|
|
30696
|
+
if (detection.format === "none") {
|
|
30697
|
+
return {
|
|
30698
|
+
success: true,
|
|
30699
|
+
migrated: false,
|
|
30700
|
+
fromFormat: "none",
|
|
30701
|
+
toFormat: "multi-kit"
|
|
30702
|
+
};
|
|
30703
|
+
}
|
|
30704
|
+
const metadataPath = join16(claudeDir, "metadata.json");
|
|
30705
|
+
const legacy = detection.metadata;
|
|
30706
|
+
if (!legacy) {
|
|
30707
|
+
return {
|
|
30708
|
+
success: false,
|
|
30709
|
+
migrated: false,
|
|
30710
|
+
fromFormat: "legacy",
|
|
30711
|
+
toFormat: "multi-kit",
|
|
30712
|
+
error: "Metadata exists but could not be read"
|
|
30713
|
+
};
|
|
30714
|
+
}
|
|
30715
|
+
const legacyKit = detection.detectedKit || "engineer";
|
|
30716
|
+
try {
|
|
30717
|
+
const kitMetadata = {
|
|
30718
|
+
version: legacy.version || "unknown",
|
|
30719
|
+
installedAt: legacy.installedAt || new Date().toISOString(),
|
|
30720
|
+
files: legacy.files || []
|
|
30721
|
+
};
|
|
30722
|
+
const multiKit = {
|
|
30723
|
+
kits: {
|
|
30724
|
+
[legacyKit]: kitMetadata
|
|
30725
|
+
},
|
|
30726
|
+
scope: legacy.scope,
|
|
30727
|
+
name: legacy.name,
|
|
30728
|
+
version: legacy.version,
|
|
30729
|
+
installedAt: legacy.installedAt,
|
|
30730
|
+
installedFiles: legacy.installedFiles,
|
|
30731
|
+
userConfigFiles: legacy.userConfigFiles,
|
|
30732
|
+
files: legacy.files
|
|
30733
|
+
};
|
|
30734
|
+
await import_fs_extra7.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
|
|
30735
|
+
logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
|
|
30736
|
+
return {
|
|
30737
|
+
success: true,
|
|
30738
|
+
migrated: true,
|
|
30739
|
+
fromFormat: "legacy",
|
|
30740
|
+
toFormat: "multi-kit"
|
|
30741
|
+
};
|
|
30742
|
+
} catch (error) {
|
|
30743
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
30744
|
+
logger.error(`Metadata migration failed: ${errorMsg}`);
|
|
30745
|
+
return {
|
|
30746
|
+
success: false,
|
|
30747
|
+
migrated: false,
|
|
30748
|
+
fromFormat: "legacy",
|
|
30749
|
+
toFormat: "multi-kit",
|
|
30750
|
+
error: errorMsg
|
|
30751
|
+
};
|
|
30752
|
+
}
|
|
30753
|
+
}
|
|
30754
|
+
function getKitMetadata(metadata, kit) {
|
|
30755
|
+
if (metadata.kits?.[kit]) {
|
|
30756
|
+
return metadata.kits[kit];
|
|
30757
|
+
}
|
|
30758
|
+
if (!metadata.kits && metadata.version) {
|
|
30759
|
+
return {
|
|
30760
|
+
version: metadata.version,
|
|
30761
|
+
installedAt: metadata.installedAt || "",
|
|
30762
|
+
files: metadata.files
|
|
30763
|
+
};
|
|
30764
|
+
}
|
|
30765
|
+
return null;
|
|
30766
|
+
}
|
|
30767
|
+
function getAllTrackedFiles(metadata) {
|
|
30768
|
+
if (metadata.kits) {
|
|
30769
|
+
const allFiles = [];
|
|
30770
|
+
for (const kit of Object.values(metadata.kits)) {
|
|
30771
|
+
if (kit.files) {
|
|
30772
|
+
allFiles.push(...kit.files);
|
|
30773
|
+
}
|
|
30774
|
+
}
|
|
30775
|
+
return allFiles;
|
|
30776
|
+
}
|
|
30777
|
+
return metadata.files || [];
|
|
30778
|
+
}
|
|
30779
|
+
function getInstalledKits(metadata) {
|
|
30780
|
+
if (metadata.kits) {
|
|
30781
|
+
return Object.keys(metadata.kits);
|
|
30782
|
+
}
|
|
30783
|
+
const nameToCheck = metadata.name || "";
|
|
30784
|
+
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30785
|
+
return ["engineer"];
|
|
30786
|
+
}
|
|
30787
|
+
if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30788
|
+
return ["marketing"];
|
|
30789
|
+
}
|
|
30790
|
+
if (metadata.version) {
|
|
30791
|
+
return ["engineer"];
|
|
30792
|
+
}
|
|
30793
|
+
return [];
|
|
30794
|
+
}
|
|
30795
|
+
|
|
30796
|
+
// src/services/file-operations/manifest-writer.ts
|
|
30797
|
+
init_logger();
|
|
30798
|
+
init_types2();
|
|
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
|
-
|
|
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
|
-
|
|
31004
|
+
if (completed > reportedProgress) {
|
|
31005
|
+
reportedProgress = completed;
|
|
31006
|
+
onProgress?.(completed, total);
|
|
31007
|
+
}
|
|
30005
31008
|
}
|
|
30006
31009
|
return result;
|
|
30007
31010
|
}));
|
|
@@ -30015,39 +31018,70 @@ 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 =
|
|
30020
|
-
|
|
30021
|
-
|
|
30022
|
-
|
|
30023
|
-
|
|
30024
|
-
|
|
30025
|
-
|
|
30026
|
-
|
|
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
|
+
installedFiles: this.getInstalledFiles(),
|
|
31065
|
+
userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()],
|
|
31066
|
+
files: trackedFiles.length > 0 ? trackedFiles : undefined
|
|
31067
|
+
};
|
|
31068
|
+
const validated = MetadataSchema.parse(metadata);
|
|
31069
|
+
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
31070
|
+
logger.debug(`Wrote manifest for kit "${kit}" with ${trackedFiles.length} tracked files`);
|
|
31071
|
+
} finally {
|
|
31072
|
+
if (release) {
|
|
31073
|
+
await release();
|
|
31074
|
+
logger.debug(`Released lock on ${metadataPath}`);
|
|
30027
31075
|
}
|
|
30028
31076
|
}
|
|
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
31077
|
}
|
|
30044
31078
|
static async readManifest(claudeDir) {
|
|
30045
|
-
const metadataPath =
|
|
30046
|
-
if (!await
|
|
31079
|
+
const metadataPath = join17(claudeDir, "metadata.json");
|
|
31080
|
+
if (!await import_fs_extra8.pathExists(metadataPath)) {
|
|
30047
31081
|
return null;
|
|
30048
31082
|
}
|
|
30049
31083
|
try {
|
|
30050
|
-
const content = await
|
|
31084
|
+
const content = await import_fs_extra8.readFile(metadataPath, "utf-8");
|
|
30051
31085
|
const parsed = JSON.parse(content);
|
|
30052
31086
|
return MetadataSchema.parse(parsed);
|
|
30053
31087
|
} catch (error) {
|
|
@@ -30055,13 +31089,82 @@ class ManifestWriter {
|
|
|
30055
31089
|
return null;
|
|
30056
31090
|
}
|
|
30057
31091
|
}
|
|
30058
|
-
static async
|
|
31092
|
+
static async readKitManifest(claudeDir, kit) {
|
|
30059
31093
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
30060
|
-
if (metadata
|
|
31094
|
+
if (!metadata)
|
|
31095
|
+
return null;
|
|
31096
|
+
return getKitMetadata(metadata, kit);
|
|
31097
|
+
}
|
|
31098
|
+
static async getUninstallManifest(claudeDir, kit) {
|
|
31099
|
+
const detection = await detectMetadataFormat(claudeDir);
|
|
31100
|
+
if (detection.format === "multi-kit" && detection.metadata?.kits) {
|
|
31101
|
+
const installedKits = Object.keys(detection.metadata.kits);
|
|
31102
|
+
if (kit) {
|
|
31103
|
+
const kitMeta = detection.metadata.kits[kit];
|
|
31104
|
+
if (!kitMeta?.files) {
|
|
31105
|
+
return {
|
|
31106
|
+
filesToRemove: [],
|
|
31107
|
+
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
31108
|
+
hasManifest: true,
|
|
31109
|
+
isMultiKit: true,
|
|
31110
|
+
remainingKits: installedKits.filter((k2) => k2 !== kit)
|
|
31111
|
+
};
|
|
31112
|
+
}
|
|
31113
|
+
const kitFiles = kitMeta.files.map((f3) => f3.path);
|
|
31114
|
+
const sharedFiles = new Set;
|
|
31115
|
+
for (const otherKit of installedKits) {
|
|
31116
|
+
if (otherKit !== kit) {
|
|
31117
|
+
const otherMeta = detection.metadata.kits[otherKit];
|
|
31118
|
+
if (otherMeta?.files) {
|
|
31119
|
+
for (const f3 of otherMeta.files) {
|
|
31120
|
+
sharedFiles.add(f3.path);
|
|
31121
|
+
}
|
|
31122
|
+
}
|
|
31123
|
+
}
|
|
31124
|
+
}
|
|
31125
|
+
const filesToRemove = kitFiles.filter((f3) => !sharedFiles.has(f3));
|
|
31126
|
+
const filesToPreserve = [
|
|
31127
|
+
...USER_CONFIG_PATTERNS,
|
|
31128
|
+
...kitFiles.filter((f3) => sharedFiles.has(f3))
|
|
31129
|
+
];
|
|
31130
|
+
return {
|
|
31131
|
+
filesToRemove,
|
|
31132
|
+
filesToPreserve,
|
|
31133
|
+
hasManifest: true,
|
|
31134
|
+
isMultiKit: true,
|
|
31135
|
+
remainingKits: installedKits.filter((k2) => k2 !== kit)
|
|
31136
|
+
};
|
|
31137
|
+
}
|
|
31138
|
+
const allFiles = getAllTrackedFiles(detection.metadata);
|
|
31139
|
+
return {
|
|
31140
|
+
filesToRemove: allFiles.map((f3) => f3.path),
|
|
31141
|
+
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
31142
|
+
hasManifest: true,
|
|
31143
|
+
isMultiKit: true,
|
|
31144
|
+
remainingKits: []
|
|
31145
|
+
};
|
|
31146
|
+
}
|
|
31147
|
+
if (detection.format === "legacy" && detection.metadata) {
|
|
31148
|
+
const legacyFiles2 = detection.metadata.files?.map((f3) => f3.path) || [];
|
|
31149
|
+
const installedFiles = detection.metadata.installedFiles || [];
|
|
31150
|
+
const hasFiles = legacyFiles2.length > 0 || installedFiles.length > 0;
|
|
31151
|
+
if (!hasFiles) {
|
|
31152
|
+
const legacyDirs2 = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
|
|
31153
|
+
const legacyFileList = ["metadata.json"];
|
|
31154
|
+
return {
|
|
31155
|
+
filesToRemove: [...legacyDirs2, ...legacyFileList],
|
|
31156
|
+
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
31157
|
+
hasManifest: false,
|
|
31158
|
+
isMultiKit: false,
|
|
31159
|
+
remainingKits: []
|
|
31160
|
+
};
|
|
31161
|
+
}
|
|
30061
31162
|
return {
|
|
30062
|
-
filesToRemove:
|
|
30063
|
-
filesToPreserve: metadata.userConfigFiles || USER_CONFIG_PATTERNS,
|
|
30064
|
-
hasManifest: true
|
|
31163
|
+
filesToRemove: legacyFiles2.length > 0 ? legacyFiles2 : installedFiles,
|
|
31164
|
+
filesToPreserve: detection.metadata.userConfigFiles || USER_CONFIG_PATTERNS,
|
|
31165
|
+
hasManifest: true,
|
|
31166
|
+
isMultiKit: false,
|
|
31167
|
+
remainingKits: []
|
|
30065
31168
|
};
|
|
30066
31169
|
}
|
|
30067
31170
|
const legacyDirs = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
|
|
@@ -30069,20 +31172,55 @@ class ManifestWriter {
|
|
|
30069
31172
|
return {
|
|
30070
31173
|
filesToRemove: [...legacyDirs, ...legacyFiles],
|
|
30071
31174
|
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
30072
|
-
hasManifest: false
|
|
31175
|
+
hasManifest: false,
|
|
31176
|
+
isMultiKit: false,
|
|
31177
|
+
remainingKits: []
|
|
30073
31178
|
};
|
|
30074
31179
|
}
|
|
31180
|
+
static async removeKitFromManifest(claudeDir, kit) {
|
|
31181
|
+
const metadataPath = join17(claudeDir, "metadata.json");
|
|
31182
|
+
if (!await import_fs_extra8.pathExists(metadataPath))
|
|
31183
|
+
return false;
|
|
31184
|
+
let release = null;
|
|
31185
|
+
try {
|
|
31186
|
+
release = await import_proper_lockfile.lock(metadataPath, {
|
|
31187
|
+
retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
|
|
31188
|
+
stale: 60000
|
|
31189
|
+
});
|
|
31190
|
+
logger.debug(`Acquired lock on ${metadataPath} for kit removal`);
|
|
31191
|
+
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
31192
|
+
if (!metadata?.kits?.[kit])
|
|
31193
|
+
return false;
|
|
31194
|
+
const { [kit]: _removed, ...remainingKits } = metadata.kits;
|
|
31195
|
+
if (Object.keys(remainingKits).length === 0) {
|
|
31196
|
+
logger.debug("No kits remaining, metadata.json will be cleaned up");
|
|
31197
|
+
return true;
|
|
31198
|
+
}
|
|
31199
|
+
const updated = {
|
|
31200
|
+
...metadata,
|
|
31201
|
+
kits: remainingKits
|
|
31202
|
+
};
|
|
31203
|
+
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
31204
|
+
logger.debug(`Removed kit "${kit}" from metadata, ${Object.keys(remainingKits).length} kit(s) remaining`);
|
|
31205
|
+
return true;
|
|
31206
|
+
} finally {
|
|
31207
|
+
if (release) {
|
|
31208
|
+
await release();
|
|
31209
|
+
logger.debug(`Released lock on ${metadataPath}`);
|
|
31210
|
+
}
|
|
31211
|
+
}
|
|
31212
|
+
}
|
|
30075
31213
|
}
|
|
30076
31214
|
|
|
30077
31215
|
// src/domains/migration/legacy-migration.ts
|
|
30078
31216
|
init_logger();
|
|
30079
|
-
var
|
|
31217
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
30080
31218
|
|
|
30081
31219
|
// src/domains/migration/release-manifest.ts
|
|
30082
31220
|
init_logger();
|
|
30083
31221
|
init_zod();
|
|
30084
|
-
var
|
|
30085
|
-
import { join as
|
|
31222
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
31223
|
+
import { join as join18 } from "node:path";
|
|
30086
31224
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
30087
31225
|
path: exports_external.string(),
|
|
30088
31226
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -30096,9 +31234,9 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
30096
31234
|
|
|
30097
31235
|
class ReleaseManifestLoader {
|
|
30098
31236
|
static async load(extractDir) {
|
|
30099
|
-
const manifestPath =
|
|
31237
|
+
const manifestPath = join18(extractDir, "release-manifest.json");
|
|
30100
31238
|
try {
|
|
30101
|
-
const content = await
|
|
31239
|
+
const content = await import_fs_extra9.readFile(manifestPath, "utf-8");
|
|
30102
31240
|
const parsed = JSON.parse(content);
|
|
30103
31241
|
return ReleaseManifestSchema.parse(parsed);
|
|
30104
31242
|
} catch (error) {
|
|
@@ -30142,10 +31280,10 @@ class LegacyMigration {
|
|
|
30142
31280
|
for (const entry of entries) {
|
|
30143
31281
|
if (entry === "metadata.json")
|
|
30144
31282
|
continue;
|
|
30145
|
-
const fullPath =
|
|
31283
|
+
const fullPath = join19(dir, entry);
|
|
30146
31284
|
let stats;
|
|
30147
31285
|
try {
|
|
30148
|
-
stats = await
|
|
31286
|
+
stats = await stat3(fullPath);
|
|
30149
31287
|
} catch (err) {
|
|
30150
31288
|
const error = err;
|
|
30151
31289
|
if (error.code === "ENOENT") {
|
|
@@ -30244,7 +31382,7 @@ User-created files (sample):`);
|
|
|
30244
31382
|
];
|
|
30245
31383
|
if (filesToChecksum.length > 0) {
|
|
30246
31384
|
const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
|
|
30247
|
-
const fullPath =
|
|
31385
|
+
const fullPath = join19(claudeDir, relativePath);
|
|
30248
31386
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
30249
31387
|
return { relativePath, checksum, ownership };
|
|
30250
31388
|
}));
|
|
@@ -30265,8 +31403,8 @@ User-created files (sample):`);
|
|
|
30265
31403
|
installedAt: new Date().toISOString(),
|
|
30266
31404
|
files: trackedFiles
|
|
30267
31405
|
};
|
|
30268
|
-
const metadataPath =
|
|
30269
|
-
await
|
|
31406
|
+
const metadataPath = join19(claudeDir, "metadata.json");
|
|
31407
|
+
await import_fs_extra10.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
30270
31408
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
30271
31409
|
return true;
|
|
30272
31410
|
}
|
|
@@ -30274,24 +31412,24 @@ User-created files (sample):`);
|
|
|
30274
31412
|
|
|
30275
31413
|
// src/domains/skills/skills-detector.ts
|
|
30276
31414
|
init_logger();
|
|
30277
|
-
var
|
|
31415
|
+
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
30278
31416
|
import { readdir as readdir6 } from "node:fs/promises";
|
|
30279
|
-
import { join as
|
|
31417
|
+
import { join as join21 } from "node:path";
|
|
30280
31418
|
|
|
30281
31419
|
// src/domains/skills/skills-manifest.ts
|
|
30282
31420
|
init_logger();
|
|
30283
31421
|
init_types2();
|
|
30284
|
-
var
|
|
31422
|
+
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
30285
31423
|
import { createHash as createHash2 } from "node:crypto";
|
|
30286
|
-
import { readFile as
|
|
30287
|
-
import { join as
|
|
31424
|
+
import { readFile as readFile13, readdir as readdir5, writeFile as writeFile12 } from "node:fs/promises";
|
|
31425
|
+
import { join as join20, relative as relative5 } from "node:path";
|
|
30288
31426
|
|
|
30289
31427
|
class SkillsManifestManager {
|
|
30290
31428
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
30291
31429
|
static MANIFEST_VERSION = "1.0.0";
|
|
30292
31430
|
static async generateManifest(skillsDir) {
|
|
30293
31431
|
logger.debug(`Generating manifest for: ${skillsDir}`);
|
|
30294
|
-
if (!await
|
|
31432
|
+
if (!await import_fs_extra11.pathExists(skillsDir)) {
|
|
30295
31433
|
throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
|
|
30296
31434
|
}
|
|
30297
31435
|
const structure = await SkillsManifestManager.detectStructure(skillsDir);
|
|
@@ -30306,18 +31444,18 @@ class SkillsManifestManager {
|
|
|
30306
31444
|
return manifest;
|
|
30307
31445
|
}
|
|
30308
31446
|
static async writeManifest(skillsDir, manifest) {
|
|
30309
|
-
const manifestPath =
|
|
30310
|
-
await
|
|
31447
|
+
const manifestPath = join20(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31448
|
+
await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
30311
31449
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
30312
31450
|
}
|
|
30313
31451
|
static async readManifest(skillsDir) {
|
|
30314
|
-
const manifestPath =
|
|
30315
|
-
if (!await
|
|
31452
|
+
const manifestPath = join20(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31453
|
+
if (!await import_fs_extra11.pathExists(manifestPath)) {
|
|
30316
31454
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
30317
31455
|
return null;
|
|
30318
31456
|
}
|
|
30319
31457
|
try {
|
|
30320
|
-
const content = await
|
|
31458
|
+
const content = await readFile13(manifestPath, "utf-8");
|
|
30321
31459
|
const data = JSON.parse(content);
|
|
30322
31460
|
const manifest = SkillsManifestSchema.parse(data);
|
|
30323
31461
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -30334,7 +31472,7 @@ class SkillsManifestManager {
|
|
|
30334
31472
|
return "flat";
|
|
30335
31473
|
}
|
|
30336
31474
|
for (const dir of dirs.slice(0, 3)) {
|
|
30337
|
-
const dirPath =
|
|
31475
|
+
const dirPath = join20(skillsDir, dir.name);
|
|
30338
31476
|
const subEntries = await readdir5(dirPath, { withFileTypes: true });
|
|
30339
31477
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
30340
31478
|
if (hasSubdirs) {
|
|
@@ -30353,7 +31491,7 @@ class SkillsManifestManager {
|
|
|
30353
31491
|
const entries = await readdir5(skillsDir, { withFileTypes: true });
|
|
30354
31492
|
for (const entry of entries) {
|
|
30355
31493
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
30356
|
-
const skillPath =
|
|
31494
|
+
const skillPath = join20(skillsDir, entry.name);
|
|
30357
31495
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30358
31496
|
skills.push({
|
|
30359
31497
|
name: entry.name,
|
|
@@ -30365,11 +31503,11 @@ class SkillsManifestManager {
|
|
|
30365
31503
|
const categories = await readdir5(skillsDir, { withFileTypes: true });
|
|
30366
31504
|
for (const category of categories) {
|
|
30367
31505
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
30368
|
-
const categoryPath =
|
|
31506
|
+
const categoryPath = join20(skillsDir, category.name);
|
|
30369
31507
|
const skillEntries = await readdir5(categoryPath, { withFileTypes: true });
|
|
30370
31508
|
for (const skillEntry of skillEntries) {
|
|
30371
31509
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
30372
|
-
const skillPath =
|
|
31510
|
+
const skillPath = join20(categoryPath, skillEntry.name);
|
|
30373
31511
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30374
31512
|
skills.push({
|
|
30375
31513
|
name: skillEntry.name,
|
|
@@ -30389,7 +31527,7 @@ class SkillsManifestManager {
|
|
|
30389
31527
|
files.sort();
|
|
30390
31528
|
for (const file of files) {
|
|
30391
31529
|
const relativePath = relative5(dirPath, file);
|
|
30392
|
-
const content = await
|
|
31530
|
+
const content = await readFile13(file);
|
|
30393
31531
|
hash.update(relativePath);
|
|
30394
31532
|
hash.update(content);
|
|
30395
31533
|
}
|
|
@@ -30399,7 +31537,7 @@ class SkillsManifestManager {
|
|
|
30399
31537
|
const files = [];
|
|
30400
31538
|
const entries = await readdir5(dirPath, { withFileTypes: true });
|
|
30401
31539
|
for (const entry of entries) {
|
|
30402
|
-
const fullPath =
|
|
31540
|
+
const fullPath = join20(dirPath, entry.name);
|
|
30403
31541
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30404
31542
|
continue;
|
|
30405
31543
|
}
|
|
@@ -30519,8 +31657,8 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
30519
31657
|
class SkillsMigrationDetector {
|
|
30520
31658
|
static async detectMigration(oldSkillsDir, currentSkillsDir) {
|
|
30521
31659
|
logger.debug("Detecting skills migration need...");
|
|
30522
|
-
const oldExists = await
|
|
30523
|
-
const currentExists = await
|
|
31660
|
+
const oldExists = await import_fs_extra12.pathExists(oldSkillsDir);
|
|
31661
|
+
const currentExists = await import_fs_extra12.pathExists(currentSkillsDir);
|
|
30524
31662
|
if (!oldExists && !currentExists) {
|
|
30525
31663
|
logger.debug("No skills directories found, migration not needed");
|
|
30526
31664
|
return {
|
|
@@ -30631,7 +31769,7 @@ class SkillsMigrationDetector {
|
|
|
30631
31769
|
};
|
|
30632
31770
|
}
|
|
30633
31771
|
static async scanDirectory(skillsDir) {
|
|
30634
|
-
if (!await
|
|
31772
|
+
if (!await import_fs_extra12.pathExists(skillsDir)) {
|
|
30635
31773
|
return ["flat", []];
|
|
30636
31774
|
}
|
|
30637
31775
|
const entries = await readdir6(skillsDir, { withFileTypes: true });
|
|
@@ -30642,12 +31780,12 @@ class SkillsMigrationDetector {
|
|
|
30642
31780
|
let totalSkillLikeCount = 0;
|
|
30643
31781
|
const allSkills = [];
|
|
30644
31782
|
for (const dir of dirs) {
|
|
30645
|
-
const dirPath =
|
|
31783
|
+
const dirPath = join21(skillsDir, dir.name);
|
|
30646
31784
|
const subEntries = await readdir6(dirPath, { withFileTypes: true });
|
|
30647
31785
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30648
31786
|
if (subdirs.length > 0) {
|
|
30649
31787
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30650
|
-
const subdirPath =
|
|
31788
|
+
const subdirPath = join21(dirPath, subdir.name);
|
|
30651
31789
|
const subdirFiles = await readdir6(subdirPath, { withFileTypes: true });
|
|
30652
31790
|
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
31791
|
if (hasSkillMarker) {
|
|
@@ -30684,16 +31822,16 @@ class SkillsMigrationDetector {
|
|
|
30684
31822
|
// src/domains/skills/skills-migrator.ts
|
|
30685
31823
|
init_logger();
|
|
30686
31824
|
init_types2();
|
|
30687
|
-
var
|
|
31825
|
+
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
30688
31826
|
import { copyFile as copyFile2, mkdir as mkdir8, readdir as readdir9, rm as rm3 } from "node:fs/promises";
|
|
30689
|
-
import { join as
|
|
31827
|
+
import { join as join24 } from "node:path";
|
|
30690
31828
|
|
|
30691
31829
|
// src/domains/skills/skills-backup-manager.ts
|
|
30692
31830
|
init_logger();
|
|
30693
31831
|
init_types2();
|
|
30694
|
-
var
|
|
30695
|
-
import { copyFile, mkdir as mkdir7, readdir as readdir7, rm as rm2, stat as
|
|
30696
|
-
import { basename as basename2, join as
|
|
31832
|
+
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
31833
|
+
import { copyFile, mkdir as mkdir7, readdir as readdir7, rm as rm2, stat as stat4 } from "node:fs/promises";
|
|
31834
|
+
import { basename as basename2, join as join22, normalize as normalize4 } from "node:path";
|
|
30697
31835
|
function validatePath(path9, paramName) {
|
|
30698
31836
|
if (!path9 || typeof path9 !== "string") {
|
|
30699
31837
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30713,13 +31851,13 @@ class SkillsBackupManager {
|
|
|
30713
31851
|
if (parentDir) {
|
|
30714
31852
|
validatePath(parentDir, "parentDir");
|
|
30715
31853
|
}
|
|
30716
|
-
if (!await
|
|
31854
|
+
if (!await import_fs_extra13.pathExists(skillsDir)) {
|
|
30717
31855
|
throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
|
|
30718
31856
|
}
|
|
30719
31857
|
const timestamp = Date.now();
|
|
30720
31858
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
30721
31859
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
30722
|
-
const backupDir = parentDir ?
|
|
31860
|
+
const backupDir = parentDir ? join22(parentDir, backupDirName) : join22(skillsDir, "..", backupDirName);
|
|
30723
31861
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
30724
31862
|
try {
|
|
30725
31863
|
await mkdir7(backupDir, { recursive: true });
|
|
@@ -30736,12 +31874,12 @@ class SkillsBackupManager {
|
|
|
30736
31874
|
static async restoreBackup(backupDir, targetDir) {
|
|
30737
31875
|
validatePath(backupDir, "backupDir");
|
|
30738
31876
|
validatePath(targetDir, "targetDir");
|
|
30739
|
-
if (!await
|
|
31877
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30740
31878
|
throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
|
|
30741
31879
|
}
|
|
30742
31880
|
logger.info(`Restoring from backup: ${backupDir}`);
|
|
30743
31881
|
try {
|
|
30744
|
-
if (await
|
|
31882
|
+
if (await import_fs_extra13.pathExists(targetDir)) {
|
|
30745
31883
|
await rm2(targetDir, { recursive: true, force: true });
|
|
30746
31884
|
}
|
|
30747
31885
|
await mkdir7(targetDir, { recursive: true });
|
|
@@ -30752,7 +31890,7 @@ class SkillsBackupManager {
|
|
|
30752
31890
|
}
|
|
30753
31891
|
}
|
|
30754
31892
|
static async deleteBackup(backupDir) {
|
|
30755
|
-
if (!await
|
|
31893
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30756
31894
|
logger.warning(`Backup directory does not exist: ${backupDir}`);
|
|
30757
31895
|
return;
|
|
30758
31896
|
}
|
|
@@ -30765,12 +31903,12 @@ class SkillsBackupManager {
|
|
|
30765
31903
|
}
|
|
30766
31904
|
}
|
|
30767
31905
|
static async listBackups(parentDir) {
|
|
30768
|
-
if (!await
|
|
31906
|
+
if (!await import_fs_extra13.pathExists(parentDir)) {
|
|
30769
31907
|
return [];
|
|
30770
31908
|
}
|
|
30771
31909
|
try {
|
|
30772
31910
|
const entries = await readdir7(parentDir, { withFileTypes: true });
|
|
30773
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
31911
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join22(parentDir, entry.name));
|
|
30774
31912
|
backups.sort().reverse();
|
|
30775
31913
|
return backups;
|
|
30776
31914
|
} catch (error) {
|
|
@@ -30790,7 +31928,7 @@ class SkillsBackupManager {
|
|
|
30790
31928
|
}
|
|
30791
31929
|
}
|
|
30792
31930
|
static async getBackupSize(backupDir) {
|
|
30793
|
-
if (!await
|
|
31931
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30794
31932
|
return 0;
|
|
30795
31933
|
}
|
|
30796
31934
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
@@ -30798,8 +31936,8 @@ class SkillsBackupManager {
|
|
|
30798
31936
|
static async copyDirectory(sourceDir, destDir) {
|
|
30799
31937
|
const entries = await readdir7(sourceDir, { withFileTypes: true });
|
|
30800
31938
|
for (const entry of entries) {
|
|
30801
|
-
const sourcePath =
|
|
30802
|
-
const destPath =
|
|
31939
|
+
const sourcePath = join22(sourceDir, entry.name);
|
|
31940
|
+
const destPath = join22(destDir, entry.name);
|
|
30803
31941
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30804
31942
|
continue;
|
|
30805
31943
|
}
|
|
@@ -30815,14 +31953,14 @@ class SkillsBackupManager {
|
|
|
30815
31953
|
let size = 0;
|
|
30816
31954
|
const entries = await readdir7(dirPath, { withFileTypes: true });
|
|
30817
31955
|
for (const entry of entries) {
|
|
30818
|
-
const fullPath =
|
|
31956
|
+
const fullPath = join22(dirPath, entry.name);
|
|
30819
31957
|
if (entry.isSymbolicLink()) {
|
|
30820
31958
|
continue;
|
|
30821
31959
|
}
|
|
30822
31960
|
if (entry.isDirectory()) {
|
|
30823
31961
|
size += await SkillsBackupManager.getDirectorySize(fullPath);
|
|
30824
31962
|
} else if (entry.isFile()) {
|
|
30825
|
-
const stats = await
|
|
31963
|
+
const stats = await stat4(fullPath);
|
|
30826
31964
|
size += stats.size;
|
|
30827
31965
|
}
|
|
30828
31966
|
}
|
|
@@ -30842,11 +31980,11 @@ class SkillsBackupManager {
|
|
|
30842
31980
|
// src/domains/skills/skills-customization-scanner.ts
|
|
30843
31981
|
init_logger();
|
|
30844
31982
|
init_types2();
|
|
30845
|
-
var
|
|
31983
|
+
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
30846
31984
|
import { createHash as createHash3 } from "node:crypto";
|
|
30847
31985
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
30848
|
-
import { readFile as
|
|
30849
|
-
import { join as
|
|
31986
|
+
import { readFile as readFile14, readdir as readdir8 } from "node:fs/promises";
|
|
31987
|
+
import { join as join23, normalize as normalize5, relative as relative6 } from "node:path";
|
|
30850
31988
|
function validatePath2(path9, paramName) {
|
|
30851
31989
|
if (!path9 || typeof path9 !== "string") {
|
|
30852
31990
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30925,7 +32063,7 @@ class SkillsCustomizationScanner {
|
|
|
30925
32063
|
static async detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
30926
32064
|
const changes = [];
|
|
30927
32065
|
const currentFiles = await SkillsCustomizationScanner.getAllFiles(currentSkillPath);
|
|
30928
|
-
const baselineFiles = await
|
|
32066
|
+
const baselineFiles = await import_fs_extra14.pathExists(baselineSkillPath) ? await SkillsCustomizationScanner.getAllFiles(baselineSkillPath) : [];
|
|
30929
32067
|
const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
|
|
30930
32068
|
const relPath = relative6(currentSkillPath, f3);
|
|
30931
32069
|
const hash = await SkillsCustomizationScanner.hashFile(f3);
|
|
@@ -30985,7 +32123,7 @@ class SkillsCustomizationScanner {
|
|
|
30985
32123
|
return false;
|
|
30986
32124
|
}
|
|
30987
32125
|
static async scanSkillsDirectory(skillsDir) {
|
|
30988
|
-
if (!await
|
|
32126
|
+
if (!await import_fs_extra14.pathExists(skillsDir)) {
|
|
30989
32127
|
return ["flat", []];
|
|
30990
32128
|
}
|
|
30991
32129
|
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
@@ -30993,13 +32131,13 @@ class SkillsCustomizationScanner {
|
|
|
30993
32131
|
if (dirs.length === 0) {
|
|
30994
32132
|
return ["flat", []];
|
|
30995
32133
|
}
|
|
30996
|
-
const firstDirPath =
|
|
32134
|
+
const firstDirPath = join23(skillsDir, dirs[0].name);
|
|
30997
32135
|
const subEntries = await readdir8(firstDirPath, { withFileTypes: true });
|
|
30998
32136
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30999
32137
|
if (subdirs.length > 0) {
|
|
31000
32138
|
let skillLikeCount = 0;
|
|
31001
32139
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
31002
|
-
const subdirPath =
|
|
32140
|
+
const subdirPath = join23(firstDirPath, subdir.name);
|
|
31003
32141
|
const subdirFiles = await readdir8(subdirPath, { withFileTypes: true });
|
|
31004
32142
|
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
32143
|
if (hasSkillMarker) {
|
|
@@ -31009,7 +32147,7 @@ class SkillsCustomizationScanner {
|
|
|
31009
32147
|
if (skillLikeCount > 0) {
|
|
31010
32148
|
const skills = [];
|
|
31011
32149
|
for (const dir of dirs) {
|
|
31012
|
-
const categoryPath =
|
|
32150
|
+
const categoryPath = join23(skillsDir, dir.name);
|
|
31013
32151
|
const skillDirs = await readdir8(categoryPath, { withFileTypes: true });
|
|
31014
32152
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
31015
32153
|
}
|
|
@@ -31019,8 +32157,8 @@ class SkillsCustomizationScanner {
|
|
|
31019
32157
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
31020
32158
|
}
|
|
31021
32159
|
static async findSkillPath(skillsDir, skillName) {
|
|
31022
|
-
const flatPath =
|
|
31023
|
-
if (await
|
|
32160
|
+
const flatPath = join23(skillsDir, skillName);
|
|
32161
|
+
if (await import_fs_extra14.pathExists(flatPath)) {
|
|
31024
32162
|
return { path: flatPath, category: undefined };
|
|
31025
32163
|
}
|
|
31026
32164
|
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
@@ -31028,9 +32166,9 @@ class SkillsCustomizationScanner {
|
|
|
31028
32166
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
31029
32167
|
continue;
|
|
31030
32168
|
}
|
|
31031
|
-
const categoryPath =
|
|
31032
|
-
const skillPath =
|
|
31033
|
-
if (await
|
|
32169
|
+
const categoryPath = join23(skillsDir, entry.name);
|
|
32170
|
+
const skillPath = join23(categoryPath, skillName);
|
|
32171
|
+
if (await import_fs_extra14.pathExists(skillPath)) {
|
|
31034
32172
|
return { path: skillPath, category: entry.name };
|
|
31035
32173
|
}
|
|
31036
32174
|
}
|
|
@@ -31040,7 +32178,7 @@ class SkillsCustomizationScanner {
|
|
|
31040
32178
|
const files = [];
|
|
31041
32179
|
const entries = await readdir8(dirPath, { withFileTypes: true });
|
|
31042
32180
|
for (const entry of entries) {
|
|
31043
|
-
const fullPath =
|
|
32181
|
+
const fullPath = join23(dirPath, entry.name);
|
|
31044
32182
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31045
32183
|
continue;
|
|
31046
32184
|
}
|
|
@@ -31073,7 +32211,7 @@ class SkillsCustomizationScanner {
|
|
|
31073
32211
|
files.sort();
|
|
31074
32212
|
for (const file of files) {
|
|
31075
32213
|
const relativePath = relative6(dirPath, file);
|
|
31076
|
-
const content = await
|
|
32214
|
+
const content = await readFile14(file);
|
|
31077
32215
|
hash.update(relativePath);
|
|
31078
32216
|
hash.update(content);
|
|
31079
32217
|
}
|
|
@@ -31283,7 +32421,7 @@ class SkillsMigrator {
|
|
|
31283
32421
|
}
|
|
31284
32422
|
}
|
|
31285
32423
|
if (options.backup && !options.dryRun) {
|
|
31286
|
-
const claudeDir =
|
|
32424
|
+
const claudeDir = join24(currentSkillsDir, "..");
|
|
31287
32425
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
31288
32426
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
31289
32427
|
}
|
|
@@ -31335,14 +32473,14 @@ class SkillsMigrator {
|
|
|
31335
32473
|
const migrated = [];
|
|
31336
32474
|
const preserved = [];
|
|
31337
32475
|
const errors2 = [];
|
|
31338
|
-
const tempDir =
|
|
32476
|
+
const tempDir = join24(currentSkillsDir, "..", ".skills-migration-temp");
|
|
31339
32477
|
await mkdir8(tempDir, { recursive: true });
|
|
31340
32478
|
try {
|
|
31341
32479
|
for (const mapping of mappings) {
|
|
31342
32480
|
try {
|
|
31343
32481
|
const skillName = mapping.skillName;
|
|
31344
32482
|
const currentSkillPath = mapping.oldPath;
|
|
31345
|
-
if (!await
|
|
32483
|
+
if (!await import_fs_extra15.pathExists(currentSkillPath)) {
|
|
31346
32484
|
logger.warning(`Skill not found, skipping: ${skillName}`);
|
|
31347
32485
|
continue;
|
|
31348
32486
|
}
|
|
@@ -31356,9 +32494,9 @@ class SkillsMigrator {
|
|
|
31356
32494
|
}
|
|
31357
32495
|
}
|
|
31358
32496
|
const category = mapping.category;
|
|
31359
|
-
const targetPath = category ?
|
|
32497
|
+
const targetPath = category ? join24(tempDir, category, skillName) : join24(tempDir, skillName);
|
|
31360
32498
|
if (category) {
|
|
31361
|
-
await mkdir8(
|
|
32499
|
+
await mkdir8(join24(tempDir, category), { recursive: true });
|
|
31362
32500
|
}
|
|
31363
32501
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
31364
32502
|
migrated.push(skillName);
|
|
@@ -31392,8 +32530,8 @@ class SkillsMigrator {
|
|
|
31392
32530
|
await mkdir8(destDir, { recursive: true });
|
|
31393
32531
|
const entries = await readdir9(sourceDir, { withFileTypes: true });
|
|
31394
32532
|
for (const entry of entries) {
|
|
31395
|
-
const sourcePath =
|
|
31396
|
-
const destPath =
|
|
32533
|
+
const sourcePath = join24(sourceDir, entry.name);
|
|
32534
|
+
const destPath = join24(destDir, entry.name);
|
|
31397
32535
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31398
32536
|
continue;
|
|
31399
32537
|
}
|
|
@@ -31981,31 +33119,31 @@ class PromptsManager {
|
|
|
31981
33119
|
|
|
31982
33120
|
// src/services/file-operations/file-scanner.ts
|
|
31983
33121
|
init_logger();
|
|
31984
|
-
import { join as
|
|
31985
|
-
var
|
|
33122
|
+
import { join as join28, relative as relative7, resolve as resolve5 } from "node:path";
|
|
33123
|
+
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31986
33124
|
|
|
31987
33125
|
class FileScanner {
|
|
31988
33126
|
static async getFiles(dirPath, relativeTo) {
|
|
31989
33127
|
const basePath = relativeTo || dirPath;
|
|
31990
33128
|
const files = [];
|
|
31991
|
-
if (!await
|
|
33129
|
+
if (!await import_fs_extra16.pathExists(dirPath)) {
|
|
31992
33130
|
return files;
|
|
31993
33131
|
}
|
|
31994
33132
|
try {
|
|
31995
|
-
const entries = await
|
|
33133
|
+
const entries = await import_fs_extra16.readdir(dirPath, { encoding: "utf8" });
|
|
31996
33134
|
for (const entry of entries) {
|
|
31997
33135
|
if (SKIP_DIRS_ALL.includes(entry)) {
|
|
31998
33136
|
logger.debug(`Skipping directory: ${entry}`);
|
|
31999
33137
|
continue;
|
|
32000
33138
|
}
|
|
32001
|
-
const fullPath =
|
|
33139
|
+
const fullPath = join28(dirPath, entry);
|
|
32002
33140
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
32003
33141
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
32004
33142
|
continue;
|
|
32005
33143
|
}
|
|
32006
33144
|
let stats;
|
|
32007
33145
|
try {
|
|
32008
|
-
stats = await
|
|
33146
|
+
stats = await import_fs_extra16.lstat(fullPath);
|
|
32009
33147
|
} catch (error) {
|
|
32010
33148
|
if (error instanceof Error && "code" in error && (error.code === "EACCES" || error.code === "EPERM")) {
|
|
32011
33149
|
logger.warning(`Skipping inaccessible path: ${entry}`);
|
|
@@ -32033,8 +33171,8 @@ class FileScanner {
|
|
|
32033
33171
|
return files;
|
|
32034
33172
|
}
|
|
32035
33173
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
32036
|
-
const destSubDir =
|
|
32037
|
-
const sourceSubDir =
|
|
33174
|
+
const destSubDir = join28(destDir, subPath);
|
|
33175
|
+
const sourceSubDir = join28(sourceDir, subPath);
|
|
32038
33176
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
32039
33177
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
32040
33178
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -32044,7 +33182,7 @@ class FileScanner {
|
|
|
32044
33182
|
const sourceFiles = await FileScanner.getFiles(sourceSubDir, sourceDir);
|
|
32045
33183
|
logger.debug(`findCustomFiles - destFiles count: ${destFiles.length}`);
|
|
32046
33184
|
logger.debug(`findCustomFiles - sourceFiles count: ${sourceFiles.length}`);
|
|
32047
|
-
const sourceExists = await
|
|
33185
|
+
const sourceExists = await import_fs_extra16.pathExists(sourceSubDir);
|
|
32048
33186
|
if (sourceExists && sourceFiles.length === 0 && destFiles.length > 100) {
|
|
32049
33187
|
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
33188
|
return [];
|
|
@@ -32072,10 +33210,10 @@ class FileScanner {
|
|
|
32072
33210
|
}
|
|
32073
33211
|
|
|
32074
33212
|
// src/services/transformers/commands-prefix.ts
|
|
32075
|
-
import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as
|
|
32076
|
-
import { join as
|
|
33213
|
+
import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as stat5 } from "node:fs/promises";
|
|
33214
|
+
import { join as join29 } from "node:path";
|
|
32077
33215
|
init_logger();
|
|
32078
|
-
var
|
|
33216
|
+
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
32079
33217
|
function stripWindowsDrivePrefix(path9) {
|
|
32080
33218
|
if (path9.length >= 2 && /[a-zA-Z]/.test(path9[0]) && path9[1] === ":") {
|
|
32081
33219
|
return path9.slice(2);
|
|
@@ -32114,14 +33252,14 @@ function validatePath4(path9, paramName) {
|
|
|
32114
33252
|
class CommandsPrefix {
|
|
32115
33253
|
static async applyPrefix(extractDir) {
|
|
32116
33254
|
validatePath4(extractDir, "extractDir");
|
|
32117
|
-
const commandsDir =
|
|
32118
|
-
if (!await
|
|
33255
|
+
const commandsDir = join29(extractDir, ".claude", "commands");
|
|
33256
|
+
if (!await import_fs_extra17.pathExists(commandsDir)) {
|
|
32119
33257
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
32120
33258
|
return;
|
|
32121
33259
|
}
|
|
32122
33260
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
32123
|
-
const backupDir =
|
|
32124
|
-
const tempDir =
|
|
33261
|
+
const backupDir = join29(extractDir, ".commands-backup");
|
|
33262
|
+
const tempDir = join29(extractDir, ".commands-prefix-temp");
|
|
32125
33263
|
try {
|
|
32126
33264
|
const entries = await readdir11(commandsDir);
|
|
32127
33265
|
if (entries.length === 0) {
|
|
@@ -32129,28 +33267,28 @@ class CommandsPrefix {
|
|
|
32129
33267
|
return;
|
|
32130
33268
|
}
|
|
32131
33269
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
32132
|
-
const ckDir2 =
|
|
32133
|
-
const ckStat = await
|
|
33270
|
+
const ckDir2 = join29(commandsDir, "ck");
|
|
33271
|
+
const ckStat = await stat5(ckDir2);
|
|
32134
33272
|
if (ckStat.isDirectory()) {
|
|
32135
33273
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
32136
33274
|
return;
|
|
32137
33275
|
}
|
|
32138
33276
|
}
|
|
32139
|
-
await
|
|
33277
|
+
await import_fs_extra17.copy(commandsDir, backupDir);
|
|
32140
33278
|
logger.verbose("Created backup of commands directory");
|
|
32141
33279
|
await mkdir10(tempDir, { recursive: true });
|
|
32142
|
-
const ckDir =
|
|
33280
|
+
const ckDir = join29(tempDir, "ck");
|
|
32143
33281
|
await mkdir10(ckDir, { recursive: true });
|
|
32144
33282
|
let processedCount = 0;
|
|
32145
33283
|
for (const entry of entries) {
|
|
32146
|
-
const sourcePath =
|
|
33284
|
+
const sourcePath = join29(commandsDir, entry);
|
|
32147
33285
|
const stats = await lstat3(sourcePath);
|
|
32148
33286
|
if (stats.isSymbolicLink()) {
|
|
32149
33287
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
32150
33288
|
continue;
|
|
32151
33289
|
}
|
|
32152
|
-
const destPath =
|
|
32153
|
-
await
|
|
33290
|
+
const destPath = join29(ckDir, entry);
|
|
33291
|
+
await import_fs_extra17.copy(sourcePath, destPath, {
|
|
32154
33292
|
overwrite: false,
|
|
32155
33293
|
errorOnExist: true
|
|
32156
33294
|
});
|
|
@@ -32159,35 +33297,35 @@ class CommandsPrefix {
|
|
|
32159
33297
|
}
|
|
32160
33298
|
if (processedCount === 0) {
|
|
32161
33299
|
logger.warning("No files to move (all were symlinks or invalid)");
|
|
32162
|
-
await
|
|
32163
|
-
await
|
|
33300
|
+
await import_fs_extra17.remove(backupDir);
|
|
33301
|
+
await import_fs_extra17.remove(tempDir);
|
|
32164
33302
|
return;
|
|
32165
33303
|
}
|
|
32166
|
-
await
|
|
32167
|
-
await
|
|
32168
|
-
await
|
|
33304
|
+
await import_fs_extra17.remove(commandsDir);
|
|
33305
|
+
await import_fs_extra17.move(tempDir, commandsDir);
|
|
33306
|
+
await import_fs_extra17.remove(backupDir);
|
|
32169
33307
|
logger.success("Successfully applied /ck: prefix to all commands");
|
|
32170
33308
|
} catch (error) {
|
|
32171
|
-
if (await
|
|
33309
|
+
if (await import_fs_extra17.pathExists(backupDir)) {
|
|
32172
33310
|
try {
|
|
32173
|
-
await
|
|
32174
|
-
await
|
|
33311
|
+
await import_fs_extra17.remove(commandsDir).catch(() => {});
|
|
33312
|
+
await import_fs_extra17.move(backupDir, commandsDir);
|
|
32175
33313
|
logger.info("Restored original commands directory from backup");
|
|
32176
33314
|
} catch (rollbackError) {
|
|
32177
33315
|
logger.error(`Rollback failed: ${rollbackError}`);
|
|
32178
33316
|
}
|
|
32179
33317
|
}
|
|
32180
|
-
if (await
|
|
32181
|
-
await
|
|
33318
|
+
if (await import_fs_extra17.pathExists(tempDir)) {
|
|
33319
|
+
await import_fs_extra17.remove(tempDir).catch(() => {});
|
|
32182
33320
|
}
|
|
32183
33321
|
logger.error("Failed to apply /ck: prefix to commands");
|
|
32184
33322
|
throw error;
|
|
32185
33323
|
} finally {
|
|
32186
|
-
if (await
|
|
32187
|
-
await
|
|
33324
|
+
if (await import_fs_extra17.pathExists(backupDir)) {
|
|
33325
|
+
await import_fs_extra17.remove(backupDir).catch(() => {});
|
|
32188
33326
|
}
|
|
32189
|
-
if (await
|
|
32190
|
-
await
|
|
33327
|
+
if (await import_fs_extra17.pathExists(tempDir)) {
|
|
33328
|
+
await import_fs_extra17.remove(tempDir).catch(() => {});
|
|
32191
33329
|
}
|
|
32192
33330
|
}
|
|
32193
33331
|
}
|
|
@@ -32197,15 +33335,15 @@ class CommandsPrefix {
|
|
|
32197
33335
|
static async cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
32198
33336
|
const { dryRun = false, forceOverwrite = false } = options;
|
|
32199
33337
|
validatePath4(targetDir, "targetDir");
|
|
32200
|
-
const claudeDir = isGlobal ? targetDir :
|
|
32201
|
-
const commandsDir =
|
|
33338
|
+
const claudeDir = isGlobal ? targetDir : join29(targetDir, ".claude");
|
|
33339
|
+
const commandsDir = join29(claudeDir, "commands");
|
|
32202
33340
|
const result = {
|
|
32203
33341
|
results: [],
|
|
32204
33342
|
deletedCount: 0,
|
|
32205
33343
|
preservedCount: 0,
|
|
32206
33344
|
wasDryRun: dryRun
|
|
32207
33345
|
};
|
|
32208
|
-
if (!await
|
|
33346
|
+
if (!await import_fs_extra17.pathExists(commandsDir)) {
|
|
32209
33347
|
logger.verbose(`Commands directory does not exist: ${commandsDir}`);
|
|
32210
33348
|
return result;
|
|
32211
33349
|
}
|
|
@@ -32226,7 +33364,7 @@ class CommandsPrefix {
|
|
|
32226
33364
|
return result;
|
|
32227
33365
|
}
|
|
32228
33366
|
for (const entry of entries) {
|
|
32229
|
-
const entryPath =
|
|
33367
|
+
const entryPath = join29(commandsDir, entry);
|
|
32230
33368
|
const stats = await lstat3(entryPath);
|
|
32231
33369
|
if (stats.isSymbolicLink()) {
|
|
32232
33370
|
logger.warning(`Skipping symlink: ${entry}`);
|
|
@@ -32252,7 +33390,7 @@ class CommandsPrefix {
|
|
|
32252
33390
|
action: "delete"
|
|
32253
33391
|
});
|
|
32254
33392
|
if (!dryRun) {
|
|
32255
|
-
await
|
|
33393
|
+
await import_fs_extra17.remove(file);
|
|
32256
33394
|
logger.verbose(`Deleted CK file: ${relativePath}`);
|
|
32257
33395
|
}
|
|
32258
33396
|
result.deletedCount++;
|
|
@@ -32265,7 +33403,7 @@ class CommandsPrefix {
|
|
|
32265
33403
|
reason: "force overwrite"
|
|
32266
33404
|
});
|
|
32267
33405
|
if (!dryRun) {
|
|
32268
|
-
await
|
|
33406
|
+
await import_fs_extra17.remove(file);
|
|
32269
33407
|
logger.verbose(`Force-deleted modified file: ${relativePath}`);
|
|
32270
33408
|
}
|
|
32271
33409
|
result.deletedCount++;
|
|
@@ -32289,7 +33427,7 @@ class CommandsPrefix {
|
|
|
32289
33427
|
reason: "force overwrite"
|
|
32290
33428
|
});
|
|
32291
33429
|
if (!dryRun) {
|
|
32292
|
-
await
|
|
33430
|
+
await import_fs_extra17.remove(file);
|
|
32293
33431
|
logger.verbose(`Force-deleted user file: ${relativePath}`);
|
|
32294
33432
|
}
|
|
32295
33433
|
result.deletedCount++;
|
|
@@ -32307,7 +33445,7 @@ class CommandsPrefix {
|
|
|
32307
33445
|
}
|
|
32308
33446
|
}
|
|
32309
33447
|
if (canDeleteDir && !dryRun) {
|
|
32310
|
-
await
|
|
33448
|
+
await import_fs_extra17.remove(entryPath);
|
|
32311
33449
|
logger.verbose(`Removed directory: ${entry}`);
|
|
32312
33450
|
}
|
|
32313
33451
|
} else {
|
|
@@ -32320,7 +33458,7 @@ class CommandsPrefix {
|
|
|
32320
33458
|
action: "delete"
|
|
32321
33459
|
});
|
|
32322
33460
|
if (!dryRun) {
|
|
32323
|
-
await
|
|
33461
|
+
await import_fs_extra17.remove(entryPath);
|
|
32324
33462
|
logger.verbose(`Deleted CK file: ${entry}`);
|
|
32325
33463
|
}
|
|
32326
33464
|
result.deletedCount++;
|
|
@@ -32333,7 +33471,7 @@ class CommandsPrefix {
|
|
|
32333
33471
|
reason: "force overwrite"
|
|
32334
33472
|
});
|
|
32335
33473
|
if (!dryRun) {
|
|
32336
|
-
await
|
|
33474
|
+
await import_fs_extra17.remove(entryPath);
|
|
32337
33475
|
logger.verbose(`Force-deleted modified file: ${entry}`);
|
|
32338
33476
|
}
|
|
32339
33477
|
result.deletedCount++;
|
|
@@ -32356,7 +33494,7 @@ class CommandsPrefix {
|
|
|
32356
33494
|
reason: "force overwrite"
|
|
32357
33495
|
});
|
|
32358
33496
|
if (!dryRun) {
|
|
32359
|
-
await
|
|
33497
|
+
await import_fs_extra17.remove(entryPath);
|
|
32360
33498
|
logger.verbose(`Force-deleted user file: ${entry}`);
|
|
32361
33499
|
}
|
|
32362
33500
|
result.deletedCount++;
|
|
@@ -32392,7 +33530,7 @@ class CommandsPrefix {
|
|
|
32392
33530
|
const files = [];
|
|
32393
33531
|
const entries = await readdir11(dir);
|
|
32394
33532
|
for (const entry of entries) {
|
|
32395
|
-
const fullPath =
|
|
33533
|
+
const fullPath = join29(dir, entry);
|
|
32396
33534
|
const stats = await lstat3(fullPath);
|
|
32397
33535
|
if (stats.isSymbolicLink()) {
|
|
32398
33536
|
continue;
|
|
@@ -32410,9 +33548,9 @@ class CommandsPrefix {
|
|
|
32410
33548
|
// src/services/transformers/folder-path-transformer.ts
|
|
32411
33549
|
init_logger();
|
|
32412
33550
|
init_types2();
|
|
32413
|
-
var
|
|
32414
|
-
import { readFile as
|
|
32415
|
-
import { join as
|
|
33551
|
+
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
33552
|
+
import { readFile as readFile16, readdir as readdir12, rename as rename3, writeFile as writeFile14 } from "node:fs/promises";
|
|
33553
|
+
import { join as join30, relative as relative8 } from "node:path";
|
|
32416
33554
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
32417
33555
|
".md",
|
|
32418
33556
|
".txt",
|
|
@@ -32458,34 +33596,34 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
32458
33596
|
}
|
|
32459
33597
|
const dirsToRename = [];
|
|
32460
33598
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
32461
|
-
const docsPath =
|
|
32462
|
-
if (await
|
|
33599
|
+
const docsPath = join30(extractDir, DEFAULT_FOLDERS.docs);
|
|
33600
|
+
if (await import_fs_extra18.pathExists(docsPath)) {
|
|
32463
33601
|
dirsToRename.push({
|
|
32464
33602
|
from: docsPath,
|
|
32465
|
-
to:
|
|
33603
|
+
to: join30(extractDir, folders.docs)
|
|
32466
33604
|
});
|
|
32467
33605
|
}
|
|
32468
|
-
const claudeDocsPath =
|
|
32469
|
-
if (await
|
|
33606
|
+
const claudeDocsPath = join30(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
33607
|
+
if (await import_fs_extra18.pathExists(claudeDocsPath)) {
|
|
32470
33608
|
dirsToRename.push({
|
|
32471
33609
|
from: claudeDocsPath,
|
|
32472
|
-
to:
|
|
33610
|
+
to: join30(extractDir, ".claude", folders.docs)
|
|
32473
33611
|
});
|
|
32474
33612
|
}
|
|
32475
33613
|
}
|
|
32476
33614
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
32477
|
-
const plansPath =
|
|
32478
|
-
if (await
|
|
33615
|
+
const plansPath = join30(extractDir, DEFAULT_FOLDERS.plans);
|
|
33616
|
+
if (await import_fs_extra18.pathExists(plansPath)) {
|
|
32479
33617
|
dirsToRename.push({
|
|
32480
33618
|
from: plansPath,
|
|
32481
|
-
to:
|
|
33619
|
+
to: join30(extractDir, folders.plans)
|
|
32482
33620
|
});
|
|
32483
33621
|
}
|
|
32484
|
-
const claudePlansPath =
|
|
32485
|
-
if (await
|
|
33622
|
+
const claudePlansPath = join30(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
33623
|
+
if (await import_fs_extra18.pathExists(claudePlansPath)) {
|
|
32486
33624
|
dirsToRename.push({
|
|
32487
33625
|
from: claudePlansPath,
|
|
32488
|
-
to:
|
|
33626
|
+
to: join30(extractDir, ".claude", folders.plans)
|
|
32489
33627
|
});
|
|
32490
33628
|
}
|
|
32491
33629
|
}
|
|
@@ -32522,7 +33660,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32522
33660
|
let replacementsCount = 0;
|
|
32523
33661
|
const entries = await readdir12(dir, { withFileTypes: true });
|
|
32524
33662
|
for (const entry of entries) {
|
|
32525
|
-
const fullPath =
|
|
33663
|
+
const fullPath = join30(dir, entry.name);
|
|
32526
33664
|
if (entry.isDirectory()) {
|
|
32527
33665
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
32528
33666
|
continue;
|
|
@@ -32535,7 +33673,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32535
33673
|
if (!shouldTransform)
|
|
32536
33674
|
continue;
|
|
32537
33675
|
try {
|
|
32538
|
-
const content = await
|
|
33676
|
+
const content = await readFile16(fullPath, "utf-8");
|
|
32539
33677
|
let newContent = content;
|
|
32540
33678
|
let changeCount = 0;
|
|
32541
33679
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -32551,7 +33689,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32551
33689
|
if (options.dryRun) {
|
|
32552
33690
|
logger.debug(`[dry-run] Would update ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
32553
33691
|
} else {
|
|
32554
|
-
await
|
|
33692
|
+
await writeFile14(fullPath, newContent, "utf-8");
|
|
32555
33693
|
logger.debug(`Updated ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
32556
33694
|
}
|
|
32557
33695
|
filesChanged++;
|
|
@@ -32631,9 +33769,9 @@ function validateFolderName(name2) {
|
|
|
32631
33769
|
|
|
32632
33770
|
// src/services/transformers/global-path-transformer.ts
|
|
32633
33771
|
init_logger();
|
|
32634
|
-
import { readFile as
|
|
33772
|
+
import { readFile as readFile17, readdir as readdir13, writeFile as writeFile15 } from "node:fs/promises";
|
|
32635
33773
|
import { platform as platform9 } from "node:os";
|
|
32636
|
-
import { extname, join as
|
|
33774
|
+
import { extname, join as join31 } from "node:path";
|
|
32637
33775
|
var IS_WINDOWS2 = platform9() === "win32";
|
|
32638
33776
|
var HOME_PREFIX = IS_WINDOWS2 ? "%USERPROFILE%" : "$HOME";
|
|
32639
33777
|
function getHomeDirPrefix() {
|
|
@@ -32725,7 +33863,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
32725
33863
|
async function processDirectory(dir) {
|
|
32726
33864
|
const entries = await readdir13(dir, { withFileTypes: true });
|
|
32727
33865
|
for (const entry of entries) {
|
|
32728
|
-
const fullPath =
|
|
33866
|
+
const fullPath = join31(dir, entry.name);
|
|
32729
33867
|
if (entry.isDirectory()) {
|
|
32730
33868
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
32731
33869
|
continue;
|
|
@@ -32733,10 +33871,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
32733
33871
|
await processDirectory(fullPath);
|
|
32734
33872
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
32735
33873
|
try {
|
|
32736
|
-
const content = await
|
|
33874
|
+
const content = await readFile17(fullPath, "utf-8");
|
|
32737
33875
|
const { transformed, changes } = transformContent(content);
|
|
32738
33876
|
if (changes > 0) {
|
|
32739
|
-
await
|
|
33877
|
+
await writeFile15(fullPath, transformed, "utf-8");
|
|
32740
33878
|
filesTransformed++;
|
|
32741
33879
|
totalChanges += changes;
|
|
32742
33880
|
if (options.verbose) {
|
|
@@ -32767,7 +33905,7 @@ init_environment();
|
|
|
32767
33905
|
init_logger();
|
|
32768
33906
|
init_output_manager();
|
|
32769
33907
|
init_types2();
|
|
32770
|
-
var
|
|
33908
|
+
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
32771
33909
|
async function initCommand(options) {
|
|
32772
33910
|
const prompts = new PromptsManager;
|
|
32773
33911
|
prompts.intro("\uD83D\uDD27 ClaudeKit - Initialize/Update Project");
|
|
@@ -32786,8 +33924,8 @@ async function initCommand(options) {
|
|
|
32786
33924
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
32787
33925
|
const cwdResolved = resolve6(process.cwd());
|
|
32788
33926
|
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve6(globalKitDir, "..");
|
|
32789
|
-
const localSettingsPath =
|
|
32790
|
-
if (!isInGlobalDir && await
|
|
33927
|
+
const localSettingsPath = join32(process.cwd(), ".claude", "settings.json");
|
|
33928
|
+
if (!isInGlobalDir && await import_fs_extra19.pathExists(localSettingsPath)) {
|
|
32791
33929
|
if (isNonInteractive2) {
|
|
32792
33930
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
32793
33931
|
logger.warning("Consider removing local installation: rm -rf .claude");
|
|
@@ -32798,9 +33936,9 @@ async function initCommand(options) {
|
|
|
32798
33936
|
return;
|
|
32799
33937
|
}
|
|
32800
33938
|
if (choice === "remove") {
|
|
32801
|
-
const localClaudeDir =
|
|
33939
|
+
const localClaudeDir = join32(process.cwd(), ".claude");
|
|
32802
33940
|
try {
|
|
32803
|
-
await
|
|
33941
|
+
await import_fs_extra19.remove(localClaudeDir);
|
|
32804
33942
|
logger.success("Removed local .claude/ directory");
|
|
32805
33943
|
} catch (error) {
|
|
32806
33944
|
logger.error(`Failed to remove local installation: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -32844,7 +33982,7 @@ async function initCommand(options) {
|
|
|
32844
33982
|
}
|
|
32845
33983
|
const resolvedDir = resolve6(targetDir);
|
|
32846
33984
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32847
|
-
if (!await
|
|
33985
|
+
if (!await import_fs_extra19.pathExists(resolvedDir)) {
|
|
32848
33986
|
if (validOptions.global) {
|
|
32849
33987
|
const { mkdir: mkdir11 } = await import("node:fs/promises");
|
|
32850
33988
|
await mkdir11(resolvedDir, { recursive: true });
|
|
@@ -32857,7 +33995,7 @@ async function initCommand(options) {
|
|
|
32857
33995
|
}
|
|
32858
33996
|
if (validOptions.fresh) {
|
|
32859
33997
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
32860
|
-
const claudeDir2 = prefix ?
|
|
33998
|
+
const claudeDir2 = prefix ? join32(resolvedDir, prefix) : resolvedDir;
|
|
32861
33999
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
32862
34000
|
if (!canProceed) {
|
|
32863
34001
|
return;
|
|
@@ -32885,7 +34023,7 @@ async function initCommand(options) {
|
|
|
32885
34023
|
logger.info("Fetching available versions...");
|
|
32886
34024
|
let currentVersion = null;
|
|
32887
34025
|
try {
|
|
32888
|
-
const metadataPath = validOptions.global ?
|
|
34026
|
+
const metadataPath = validOptions.global ? join32(PathResolver.getGlobalKitDir(), "metadata.json") : join32(resolvedDir, ".claude", "metadata.json");
|
|
32889
34027
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
32890
34028
|
currentVersion = metadata?.version || null;
|
|
32891
34029
|
if (currentVersion) {
|
|
@@ -33010,9 +34148,9 @@ async function initCommand(options) {
|
|
|
33010
34148
|
}
|
|
33011
34149
|
}
|
|
33012
34150
|
if (!validOptions.fresh) {
|
|
33013
|
-
const newSkillsDir =
|
|
34151
|
+
const newSkillsDir = join32(extractDir, ".claude", "skills");
|
|
33014
34152
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
33015
|
-
if (await
|
|
34153
|
+
if (await import_fs_extra19.pathExists(newSkillsDir) && await import_fs_extra19.pathExists(currentSkillsDir)) {
|
|
33016
34154
|
logger.info("Checking for skills directory migration...");
|
|
33017
34155
|
const migrationDetection = await SkillsMigrationDetector.detectMigration(newSkillsDir, currentSkillsDir);
|
|
33018
34156
|
if (migrationDetection.status === "recommended" || migrationDetection.status === "required") {
|
|
@@ -33035,7 +34173,7 @@ async function initCommand(options) {
|
|
|
33035
34173
|
let customClaudeFiles = [];
|
|
33036
34174
|
if (!validOptions.fresh) {
|
|
33037
34175
|
logger.info("Scanning for custom .claude files...");
|
|
33038
|
-
const scanSourceDir = validOptions.global ?
|
|
34176
|
+
const scanSourceDir = validOptions.global ? join32(extractDir, ".claude") : extractDir;
|
|
33039
34177
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
33040
34178
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
33041
34179
|
} else {
|
|
@@ -33070,9 +34208,12 @@ async function initCommand(options) {
|
|
|
33070
34208
|
}
|
|
33071
34209
|
merger.setGlobalFlag(validOptions.global);
|
|
33072
34210
|
merger.setForceOverwriteSettings(validOptions.forceOverwriteSettings);
|
|
33073
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
34211
|
+
const claudeDir = validOptions.global ? resolvedDir : join32(resolvedDir, ".claude");
|
|
33074
34212
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
33075
|
-
if (
|
|
34213
|
+
if (releaseManifest) {
|
|
34214
|
+
merger.setManifest(releaseManifest);
|
|
34215
|
+
}
|
|
34216
|
+
if (!validOptions.fresh && await import_fs_extra19.pathExists(claudeDir)) {
|
|
33076
34217
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
33077
34218
|
if (legacyDetection.isLegacy && releaseManifest) {
|
|
33078
34219
|
logger.info("Legacy installation detected - migrating to ownership tracking...");
|
|
@@ -33092,7 +34233,7 @@ async function initCommand(options) {
|
|
|
33092
34233
|
return;
|
|
33093
34234
|
}
|
|
33094
34235
|
}
|
|
33095
|
-
const sourceDir = validOptions.global ?
|
|
34236
|
+
const sourceDir = validOptions.global ? join32(extractDir, ".claude") : extractDir;
|
|
33096
34237
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
33097
34238
|
const manifestWriter = new ManifestWriter;
|
|
33098
34239
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -33101,7 +34242,7 @@ async function initCommand(options) {
|
|
|
33101
34242
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
33102
34243
|
continue;
|
|
33103
34244
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
33104
|
-
const filePath =
|
|
34245
|
+
const filePath = join32(claudeDir, relativePath);
|
|
33105
34246
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
33106
34247
|
const ownership = manifestEntry ? "ck" : "user";
|
|
33107
34248
|
filesToTrack.push({
|
|
@@ -33120,13 +34261,13 @@ async function initCommand(options) {
|
|
|
33120
34261
|
}
|
|
33121
34262
|
});
|
|
33122
34263
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
33123
|
-
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
34264
|
+
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local", kit);
|
|
33124
34265
|
if (validOptions.global) {
|
|
33125
|
-
const claudeMdSource =
|
|
33126
|
-
const claudeMdDest =
|
|
33127
|
-
if (await
|
|
33128
|
-
if (!await
|
|
33129
|
-
await
|
|
34266
|
+
const claudeMdSource = join32(extractDir, "CLAUDE.md");
|
|
34267
|
+
const claudeMdDest = join32(resolvedDir, "CLAUDE.md");
|
|
34268
|
+
if (await import_fs_extra19.pathExists(claudeMdSource)) {
|
|
34269
|
+
if (!await import_fs_extra19.pathExists(claudeMdDest)) {
|
|
34270
|
+
await import_fs_extra19.copy(claudeMdSource, claudeMdDest);
|
|
33130
34271
|
logger.success("Copied CLAUDE.md to global directory");
|
|
33131
34272
|
} else {
|
|
33132
34273
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -33165,8 +34306,8 @@ async function initCommand(options) {
|
|
|
33165
34306
|
}
|
|
33166
34307
|
}
|
|
33167
34308
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
33168
|
-
const envPath =
|
|
33169
|
-
if (!await
|
|
34309
|
+
const envPath = join32(claudeDir, ".env");
|
|
34310
|
+
if (!await import_fs_extra19.pathExists(envPath)) {
|
|
33170
34311
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
33171
34312
|
if (shouldSetup) {
|
|
33172
34313
|
await runSetupWizard({
|
|
@@ -33196,13 +34337,13 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
33196
34337
|
}
|
|
33197
34338
|
|
|
33198
34339
|
// src/commands/new.ts
|
|
33199
|
-
import { join as
|
|
34340
|
+
import { join as join33, resolve as resolve7 } from "node:path";
|
|
33200
34341
|
init_package_installer();
|
|
33201
34342
|
init_environment();
|
|
33202
34343
|
init_logger();
|
|
33203
34344
|
init_output_manager();
|
|
33204
34345
|
init_types2();
|
|
33205
|
-
var
|
|
34346
|
+
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
33206
34347
|
async function newCommand(options) {
|
|
33207
34348
|
const prompts = new PromptsManager;
|
|
33208
34349
|
prompts.intro("\uD83D\uDE80 ClaudeKit - Create New Project");
|
|
@@ -33229,8 +34370,8 @@ async function newCommand(options) {
|
|
|
33229
34370
|
}
|
|
33230
34371
|
const resolvedDir = resolve7(targetDir);
|
|
33231
34372
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
33232
|
-
if (await
|
|
33233
|
-
const files = await
|
|
34373
|
+
if (await import_fs_extra20.pathExists(resolvedDir)) {
|
|
34374
|
+
const files = await import_fs_extra20.readdir(resolvedDir);
|
|
33234
34375
|
const isEmpty = files.length === 0;
|
|
33235
34376
|
if (!isEmpty) {
|
|
33236
34377
|
if (isNonInteractive2) {
|
|
@@ -33377,7 +34518,7 @@ async function newCommand(options) {
|
|
|
33377
34518
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
33378
34519
|
}
|
|
33379
34520
|
await merger.merge(extractDir, resolvedDir, true);
|
|
33380
|
-
const claudeDir =
|
|
34521
|
+
const claudeDir = join33(resolvedDir, ".claude");
|
|
33381
34522
|
const manifestWriter = new ManifestWriter;
|
|
33382
34523
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
33383
34524
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -33386,7 +34527,7 @@ async function newCommand(options) {
|
|
|
33386
34527
|
if (!installedPath.startsWith(".claude/"))
|
|
33387
34528
|
continue;
|
|
33388
34529
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
33389
|
-
const filePath =
|
|
34530
|
+
const filePath = join33(claudeDir, relativePath);
|
|
33390
34531
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
33391
34532
|
const ownership = manifestEntry ? "ck" : "user";
|
|
33392
34533
|
filesToTrack.push({
|
|
@@ -33439,10 +34580,10 @@ async function newCommand(options) {
|
|
|
33439
34580
|
|
|
33440
34581
|
// src/commands/uninstall.ts
|
|
33441
34582
|
import { readdirSync, rmSync } from "node:fs";
|
|
33442
|
-
import { dirname as dirname7, join as
|
|
34583
|
+
import { dirname as dirname7, join as join34 } from "node:path";
|
|
33443
34584
|
init_logger();
|
|
33444
34585
|
init_types2();
|
|
33445
|
-
var
|
|
34586
|
+
var import_fs_extra21 = __toESM(require_lib(), 1);
|
|
33446
34587
|
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
33447
34588
|
async function detectInstallations() {
|
|
33448
34589
|
const installations = [];
|
|
@@ -33451,14 +34592,14 @@ async function detectInstallations() {
|
|
|
33451
34592
|
installations.push({
|
|
33452
34593
|
type: "local",
|
|
33453
34594
|
path: setup.project.path,
|
|
33454
|
-
exists: await
|
|
34595
|
+
exists: await import_fs_extra21.pathExists(setup.project.path)
|
|
33455
34596
|
});
|
|
33456
34597
|
}
|
|
33457
34598
|
if (setup.global.path && setup.global.metadata) {
|
|
33458
34599
|
installations.push({
|
|
33459
34600
|
type: "global",
|
|
33460
34601
|
path: setup.global.path,
|
|
33461
|
-
exists: await
|
|
34602
|
+
exists: await import_fs_extra21.pathExists(setup.global.path)
|
|
33462
34603
|
});
|
|
33463
34604
|
}
|
|
33464
34605
|
return installations.filter((i) => i.exists);
|
|
@@ -33491,14 +34632,26 @@ async function promptScope(installations) {
|
|
|
33491
34632
|
}
|
|
33492
34633
|
return selected;
|
|
33493
34634
|
}
|
|
33494
|
-
async function confirmUninstall(scope) {
|
|
34635
|
+
async function confirmUninstall(scope, kitLabel = "") {
|
|
33495
34636
|
const scopeText = scope === "all" ? "all ClaudeKit installations" : scope === "local" ? "local ClaudeKit installation" : "global ClaudeKit installation";
|
|
33496
34637
|
const confirmed = await se({
|
|
33497
|
-
message: `Continue with uninstalling ${scopeText}?`,
|
|
34638
|
+
message: `Continue with uninstalling ${scopeText}${kitLabel}?`,
|
|
33498
34639
|
initialValue: false
|
|
33499
34640
|
});
|
|
33500
34641
|
return confirmed === true;
|
|
33501
34642
|
}
|
|
34643
|
+
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
34644
|
+
if (ownership === "ck") {
|
|
34645
|
+
return { action: "delete", reason: deleteReason };
|
|
34646
|
+
}
|
|
34647
|
+
if (ownership === "ck-modified") {
|
|
34648
|
+
if (forceOverwrite) {
|
|
34649
|
+
return { action: "delete", reason: "force overwrite" };
|
|
34650
|
+
}
|
|
34651
|
+
return { action: "preserve", reason: "modified by user" };
|
|
34652
|
+
}
|
|
34653
|
+
return { action: "preserve", reason: "user-created" };
|
|
34654
|
+
}
|
|
33502
34655
|
async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
33503
34656
|
let cleaned = 0;
|
|
33504
34657
|
let currentDir = dirname7(filePath);
|
|
@@ -33519,33 +34672,56 @@ async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
|
33519
34672
|
}
|
|
33520
34673
|
return cleaned;
|
|
33521
34674
|
}
|
|
33522
|
-
async function analyzeInstallation(installation, forceOverwrite) {
|
|
33523
|
-
const result = {
|
|
34675
|
+
async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
34676
|
+
const result = {
|
|
34677
|
+
toDelete: [],
|
|
34678
|
+
toPreserve: [],
|
|
34679
|
+
remainingKits: []
|
|
34680
|
+
};
|
|
33524
34681
|
const metadata = await ManifestWriter.readManifest(installation.path);
|
|
34682
|
+
const uninstallManifest = await ManifestWriter.getUninstallManifest(installation.path, kit);
|
|
34683
|
+
result.remainingKits = uninstallManifest.remainingKits;
|
|
34684
|
+
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
34685
|
+
const kitFiles = metadata.kits[kit].files || [];
|
|
34686
|
+
for (const trackedFile of kitFiles) {
|
|
34687
|
+
const filePath = join34(installation.path, trackedFile.path);
|
|
34688
|
+
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
34689
|
+
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
34690
|
+
continue;
|
|
34691
|
+
}
|
|
34692
|
+
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
34693
|
+
if (!ownershipResult.exists)
|
|
34694
|
+
continue;
|
|
34695
|
+
const classification = classifyFileByOwnership(ownershipResult.ownership, forceOverwrite, `${kit} kit (pristine)`);
|
|
34696
|
+
if (classification.action === "delete") {
|
|
34697
|
+
result.toDelete.push({ path: trackedFile.path, reason: classification.reason });
|
|
34698
|
+
} else {
|
|
34699
|
+
result.toPreserve.push({ path: trackedFile.path, reason: classification.reason });
|
|
34700
|
+
}
|
|
34701
|
+
}
|
|
34702
|
+
if (result.remainingKits.length === 0) {
|
|
34703
|
+
result.toDelete.push({ path: "metadata.json", reason: "metadata file" });
|
|
34704
|
+
}
|
|
34705
|
+
return result;
|
|
34706
|
+
}
|
|
33525
34707
|
if (!metadata?.files || metadata.files.length === 0) {
|
|
33526
|
-
const
|
|
33527
|
-
|
|
33528
|
-
if (!filesToPreserve.includes(item)) {
|
|
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 =
|
|
34715
|
+
for (const trackedFile of metadata.files || []) {
|
|
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
|
-
|
|
33540
|
-
|
|
33541
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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 =
|
|
33594
|
-
if (await
|
|
33595
|
-
await
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
35043
|
+
version: "3.11.0",
|
|
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
|
|
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
|
|
34143
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 ?
|
|
35904
|
+
return global3 ? join36(testHome, ".config", "claude") : join36(testHome, ".claudekit");
|
|
34695
35905
|
}
|
|
34696
35906
|
if (!global3) {
|
|
34697
|
-
return
|
|
35907
|
+
return join36(homedir5(), ".claudekit");
|
|
34698
35908
|
}
|
|
34699
35909
|
const os2 = platform10();
|
|
34700
35910
|
if (os2 === "win32") {
|
|
34701
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
34702
|
-
return
|
|
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
|
|
35916
|
+
return join36(xdgConfigHome, "claude");
|
|
34707
35917
|
}
|
|
34708
|
-
return
|
|
35918
|
+
return join36(homedir5(), ".config", "claude");
|
|
34709
35919
|
}
|
|
34710
35920
|
static getConfigFile(global3 = false) {
|
|
34711
|
-
return
|
|
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 ?
|
|
35926
|
+
return global3 ? join36(testHome, ".cache", "claude") : join36(testHome, ".claudekit", "cache");
|
|
34717
35927
|
}
|
|
34718
35928
|
if (!global3) {
|
|
34719
|
-
return
|
|
35929
|
+
return join36(homedir5(), ".claudekit", "cache");
|
|
34720
35930
|
}
|
|
34721
35931
|
const os2 = platform10();
|
|
34722
35932
|
if (os2 === "win32") {
|
|
34723
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
34724
|
-
return
|
|
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
|
|
35938
|
+
return join36(xdgCacheHome, "claude");
|
|
34729
35939
|
}
|
|
34730
|
-
return
|
|
35940
|
+
return join36(homedir5(), ".cache", "claude");
|
|
34731
35941
|
}
|
|
34732
35942
|
static getGlobalKitDir() {
|
|
34733
35943
|
const testHome = PathResolver2.getTestHomeDir();
|
|
34734
35944
|
if (testHome) {
|
|
34735
|
-
return
|
|
35945
|
+
return join36(testHome, ".claude");
|
|
34736
35946
|
}
|
|
34737
|
-
return
|
|
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
|
|
35955
|
+
return join36(baseDir, prefix, "skills");
|
|
34746
35956
|
}
|
|
34747
|
-
return
|
|
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
|
|
35965
|
+
return join36(baseDir, prefix, component);
|
|
34756
35966
|
}
|
|
34757
|
-
return
|
|
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 =
|
|
35999
|
+
const globalMetadataPath = join37(globalKitDir, "metadata.json");
|
|
34790
36000
|
const prefix = PathResolver2.getPathPrefix(false);
|
|
34791
|
-
const localMetadataPath = prefix ?
|
|
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");
|