claudekit-cli 3.10.2 → 3.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1615 -405
- 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.1",
|
|
14708
15470
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
14709
15471
|
type: "module",
|
|
14710
15472
|
repository: {
|
|
@@ -14724,7 +15486,7 @@ var package_default = {
|
|
|
14724
15486
|
],
|
|
14725
15487
|
scripts: {
|
|
14726
15488
|
dev: "bun run src/index.ts",
|
|
14727
|
-
build: "bun build src/index.ts --outdir dist --target node --external
|
|
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
|
|
28413
|
+
import { dirname as dirname5, join as join13, relative as relative3 } from "node:path";
|
|
27651
28414
|
|
|
27652
28415
|
// src/domains/config/settings-merger.ts
|
|
27653
28416
|
init_logger();
|
|
@@ -27856,7 +28619,7 @@ class SettingsMerger {
|
|
|
27856
28619
|
init_logger();
|
|
27857
28620
|
init_types2();
|
|
27858
28621
|
init_dist2();
|
|
27859
|
-
var
|
|
28622
|
+
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
27860
28623
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
27861
28624
|
|
|
27862
28625
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
@@ -29293,6 +30056,280 @@ minimatch.Minimatch = Minimatch;
|
|
|
29293
30056
|
minimatch.escape = escape;
|
|
29294
30057
|
minimatch.unescape = unescape;
|
|
29295
30058
|
|
|
30059
|
+
// src/domains/installation/selective-merger.ts
|
|
30060
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
30061
|
+
|
|
30062
|
+
// src/services/file-operations/ownership-checker.ts
|
|
30063
|
+
import { createHash } from "node:crypto";
|
|
30064
|
+
import { createReadStream } from "node:fs";
|
|
30065
|
+
import { stat } from "node:fs/promises";
|
|
30066
|
+
import { relative as relative2 } from "node:path";
|
|
30067
|
+
|
|
30068
|
+
// src/domains/migration/metadata-migration.ts
|
|
30069
|
+
init_logger();
|
|
30070
|
+
var import_fs_extra3 = __toESM(require_lib(), 1);
|
|
30071
|
+
import { join as join12 } from "node:path";
|
|
30072
|
+
async function detectMetadataFormat(claudeDir) {
|
|
30073
|
+
const metadataPath = join12(claudeDir, "metadata.json");
|
|
30074
|
+
if (!await import_fs_extra3.pathExists(metadataPath)) {
|
|
30075
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30076
|
+
}
|
|
30077
|
+
try {
|
|
30078
|
+
const content = await import_fs_extra3.readFile(metadataPath, "utf-8");
|
|
30079
|
+
const parsed = JSON.parse(content);
|
|
30080
|
+
if (parsed.kits && Object.keys(parsed.kits).length > 0) {
|
|
30081
|
+
const installedKits = Object.keys(parsed.kits);
|
|
30082
|
+
return {
|
|
30083
|
+
format: "multi-kit",
|
|
30084
|
+
metadata: parsed,
|
|
30085
|
+
detectedKit: installedKits[0] || null
|
|
30086
|
+
};
|
|
30087
|
+
}
|
|
30088
|
+
if (parsed.name || parsed.version || parsed.files) {
|
|
30089
|
+
let detectedKit = null;
|
|
30090
|
+
const nameToCheck = parsed.name || "";
|
|
30091
|
+
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30092
|
+
detectedKit = "engineer";
|
|
30093
|
+
} else if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30094
|
+
detectedKit = "marketing";
|
|
30095
|
+
} else {
|
|
30096
|
+
detectedKit = "engineer";
|
|
30097
|
+
}
|
|
30098
|
+
return { format: "legacy", metadata: parsed, detectedKit };
|
|
30099
|
+
}
|
|
30100
|
+
logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
|
|
30101
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30102
|
+
} catch (error) {
|
|
30103
|
+
logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
|
|
30104
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30105
|
+
}
|
|
30106
|
+
}
|
|
30107
|
+
async function migrateToMultiKit(claudeDir) {
|
|
30108
|
+
const detection = await detectMetadataFormat(claudeDir);
|
|
30109
|
+
if (detection.format === "multi-kit") {
|
|
30110
|
+
return {
|
|
30111
|
+
success: true,
|
|
30112
|
+
migrated: false,
|
|
30113
|
+
fromFormat: "multi-kit",
|
|
30114
|
+
toFormat: "multi-kit"
|
|
30115
|
+
};
|
|
30116
|
+
}
|
|
30117
|
+
if (detection.format === "none") {
|
|
30118
|
+
return {
|
|
30119
|
+
success: true,
|
|
30120
|
+
migrated: false,
|
|
30121
|
+
fromFormat: "none",
|
|
30122
|
+
toFormat: "multi-kit"
|
|
30123
|
+
};
|
|
30124
|
+
}
|
|
30125
|
+
const metadataPath = join12(claudeDir, "metadata.json");
|
|
30126
|
+
const legacy = detection.metadata;
|
|
30127
|
+
if (!legacy) {
|
|
30128
|
+
return {
|
|
30129
|
+
success: false,
|
|
30130
|
+
migrated: false,
|
|
30131
|
+
fromFormat: "legacy",
|
|
30132
|
+
toFormat: "multi-kit",
|
|
30133
|
+
error: "Metadata exists but could not be read"
|
|
30134
|
+
};
|
|
30135
|
+
}
|
|
30136
|
+
const legacyKit = detection.detectedKit || "engineer";
|
|
30137
|
+
try {
|
|
30138
|
+
const kitMetadata = {
|
|
30139
|
+
version: legacy.version || "unknown",
|
|
30140
|
+
installedAt: legacy.installedAt || new Date().toISOString(),
|
|
30141
|
+
files: legacy.files || []
|
|
30142
|
+
};
|
|
30143
|
+
const multiKit = {
|
|
30144
|
+
kits: {
|
|
30145
|
+
[legacyKit]: kitMetadata
|
|
30146
|
+
},
|
|
30147
|
+
scope: legacy.scope,
|
|
30148
|
+
name: legacy.name,
|
|
30149
|
+
version: legacy.version,
|
|
30150
|
+
installedAt: legacy.installedAt,
|
|
30151
|
+
installedFiles: legacy.installedFiles,
|
|
30152
|
+
userConfigFiles: legacy.userConfigFiles,
|
|
30153
|
+
files: legacy.files
|
|
30154
|
+
};
|
|
30155
|
+
await import_fs_extra3.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
|
|
30156
|
+
logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
|
|
30157
|
+
return {
|
|
30158
|
+
success: true,
|
|
30159
|
+
migrated: true,
|
|
30160
|
+
fromFormat: "legacy",
|
|
30161
|
+
toFormat: "multi-kit"
|
|
30162
|
+
};
|
|
30163
|
+
} catch (error) {
|
|
30164
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
30165
|
+
logger.error(`Metadata migration failed: ${errorMsg}`);
|
|
30166
|
+
return {
|
|
30167
|
+
success: false,
|
|
30168
|
+
migrated: false,
|
|
30169
|
+
fromFormat: "legacy",
|
|
30170
|
+
toFormat: "multi-kit",
|
|
30171
|
+
error: errorMsg
|
|
30172
|
+
};
|
|
30173
|
+
}
|
|
30174
|
+
}
|
|
30175
|
+
function getKitMetadata(metadata, kit) {
|
|
30176
|
+
if (metadata.kits?.[kit]) {
|
|
30177
|
+
return metadata.kits[kit];
|
|
30178
|
+
}
|
|
30179
|
+
if (!metadata.kits && metadata.version) {
|
|
30180
|
+
return {
|
|
30181
|
+
version: metadata.version,
|
|
30182
|
+
installedAt: metadata.installedAt || "",
|
|
30183
|
+
files: metadata.files
|
|
30184
|
+
};
|
|
30185
|
+
}
|
|
30186
|
+
return null;
|
|
30187
|
+
}
|
|
30188
|
+
function getAllTrackedFiles(metadata) {
|
|
30189
|
+
if (metadata.kits) {
|
|
30190
|
+
const allFiles = [];
|
|
30191
|
+
for (const kit of Object.values(metadata.kits)) {
|
|
30192
|
+
if (kit.files) {
|
|
30193
|
+
allFiles.push(...kit.files);
|
|
30194
|
+
}
|
|
30195
|
+
}
|
|
30196
|
+
return allFiles;
|
|
30197
|
+
}
|
|
30198
|
+
return metadata.files || [];
|
|
30199
|
+
}
|
|
30200
|
+
function getInstalledKits(metadata) {
|
|
30201
|
+
if (metadata.kits) {
|
|
30202
|
+
return Object.keys(metadata.kits);
|
|
30203
|
+
}
|
|
30204
|
+
const nameToCheck = metadata.name || "";
|
|
30205
|
+
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30206
|
+
return ["engineer"];
|
|
30207
|
+
}
|
|
30208
|
+
if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30209
|
+
return ["marketing"];
|
|
30210
|
+
}
|
|
30211
|
+
if (metadata.version) {
|
|
30212
|
+
return ["engineer"];
|
|
30213
|
+
}
|
|
30214
|
+
return [];
|
|
30215
|
+
}
|
|
30216
|
+
|
|
30217
|
+
// src/services/file-operations/ownership-checker.ts
|
|
30218
|
+
class OwnershipChecker {
|
|
30219
|
+
static async calculateChecksum(filePath) {
|
|
30220
|
+
return new Promise((resolve3, reject) => {
|
|
30221
|
+
const hash = createHash("sha256");
|
|
30222
|
+
const stream = createReadStream(filePath);
|
|
30223
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
30224
|
+
stream.on("end", () => {
|
|
30225
|
+
resolve3(hash.digest("hex"));
|
|
30226
|
+
});
|
|
30227
|
+
stream.on("error", (err) => {
|
|
30228
|
+
stream.destroy();
|
|
30229
|
+
reject(new Error(`Failed to calculate checksum for "${filePath}": ${err.message}`));
|
|
30230
|
+
});
|
|
30231
|
+
});
|
|
30232
|
+
}
|
|
30233
|
+
static async checkOwnership(filePath, metadata, claudeDir) {
|
|
30234
|
+
try {
|
|
30235
|
+
await stat(filePath);
|
|
30236
|
+
} catch {
|
|
30237
|
+
return { path: filePath, ownership: "user", exists: false };
|
|
30238
|
+
}
|
|
30239
|
+
const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
|
|
30240
|
+
if (!metadata || allTrackedFiles.length === 0) {
|
|
30241
|
+
return { path: filePath, ownership: "user", exists: true };
|
|
30242
|
+
}
|
|
30243
|
+
const relativePath = relative2(claudeDir, filePath).replace(/\\/g, "/");
|
|
30244
|
+
const tracked = allTrackedFiles.find((f3) => f3.path === relativePath);
|
|
30245
|
+
if (!tracked) {
|
|
30246
|
+
return { path: filePath, ownership: "user", exists: true };
|
|
30247
|
+
}
|
|
30248
|
+
const actualChecksum = await OwnershipChecker.calculateChecksum(filePath);
|
|
30249
|
+
if (actualChecksum === tracked.checksum) {
|
|
30250
|
+
return {
|
|
30251
|
+
path: filePath,
|
|
30252
|
+
ownership: "ck",
|
|
30253
|
+
expectedChecksum: tracked.checksum,
|
|
30254
|
+
actualChecksum,
|
|
30255
|
+
exists: true
|
|
30256
|
+
};
|
|
30257
|
+
}
|
|
30258
|
+
return {
|
|
30259
|
+
path: filePath,
|
|
30260
|
+
ownership: "ck-modified",
|
|
30261
|
+
expectedChecksum: tracked.checksum,
|
|
30262
|
+
actualChecksum,
|
|
30263
|
+
exists: true
|
|
30264
|
+
};
|
|
30265
|
+
}
|
|
30266
|
+
static async checkBatch(filePaths, metadata, claudeDir) {
|
|
30267
|
+
const results = await Promise.all(filePaths.map((path9) => OwnershipChecker.checkOwnership(path9, metadata, claudeDir)));
|
|
30268
|
+
return new Map(results.map((r2) => [r2.path, r2]));
|
|
30269
|
+
}
|
|
30270
|
+
}
|
|
30271
|
+
|
|
30272
|
+
// src/domains/installation/selective-merger.ts
|
|
30273
|
+
init_logger();
|
|
30274
|
+
|
|
30275
|
+
class SelectiveMerger {
|
|
30276
|
+
manifest;
|
|
30277
|
+
manifestMap;
|
|
30278
|
+
constructor(manifest) {
|
|
30279
|
+
this.manifest = manifest;
|
|
30280
|
+
this.manifestMap = new Map;
|
|
30281
|
+
if (manifest) {
|
|
30282
|
+
for (const file of manifest.files) {
|
|
30283
|
+
this.manifestMap.set(file.path, file);
|
|
30284
|
+
}
|
|
30285
|
+
}
|
|
30286
|
+
}
|
|
30287
|
+
async shouldCopyFile(destPath, relativePath) {
|
|
30288
|
+
let destStat;
|
|
30289
|
+
try {
|
|
30290
|
+
destStat = await stat2(destPath);
|
|
30291
|
+
} catch {
|
|
30292
|
+
return { changed: true, reason: "new" };
|
|
30293
|
+
}
|
|
30294
|
+
const manifestEntry = this.manifestMap.get(relativePath);
|
|
30295
|
+
if (!manifestEntry) {
|
|
30296
|
+
logger.debug(`No manifest entry for ${relativePath}, will copy`);
|
|
30297
|
+
return { changed: true, reason: "new" };
|
|
30298
|
+
}
|
|
30299
|
+
if (destStat.size !== manifestEntry.size) {
|
|
30300
|
+
logger.debug(`Size differs for ${relativePath}: ${destStat.size} vs ${manifestEntry.size}`);
|
|
30301
|
+
return {
|
|
30302
|
+
changed: true,
|
|
30303
|
+
reason: "size-differ",
|
|
30304
|
+
sourceChecksum: manifestEntry.checksum
|
|
30305
|
+
};
|
|
30306
|
+
}
|
|
30307
|
+
const destChecksum = await OwnershipChecker.calculateChecksum(destPath);
|
|
30308
|
+
if (destChecksum !== manifestEntry.checksum) {
|
|
30309
|
+
logger.debug(`Checksum differs for ${relativePath}`);
|
|
30310
|
+
return {
|
|
30311
|
+
changed: true,
|
|
30312
|
+
reason: "checksum-differ",
|
|
30313
|
+
sourceChecksum: manifestEntry.checksum,
|
|
30314
|
+
destChecksum
|
|
30315
|
+
};
|
|
30316
|
+
}
|
|
30317
|
+
logger.debug(`Unchanged: ${relativePath}`);
|
|
30318
|
+
return {
|
|
30319
|
+
changed: false,
|
|
30320
|
+
reason: "unchanged",
|
|
30321
|
+
sourceChecksum: manifestEntry.checksum,
|
|
30322
|
+
destChecksum
|
|
30323
|
+
};
|
|
30324
|
+
}
|
|
30325
|
+
hasManifest() {
|
|
30326
|
+
return this.manifest !== null && this.manifestMap.size > 0;
|
|
30327
|
+
}
|
|
30328
|
+
getManifestFileCount() {
|
|
30329
|
+
return this.manifestMap.size;
|
|
30330
|
+
}
|
|
30331
|
+
}
|
|
30332
|
+
|
|
29296
30333
|
// src/domains/installation/file-merger.ts
|
|
29297
30334
|
class FileMerger {
|
|
29298
30335
|
neverCopyChecker = import_ignore2.default().add(NEVER_COPY_PATTERNS);
|
|
@@ -29302,6 +30339,8 @@ class FileMerger {
|
|
|
29302
30339
|
forceOverwriteSettings = false;
|
|
29303
30340
|
installedFiles = new Set;
|
|
29304
30341
|
installedDirectories = new Set;
|
|
30342
|
+
selectiveMerger = null;
|
|
30343
|
+
unchangedSkipped = 0;
|
|
29305
30344
|
setIncludePatterns(patterns) {
|
|
29306
30345
|
this.includePatterns = patterns;
|
|
29307
30346
|
}
|
|
@@ -29311,6 +30350,12 @@ class FileMerger {
|
|
|
29311
30350
|
setForceOverwriteSettings(force) {
|
|
29312
30351
|
this.forceOverwriteSettings = force;
|
|
29313
30352
|
}
|
|
30353
|
+
setManifest(manifest) {
|
|
30354
|
+
this.selectiveMerger = manifest ? new SelectiveMerger(manifest) : null;
|
|
30355
|
+
if (manifest && this.selectiveMerger?.hasManifest()) {
|
|
30356
|
+
logger.debug(`Selective merge enabled with ${this.selectiveMerger.getManifestFileCount()} tracked files`);
|
|
30357
|
+
}
|
|
30358
|
+
}
|
|
29314
30359
|
async merge(sourceDir, destDir, skipConfirmation = false) {
|
|
29315
30360
|
const conflicts = await this.detectConflicts(sourceDir, destDir);
|
|
29316
30361
|
if (conflicts.length > 0 && !skipConfirmation) {
|
|
@@ -29332,10 +30377,10 @@ class FileMerger {
|
|
|
29332
30377
|
const conflicts = [];
|
|
29333
30378
|
const files = await this.getFiles(sourceDir, sourceDir);
|
|
29334
30379
|
for (const file of files) {
|
|
29335
|
-
const relativePath =
|
|
30380
|
+
const relativePath = relative3(sourceDir, file);
|
|
29336
30381
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29337
|
-
const destPath =
|
|
29338
|
-
if (await
|
|
30382
|
+
const destPath = join13(destDir, relativePath);
|
|
30383
|
+
if (await import_fs_extra4.pathExists(destPath)) {
|
|
29339
30384
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29340
30385
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
29341
30386
|
continue;
|
|
@@ -29354,16 +30399,16 @@ class FileMerger {
|
|
|
29354
30399
|
let copiedCount = 0;
|
|
29355
30400
|
let skippedCount = 0;
|
|
29356
30401
|
for (const file of files) {
|
|
29357
|
-
const relativePath =
|
|
30402
|
+
const relativePath = relative3(sourceDir, file);
|
|
29358
30403
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29359
|
-
const destPath =
|
|
30404
|
+
const destPath = join13(destDir, relativePath);
|
|
29360
30405
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29361
30406
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
29362
30407
|
skippedCount++;
|
|
29363
30408
|
continue;
|
|
29364
30409
|
}
|
|
29365
30410
|
if (this.userConfigChecker.ignores(normalizedRelativePath)) {
|
|
29366
|
-
const fileExists = await
|
|
30411
|
+
const fileExists = await import_fs_extra4.pathExists(destPath);
|
|
29367
30412
|
if (fileExists) {
|
|
29368
30413
|
logger.debug(`Preserving user config: ${normalizedRelativePath}`);
|
|
29369
30414
|
skippedCount++;
|
|
@@ -29377,15 +30422,28 @@ class FileMerger {
|
|
|
29377
30422
|
copiedCount++;
|
|
29378
30423
|
continue;
|
|
29379
30424
|
}
|
|
29380
|
-
|
|
30425
|
+
if (this.selectiveMerger?.hasManifest()) {
|
|
30426
|
+
const compareResult = await this.selectiveMerger.shouldCopyFile(destPath, normalizedRelativePath);
|
|
30427
|
+
if (!compareResult.changed) {
|
|
30428
|
+
logger.debug(`Skipping unchanged: ${normalizedRelativePath}`);
|
|
30429
|
+
this.unchangedSkipped++;
|
|
30430
|
+
this.trackInstalledFile(normalizedRelativePath);
|
|
30431
|
+
continue;
|
|
30432
|
+
}
|
|
30433
|
+
}
|
|
30434
|
+
await import_fs_extra4.copy(file, destPath, { overwrite: true });
|
|
29381
30435
|
this.trackInstalledFile(normalizedRelativePath);
|
|
29382
30436
|
copiedCount++;
|
|
29383
30437
|
}
|
|
29384
|
-
|
|
30438
|
+
if (this.unchangedSkipped > 0) {
|
|
30439
|
+
logger.success(`Updated ${copiedCount} file(s), skipped ${this.unchangedSkipped} unchanged, skipped ${skippedCount} protected`);
|
|
30440
|
+
} else {
|
|
30441
|
+
logger.success(`Copied ${copiedCount} file(s), skipped ${skippedCount} protected file(s)`);
|
|
30442
|
+
}
|
|
29385
30443
|
}
|
|
29386
30444
|
async processSettingsJson(sourceFile, destFile) {
|
|
29387
30445
|
try {
|
|
29388
|
-
const sourceContent = await
|
|
30446
|
+
const sourceContent = await import_fs_extra4.readFile(sourceFile, "utf-8");
|
|
29389
30447
|
const isWindows5 = process.platform === "win32";
|
|
29390
30448
|
let transformedSource = sourceContent;
|
|
29391
30449
|
if (this.isGlobal) {
|
|
@@ -29401,19 +30459,19 @@ class FileMerger {
|
|
|
29401
30459
|
logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
|
|
29402
30460
|
}
|
|
29403
30461
|
}
|
|
29404
|
-
const destExists = await
|
|
30462
|
+
const destExists = await import_fs_extra4.pathExists(destFile);
|
|
29405
30463
|
if (destExists && !this.forceOverwriteSettings) {
|
|
29406
30464
|
await this.selectiveMergeSettings(transformedSource, destFile);
|
|
29407
30465
|
} else {
|
|
29408
30466
|
const formattedContent = this.formatJsonContent(transformedSource);
|
|
29409
|
-
await
|
|
30467
|
+
await import_fs_extra4.writeFile(destFile, formattedContent, "utf-8");
|
|
29410
30468
|
if (this.forceOverwriteSettings && destExists) {
|
|
29411
30469
|
logger.debug("Force overwrite enabled, replaced settings.json completely");
|
|
29412
30470
|
}
|
|
29413
30471
|
}
|
|
29414
30472
|
} catch (error) {
|
|
29415
30473
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
29416
|
-
await
|
|
30474
|
+
await import_fs_extra4.copy(sourceFile, destFile, { overwrite: true });
|
|
29417
30475
|
}
|
|
29418
30476
|
}
|
|
29419
30477
|
async selectiveMergeSettings(transformedSourceContent, destFile) {
|
|
@@ -29423,7 +30481,7 @@ class FileMerger {
|
|
|
29423
30481
|
} catch {
|
|
29424
30482
|
logger.warning("Failed to parse source settings.json, falling back to overwrite");
|
|
29425
30483
|
const formattedContent = this.formatJsonContent(transformedSourceContent);
|
|
29426
|
-
await
|
|
30484
|
+
await import_fs_extra4.writeFile(destFile, formattedContent, "utf-8");
|
|
29427
30485
|
return;
|
|
29428
30486
|
}
|
|
29429
30487
|
const destSettings = await SettingsMerger.readSettingsFile(destFile);
|
|
@@ -29469,12 +30527,12 @@ class FileMerger {
|
|
|
29469
30527
|
}
|
|
29470
30528
|
async getFiles(dir, baseDir = dir) {
|
|
29471
30529
|
const files = [];
|
|
29472
|
-
const entries = await
|
|
30530
|
+
const entries = await import_fs_extra4.readdir(dir, { encoding: "utf8" });
|
|
29473
30531
|
for (const entry of entries) {
|
|
29474
|
-
const fullPath =
|
|
29475
|
-
const relativePath =
|
|
30532
|
+
const fullPath = join13(dir, entry);
|
|
30533
|
+
const relativePath = relative3(baseDir, fullPath);
|
|
29476
30534
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29477
|
-
const stats = await
|
|
30535
|
+
const stats = await import_fs_extra4.lstat(fullPath);
|
|
29478
30536
|
if (stats.isSymbolicLink()) {
|
|
29479
30537
|
logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
|
|
29480
30538
|
continue;
|
|
@@ -29532,11 +30590,11 @@ class FileMerger {
|
|
|
29532
30590
|
|
|
29533
30591
|
// src/domains/installation/fresh-installer.ts
|
|
29534
30592
|
init_logger();
|
|
29535
|
-
import { join as
|
|
29536
|
-
var
|
|
30593
|
+
import { join as join14 } from "node:path";
|
|
30594
|
+
var import_fs_extra5 = __toESM(require_lib(), 1);
|
|
29537
30595
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
29538
30596
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
29539
|
-
if (!await
|
|
30597
|
+
if (!await import_fs_extra5.pathExists(claudeDir)) {
|
|
29540
30598
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
29541
30599
|
return true;
|
|
29542
30600
|
}
|
|
@@ -29551,8 +30609,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
29551
30609
|
const { rmSync } = await import("node:fs");
|
|
29552
30610
|
let removedCount = 0;
|
|
29553
30611
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
29554
|
-
const subdirPath =
|
|
29555
|
-
if (await
|
|
30612
|
+
const subdirPath = join14(claudeDir, subdir);
|
|
30613
|
+
if (await import_fs_extra5.pathExists(subdirPath)) {
|
|
29556
30614
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
29557
30615
|
removedCount++;
|
|
29558
30616
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
@@ -29567,11 +30625,11 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
29567
30625
|
}
|
|
29568
30626
|
|
|
29569
30627
|
// src/domains/installation/setup-wizard.ts
|
|
29570
|
-
import { join as
|
|
30628
|
+
import { join as join16 } from "node:path";
|
|
29571
30629
|
|
|
29572
30630
|
// src/domains/config/config-generator.ts
|
|
29573
|
-
var
|
|
29574
|
-
import { join as
|
|
30631
|
+
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
30632
|
+
import { join as join15 } from "node:path";
|
|
29575
30633
|
async function generateEnvFile(targetDir, values) {
|
|
29576
30634
|
const lines = [
|
|
29577
30635
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -29583,8 +30641,8 @@ async function generateEnvFile(targetDir, values) {
|
|
|
29583
30641
|
lines.push(`${key}=${value}`);
|
|
29584
30642
|
}
|
|
29585
30643
|
}
|
|
29586
|
-
const envPath =
|
|
29587
|
-
await
|
|
30644
|
+
const envPath = join15(targetDir, ".env");
|
|
30645
|
+
await import_fs_extra6.writeFile(envPath, `${lines.join(`
|
|
29588
30646
|
`)}
|
|
29589
30647
|
`, { mode: 384 });
|
|
29590
30648
|
}
|
|
@@ -29602,7 +30660,7 @@ function validateApiKey(value, pattern) {
|
|
|
29602
30660
|
// src/domains/installation/setup-wizard.ts
|
|
29603
30661
|
init_logger();
|
|
29604
30662
|
init_dist2();
|
|
29605
|
-
var
|
|
30663
|
+
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
29606
30664
|
var ESSENTIAL_CONFIGS = [
|
|
29607
30665
|
{
|
|
29608
30666
|
key: "GEMINI_API_KEY",
|
|
@@ -29631,7 +30689,7 @@ var ESSENTIAL_CONFIGS = [
|
|
|
29631
30689
|
];
|
|
29632
30690
|
async function parseEnvFile(path9) {
|
|
29633
30691
|
try {
|
|
29634
|
-
const content = await
|
|
30692
|
+
const content = await import_fs_extra7.readFile(path9, "utf-8");
|
|
29635
30693
|
const env2 = {};
|
|
29636
30694
|
for (const line of content.split(`
|
|
29637
30695
|
`)) {
|
|
@@ -29657,8 +30715,8 @@ async function parseEnvFile(path9) {
|
|
|
29657
30715
|
}
|
|
29658
30716
|
}
|
|
29659
30717
|
async function checkGlobalConfig() {
|
|
29660
|
-
const globalEnvPath =
|
|
29661
|
-
if (!await
|
|
30718
|
+
const globalEnvPath = join16(PathResolver.getGlobalKitDir(), ".env");
|
|
30719
|
+
if (!await import_fs_extra7.pathExists(globalEnvPath))
|
|
29662
30720
|
return false;
|
|
29663
30721
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
29664
30722
|
return Object.keys(env2).length > 0;
|
|
@@ -29673,8 +30731,8 @@ async function runSetupWizard(options) {
|
|
|
29673
30731
|
let globalEnv = {};
|
|
29674
30732
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
29675
30733
|
if (!isGlobal) {
|
|
29676
|
-
const globalEnvPath =
|
|
29677
|
-
if (await
|
|
30734
|
+
const globalEnvPath = join16(PathResolver.getGlobalKitDir(), ".env");
|
|
30735
|
+
if (await import_fs_extra7.pathExists(globalEnvPath)) {
|
|
29678
30736
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
29679
30737
|
}
|
|
29680
30738
|
}
|
|
@@ -29726,19 +30784,19 @@ async function runSetupWizard(options) {
|
|
|
29726
30784
|
}
|
|
29727
30785
|
}
|
|
29728
30786
|
await generateEnvFile(targetDir, values);
|
|
29729
|
-
f2.success(`Configuration saved to ${
|
|
30787
|
+
f2.success(`Configuration saved to ${join16(targetDir, ".env")}`);
|
|
29730
30788
|
return true;
|
|
29731
30789
|
}
|
|
29732
30790
|
|
|
29733
30791
|
// src/domains/migration/legacy-migration.ts
|
|
29734
|
-
import { readdir as readdir4, stat as
|
|
29735
|
-
import { join as
|
|
30792
|
+
import { readdir as readdir4, stat as stat3 } from "node:fs/promises";
|
|
30793
|
+
import { join as join19, relative as relative4 } from "node:path";
|
|
29736
30794
|
|
|
29737
30795
|
// src/services/file-operations/manifest-writer.ts
|
|
30796
|
+
import { join as join17 } from "node:path";
|
|
29738
30797
|
init_logger();
|
|
29739
30798
|
init_types2();
|
|
29740
|
-
var
|
|
29741
|
-
import { join as join16 } from "node:path";
|
|
30799
|
+
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
29742
30800
|
|
|
29743
30801
|
// node_modules/yocto-queue/index.js
|
|
29744
30802
|
class Node2 {
|
|
@@ -29880,66 +30938,8 @@ function validateConcurrency(concurrency) {
|
|
|
29880
30938
|
}
|
|
29881
30939
|
}
|
|
29882
30940
|
|
|
29883
|
-
// src/services/file-operations/ownership-checker.ts
|
|
29884
|
-
import { createHash } from "node:crypto";
|
|
29885
|
-
import { createReadStream } from "node:fs";
|
|
29886
|
-
import { stat } from "node:fs/promises";
|
|
29887
|
-
import { relative as relative3 } from "node:path";
|
|
29888
|
-
|
|
29889
|
-
class OwnershipChecker {
|
|
29890
|
-
static async calculateChecksum(filePath) {
|
|
29891
|
-
return new Promise((resolve3, reject) => {
|
|
29892
|
-
const hash = createHash("sha256");
|
|
29893
|
-
const stream = createReadStream(filePath);
|
|
29894
|
-
stream.on("data", (chunk) => hash.update(chunk));
|
|
29895
|
-
stream.on("end", () => {
|
|
29896
|
-
resolve3(hash.digest("hex"));
|
|
29897
|
-
});
|
|
29898
|
-
stream.on("error", (err) => {
|
|
29899
|
-
stream.destroy();
|
|
29900
|
-
reject(new Error(`Failed to calculate checksum for "${filePath}": ${err.message}`));
|
|
29901
|
-
});
|
|
29902
|
-
});
|
|
29903
|
-
}
|
|
29904
|
-
static async checkOwnership(filePath, metadata, claudeDir) {
|
|
29905
|
-
try {
|
|
29906
|
-
await stat(filePath);
|
|
29907
|
-
} catch {
|
|
29908
|
-
return { path: filePath, ownership: "user", exists: false };
|
|
29909
|
-
}
|
|
29910
|
-
if (!metadata || !metadata.files || metadata.files.length === 0) {
|
|
29911
|
-
return { path: filePath, ownership: "user", exists: true };
|
|
29912
|
-
}
|
|
29913
|
-
const relativePath = relative3(claudeDir, filePath).replace(/\\/g, "/");
|
|
29914
|
-
const tracked = metadata.files.find((f3) => f3.path === relativePath);
|
|
29915
|
-
if (!tracked) {
|
|
29916
|
-
return { path: filePath, ownership: "user", exists: true };
|
|
29917
|
-
}
|
|
29918
|
-
const actualChecksum = await OwnershipChecker.calculateChecksum(filePath);
|
|
29919
|
-
if (actualChecksum === tracked.checksum) {
|
|
29920
|
-
return {
|
|
29921
|
-
path: filePath,
|
|
29922
|
-
ownership: "ck",
|
|
29923
|
-
expectedChecksum: tracked.checksum,
|
|
29924
|
-
actualChecksum,
|
|
29925
|
-
exists: true
|
|
29926
|
-
};
|
|
29927
|
-
}
|
|
29928
|
-
return {
|
|
29929
|
-
path: filePath,
|
|
29930
|
-
ownership: "ck-modified",
|
|
29931
|
-
expectedChecksum: tracked.checksum,
|
|
29932
|
-
actualChecksum,
|
|
29933
|
-
exists: true
|
|
29934
|
-
};
|
|
29935
|
-
}
|
|
29936
|
-
static async checkBatch(filePaths, metadata, claudeDir) {
|
|
29937
|
-
const results = await Promise.all(filePaths.map((path9) => OwnershipChecker.checkOwnership(path9, metadata, claudeDir)));
|
|
29938
|
-
return new Map(results.map((r2) => [r2.path, r2]));
|
|
29939
|
-
}
|
|
29940
|
-
}
|
|
29941
|
-
|
|
29942
30941
|
// src/services/file-operations/manifest-writer.ts
|
|
30942
|
+
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
29943
30943
|
class ManifestWriter {
|
|
29944
30944
|
installedFiles = new Set;
|
|
29945
30945
|
userConfigFiles = new Set;
|
|
@@ -29995,13 +30995,16 @@ class ManifestWriter {
|
|
|
29995
30995
|
return false;
|
|
29996
30996
|
}
|
|
29997
30997
|
}));
|
|
29998
|
-
let completed = 0;
|
|
29999
30998
|
const progressInterval = Math.max(1, Math.floor(total / 20));
|
|
30000
|
-
|
|
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,68 @@ class ManifestWriter {
|
|
|
30015
31018
|
getTrackedFiles() {
|
|
30016
31019
|
return Array.from(this.trackedFiles.values()).sort((a3, b3) => a3.path.localeCompare(b3.path));
|
|
30017
31020
|
}
|
|
30018
|
-
async writeManifest(claudeDir, kitName, version, scope) {
|
|
30019
|
-
const metadataPath =
|
|
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
|
+
userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()]
|
|
31065
|
+
};
|
|
31066
|
+
const validated = MetadataSchema.parse(metadata);
|
|
31067
|
+
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
31068
|
+
logger.debug(`Wrote manifest for kit "${kit}" with ${trackedFiles.length} tracked files`);
|
|
31069
|
+
} finally {
|
|
31070
|
+
if (release) {
|
|
31071
|
+
await release();
|
|
31072
|
+
logger.debug(`Released lock on ${metadataPath}`);
|
|
30027
31073
|
}
|
|
30028
31074
|
}
|
|
30029
|
-
const trackedFiles = this.getTrackedFiles();
|
|
30030
|
-
const metadata = {
|
|
30031
|
-
...existingMetadata,
|
|
30032
|
-
name: kitName,
|
|
30033
|
-
version,
|
|
30034
|
-
installedAt: new Date().toISOString(),
|
|
30035
|
-
scope,
|
|
30036
|
-
installedFiles: this.getInstalledFiles(),
|
|
30037
|
-
userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()],
|
|
30038
|
-
files: trackedFiles.length > 0 ? trackedFiles : undefined
|
|
30039
|
-
};
|
|
30040
|
-
const validated = MetadataSchema.parse(metadata);
|
|
30041
|
-
await import_fs_extra7.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
30042
|
-
logger.debug(`Wrote manifest with ${this.installedFiles.size} installed files, ${trackedFiles.length} tracked`);
|
|
30043
31075
|
}
|
|
30044
31076
|
static async readManifest(claudeDir) {
|
|
30045
|
-
const metadataPath =
|
|
30046
|
-
if (!await
|
|
31077
|
+
const metadataPath = join17(claudeDir, "metadata.json");
|
|
31078
|
+
if (!await import_fs_extra8.pathExists(metadataPath)) {
|
|
30047
31079
|
return null;
|
|
30048
31080
|
}
|
|
30049
31081
|
try {
|
|
30050
|
-
const content = await
|
|
31082
|
+
const content = await import_fs_extra8.readFile(metadataPath, "utf-8");
|
|
30051
31083
|
const parsed = JSON.parse(content);
|
|
30052
31084
|
return MetadataSchema.parse(parsed);
|
|
30053
31085
|
} catch (error) {
|
|
@@ -30055,13 +31087,82 @@ class ManifestWriter {
|
|
|
30055
31087
|
return null;
|
|
30056
31088
|
}
|
|
30057
31089
|
}
|
|
30058
|
-
static async
|
|
31090
|
+
static async readKitManifest(claudeDir, kit) {
|
|
30059
31091
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
30060
|
-
if (metadata
|
|
31092
|
+
if (!metadata)
|
|
31093
|
+
return null;
|
|
31094
|
+
return getKitMetadata(metadata, kit);
|
|
31095
|
+
}
|
|
31096
|
+
static async getUninstallManifest(claudeDir, kit) {
|
|
31097
|
+
const detection = await detectMetadataFormat(claudeDir);
|
|
31098
|
+
if (detection.format === "multi-kit" && detection.metadata?.kits) {
|
|
31099
|
+
const installedKits = Object.keys(detection.metadata.kits);
|
|
31100
|
+
if (kit) {
|
|
31101
|
+
const kitMeta = detection.metadata.kits[kit];
|
|
31102
|
+
if (!kitMeta?.files) {
|
|
31103
|
+
return {
|
|
31104
|
+
filesToRemove: [],
|
|
31105
|
+
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
31106
|
+
hasManifest: true,
|
|
31107
|
+
isMultiKit: true,
|
|
31108
|
+
remainingKits: installedKits.filter((k2) => k2 !== kit)
|
|
31109
|
+
};
|
|
31110
|
+
}
|
|
31111
|
+
const kitFiles = kitMeta.files.map((f3) => f3.path);
|
|
31112
|
+
const sharedFiles = new Set;
|
|
31113
|
+
for (const otherKit of installedKits) {
|
|
31114
|
+
if (otherKit !== kit) {
|
|
31115
|
+
const otherMeta = detection.metadata.kits[otherKit];
|
|
31116
|
+
if (otherMeta?.files) {
|
|
31117
|
+
for (const f3 of otherMeta.files) {
|
|
31118
|
+
sharedFiles.add(f3.path);
|
|
31119
|
+
}
|
|
31120
|
+
}
|
|
31121
|
+
}
|
|
31122
|
+
}
|
|
31123
|
+
const filesToRemove = kitFiles.filter((f3) => !sharedFiles.has(f3));
|
|
31124
|
+
const filesToPreserve = [
|
|
31125
|
+
...USER_CONFIG_PATTERNS,
|
|
31126
|
+
...kitFiles.filter((f3) => sharedFiles.has(f3))
|
|
31127
|
+
];
|
|
31128
|
+
return {
|
|
31129
|
+
filesToRemove,
|
|
31130
|
+
filesToPreserve,
|
|
31131
|
+
hasManifest: true,
|
|
31132
|
+
isMultiKit: true,
|
|
31133
|
+
remainingKits: installedKits.filter((k2) => k2 !== kit)
|
|
31134
|
+
};
|
|
31135
|
+
}
|
|
31136
|
+
const allFiles = getAllTrackedFiles(detection.metadata);
|
|
30061
31137
|
return {
|
|
30062
|
-
filesToRemove:
|
|
30063
|
-
filesToPreserve:
|
|
30064
|
-
hasManifest: true
|
|
31138
|
+
filesToRemove: allFiles.map((f3) => f3.path),
|
|
31139
|
+
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
31140
|
+
hasManifest: true,
|
|
31141
|
+
isMultiKit: true,
|
|
31142
|
+
remainingKits: []
|
|
31143
|
+
};
|
|
31144
|
+
}
|
|
31145
|
+
if (detection.format === "legacy" && detection.metadata) {
|
|
31146
|
+
const legacyFiles2 = detection.metadata.files?.map((f3) => f3.path) || [];
|
|
31147
|
+
const installedFiles = detection.metadata.installedFiles || [];
|
|
31148
|
+
const hasFiles = legacyFiles2.length > 0 || installedFiles.length > 0;
|
|
31149
|
+
if (!hasFiles) {
|
|
31150
|
+
const legacyDirs2 = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
|
|
31151
|
+
const legacyFileList = ["metadata.json"];
|
|
31152
|
+
return {
|
|
31153
|
+
filesToRemove: [...legacyDirs2, ...legacyFileList],
|
|
31154
|
+
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
31155
|
+
hasManifest: false,
|
|
31156
|
+
isMultiKit: false,
|
|
31157
|
+
remainingKits: []
|
|
31158
|
+
};
|
|
31159
|
+
}
|
|
31160
|
+
return {
|
|
31161
|
+
filesToRemove: legacyFiles2.length > 0 ? legacyFiles2 : installedFiles,
|
|
31162
|
+
filesToPreserve: detection.metadata.userConfigFiles || USER_CONFIG_PATTERNS,
|
|
31163
|
+
hasManifest: true,
|
|
31164
|
+
isMultiKit: false,
|
|
31165
|
+
remainingKits: []
|
|
30065
31166
|
};
|
|
30066
31167
|
}
|
|
30067
31168
|
const legacyDirs = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
|
|
@@ -30069,20 +31170,55 @@ class ManifestWriter {
|
|
|
30069
31170
|
return {
|
|
30070
31171
|
filesToRemove: [...legacyDirs, ...legacyFiles],
|
|
30071
31172
|
filesToPreserve: USER_CONFIG_PATTERNS,
|
|
30072
|
-
hasManifest: false
|
|
31173
|
+
hasManifest: false,
|
|
31174
|
+
isMultiKit: false,
|
|
31175
|
+
remainingKits: []
|
|
30073
31176
|
};
|
|
30074
31177
|
}
|
|
31178
|
+
static async removeKitFromManifest(claudeDir, kit) {
|
|
31179
|
+
const metadataPath = join17(claudeDir, "metadata.json");
|
|
31180
|
+
if (!await import_fs_extra8.pathExists(metadataPath))
|
|
31181
|
+
return false;
|
|
31182
|
+
let release = null;
|
|
31183
|
+
try {
|
|
31184
|
+
release = await import_proper_lockfile.lock(metadataPath, {
|
|
31185
|
+
retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
|
|
31186
|
+
stale: 60000
|
|
31187
|
+
});
|
|
31188
|
+
logger.debug(`Acquired lock on ${metadataPath} for kit removal`);
|
|
31189
|
+
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
31190
|
+
if (!metadata?.kits?.[kit])
|
|
31191
|
+
return false;
|
|
31192
|
+
const { [kit]: _removed, ...remainingKits } = metadata.kits;
|
|
31193
|
+
if (Object.keys(remainingKits).length === 0) {
|
|
31194
|
+
logger.debug("No kits remaining, metadata.json will be cleaned up");
|
|
31195
|
+
return true;
|
|
31196
|
+
}
|
|
31197
|
+
const updated = {
|
|
31198
|
+
...metadata,
|
|
31199
|
+
kits: remainingKits
|
|
31200
|
+
};
|
|
31201
|
+
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
31202
|
+
logger.debug(`Removed kit "${kit}" from metadata, ${Object.keys(remainingKits).length} kit(s) remaining`);
|
|
31203
|
+
return true;
|
|
31204
|
+
} finally {
|
|
31205
|
+
if (release) {
|
|
31206
|
+
await release();
|
|
31207
|
+
logger.debug(`Released lock on ${metadataPath}`);
|
|
31208
|
+
}
|
|
31209
|
+
}
|
|
31210
|
+
}
|
|
30075
31211
|
}
|
|
30076
31212
|
|
|
30077
31213
|
// src/domains/migration/legacy-migration.ts
|
|
30078
31214
|
init_logger();
|
|
30079
|
-
var
|
|
31215
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
30080
31216
|
|
|
30081
31217
|
// src/domains/migration/release-manifest.ts
|
|
30082
31218
|
init_logger();
|
|
30083
31219
|
init_zod();
|
|
30084
|
-
var
|
|
30085
|
-
import { join as
|
|
31220
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
31221
|
+
import { join as join18 } from "node:path";
|
|
30086
31222
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
30087
31223
|
path: exports_external.string(),
|
|
30088
31224
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -30096,9 +31232,9 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
30096
31232
|
|
|
30097
31233
|
class ReleaseManifestLoader {
|
|
30098
31234
|
static async load(extractDir) {
|
|
30099
|
-
const manifestPath =
|
|
31235
|
+
const manifestPath = join18(extractDir, "release-manifest.json");
|
|
30100
31236
|
try {
|
|
30101
|
-
const content = await
|
|
31237
|
+
const content = await import_fs_extra9.readFile(manifestPath, "utf-8");
|
|
30102
31238
|
const parsed = JSON.parse(content);
|
|
30103
31239
|
return ReleaseManifestSchema.parse(parsed);
|
|
30104
31240
|
} catch (error) {
|
|
@@ -30142,10 +31278,10 @@ class LegacyMigration {
|
|
|
30142
31278
|
for (const entry of entries) {
|
|
30143
31279
|
if (entry === "metadata.json")
|
|
30144
31280
|
continue;
|
|
30145
|
-
const fullPath =
|
|
31281
|
+
const fullPath = join19(dir, entry);
|
|
30146
31282
|
let stats;
|
|
30147
31283
|
try {
|
|
30148
|
-
stats = await
|
|
31284
|
+
stats = await stat3(fullPath);
|
|
30149
31285
|
} catch (err) {
|
|
30150
31286
|
const error = err;
|
|
30151
31287
|
if (error.code === "ENOENT") {
|
|
@@ -30244,7 +31380,7 @@ User-created files (sample):`);
|
|
|
30244
31380
|
];
|
|
30245
31381
|
if (filesToChecksum.length > 0) {
|
|
30246
31382
|
const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
|
|
30247
|
-
const fullPath =
|
|
31383
|
+
const fullPath = join19(claudeDir, relativePath);
|
|
30248
31384
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
30249
31385
|
return { relativePath, checksum, ownership };
|
|
30250
31386
|
}));
|
|
@@ -30265,8 +31401,8 @@ User-created files (sample):`);
|
|
|
30265
31401
|
installedAt: new Date().toISOString(),
|
|
30266
31402
|
files: trackedFiles
|
|
30267
31403
|
};
|
|
30268
|
-
const metadataPath =
|
|
30269
|
-
await
|
|
31404
|
+
const metadataPath = join19(claudeDir, "metadata.json");
|
|
31405
|
+
await import_fs_extra10.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
30270
31406
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
30271
31407
|
return true;
|
|
30272
31408
|
}
|
|
@@ -30274,24 +31410,24 @@ User-created files (sample):`);
|
|
|
30274
31410
|
|
|
30275
31411
|
// src/domains/skills/skills-detector.ts
|
|
30276
31412
|
init_logger();
|
|
30277
|
-
var
|
|
31413
|
+
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
30278
31414
|
import { readdir as readdir6 } from "node:fs/promises";
|
|
30279
|
-
import { join as
|
|
31415
|
+
import { join as join21 } from "node:path";
|
|
30280
31416
|
|
|
30281
31417
|
// src/domains/skills/skills-manifest.ts
|
|
30282
31418
|
init_logger();
|
|
30283
31419
|
init_types2();
|
|
30284
|
-
var
|
|
31420
|
+
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
30285
31421
|
import { createHash as createHash2 } from "node:crypto";
|
|
30286
|
-
import { readFile as
|
|
30287
|
-
import { join as
|
|
31422
|
+
import { readFile as readFile13, readdir as readdir5, writeFile as writeFile12 } from "node:fs/promises";
|
|
31423
|
+
import { join as join20, relative as relative5 } from "node:path";
|
|
30288
31424
|
|
|
30289
31425
|
class SkillsManifestManager {
|
|
30290
31426
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
30291
31427
|
static MANIFEST_VERSION = "1.0.0";
|
|
30292
31428
|
static async generateManifest(skillsDir) {
|
|
30293
31429
|
logger.debug(`Generating manifest for: ${skillsDir}`);
|
|
30294
|
-
if (!await
|
|
31430
|
+
if (!await import_fs_extra11.pathExists(skillsDir)) {
|
|
30295
31431
|
throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
|
|
30296
31432
|
}
|
|
30297
31433
|
const structure = await SkillsManifestManager.detectStructure(skillsDir);
|
|
@@ -30306,18 +31442,18 @@ class SkillsManifestManager {
|
|
|
30306
31442
|
return manifest;
|
|
30307
31443
|
}
|
|
30308
31444
|
static async writeManifest(skillsDir, manifest) {
|
|
30309
|
-
const manifestPath =
|
|
30310
|
-
await
|
|
31445
|
+
const manifestPath = join20(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31446
|
+
await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
30311
31447
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
30312
31448
|
}
|
|
30313
31449
|
static async readManifest(skillsDir) {
|
|
30314
|
-
const manifestPath =
|
|
30315
|
-
if (!await
|
|
31450
|
+
const manifestPath = join20(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31451
|
+
if (!await import_fs_extra11.pathExists(manifestPath)) {
|
|
30316
31452
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
30317
31453
|
return null;
|
|
30318
31454
|
}
|
|
30319
31455
|
try {
|
|
30320
|
-
const content = await
|
|
31456
|
+
const content = await readFile13(manifestPath, "utf-8");
|
|
30321
31457
|
const data = JSON.parse(content);
|
|
30322
31458
|
const manifest = SkillsManifestSchema.parse(data);
|
|
30323
31459
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -30334,7 +31470,7 @@ class SkillsManifestManager {
|
|
|
30334
31470
|
return "flat";
|
|
30335
31471
|
}
|
|
30336
31472
|
for (const dir of dirs.slice(0, 3)) {
|
|
30337
|
-
const dirPath =
|
|
31473
|
+
const dirPath = join20(skillsDir, dir.name);
|
|
30338
31474
|
const subEntries = await readdir5(dirPath, { withFileTypes: true });
|
|
30339
31475
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
30340
31476
|
if (hasSubdirs) {
|
|
@@ -30353,7 +31489,7 @@ class SkillsManifestManager {
|
|
|
30353
31489
|
const entries = await readdir5(skillsDir, { withFileTypes: true });
|
|
30354
31490
|
for (const entry of entries) {
|
|
30355
31491
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
30356
|
-
const skillPath =
|
|
31492
|
+
const skillPath = join20(skillsDir, entry.name);
|
|
30357
31493
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30358
31494
|
skills.push({
|
|
30359
31495
|
name: entry.name,
|
|
@@ -30365,11 +31501,11 @@ class SkillsManifestManager {
|
|
|
30365
31501
|
const categories = await readdir5(skillsDir, { withFileTypes: true });
|
|
30366
31502
|
for (const category of categories) {
|
|
30367
31503
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
30368
|
-
const categoryPath =
|
|
31504
|
+
const categoryPath = join20(skillsDir, category.name);
|
|
30369
31505
|
const skillEntries = await readdir5(categoryPath, { withFileTypes: true });
|
|
30370
31506
|
for (const skillEntry of skillEntries) {
|
|
30371
31507
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
30372
|
-
const skillPath =
|
|
31508
|
+
const skillPath = join20(categoryPath, skillEntry.name);
|
|
30373
31509
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30374
31510
|
skills.push({
|
|
30375
31511
|
name: skillEntry.name,
|
|
@@ -30389,7 +31525,7 @@ class SkillsManifestManager {
|
|
|
30389
31525
|
files.sort();
|
|
30390
31526
|
for (const file of files) {
|
|
30391
31527
|
const relativePath = relative5(dirPath, file);
|
|
30392
|
-
const content = await
|
|
31528
|
+
const content = await readFile13(file);
|
|
30393
31529
|
hash.update(relativePath);
|
|
30394
31530
|
hash.update(content);
|
|
30395
31531
|
}
|
|
@@ -30399,7 +31535,7 @@ class SkillsManifestManager {
|
|
|
30399
31535
|
const files = [];
|
|
30400
31536
|
const entries = await readdir5(dirPath, { withFileTypes: true });
|
|
30401
31537
|
for (const entry of entries) {
|
|
30402
|
-
const fullPath =
|
|
31538
|
+
const fullPath = join20(dirPath, entry.name);
|
|
30403
31539
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30404
31540
|
continue;
|
|
30405
31541
|
}
|
|
@@ -30519,8 +31655,8 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
30519
31655
|
class SkillsMigrationDetector {
|
|
30520
31656
|
static async detectMigration(oldSkillsDir, currentSkillsDir) {
|
|
30521
31657
|
logger.debug("Detecting skills migration need...");
|
|
30522
|
-
const oldExists = await
|
|
30523
|
-
const currentExists = await
|
|
31658
|
+
const oldExists = await import_fs_extra12.pathExists(oldSkillsDir);
|
|
31659
|
+
const currentExists = await import_fs_extra12.pathExists(currentSkillsDir);
|
|
30524
31660
|
if (!oldExists && !currentExists) {
|
|
30525
31661
|
logger.debug("No skills directories found, migration not needed");
|
|
30526
31662
|
return {
|
|
@@ -30631,7 +31767,7 @@ class SkillsMigrationDetector {
|
|
|
30631
31767
|
};
|
|
30632
31768
|
}
|
|
30633
31769
|
static async scanDirectory(skillsDir) {
|
|
30634
|
-
if (!await
|
|
31770
|
+
if (!await import_fs_extra12.pathExists(skillsDir)) {
|
|
30635
31771
|
return ["flat", []];
|
|
30636
31772
|
}
|
|
30637
31773
|
const entries = await readdir6(skillsDir, { withFileTypes: true });
|
|
@@ -30642,12 +31778,12 @@ class SkillsMigrationDetector {
|
|
|
30642
31778
|
let totalSkillLikeCount = 0;
|
|
30643
31779
|
const allSkills = [];
|
|
30644
31780
|
for (const dir of dirs) {
|
|
30645
|
-
const dirPath =
|
|
31781
|
+
const dirPath = join21(skillsDir, dir.name);
|
|
30646
31782
|
const subEntries = await readdir6(dirPath, { withFileTypes: true });
|
|
30647
31783
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30648
31784
|
if (subdirs.length > 0) {
|
|
30649
31785
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30650
|
-
const subdirPath =
|
|
31786
|
+
const subdirPath = join21(dirPath, subdir.name);
|
|
30651
31787
|
const subdirFiles = await readdir6(subdirPath, { withFileTypes: true });
|
|
30652
31788
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
30653
31789
|
if (hasSkillMarker) {
|
|
@@ -30684,16 +31820,16 @@ class SkillsMigrationDetector {
|
|
|
30684
31820
|
// src/domains/skills/skills-migrator.ts
|
|
30685
31821
|
init_logger();
|
|
30686
31822
|
init_types2();
|
|
30687
|
-
var
|
|
31823
|
+
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
30688
31824
|
import { copyFile as copyFile2, mkdir as mkdir8, readdir as readdir9, rm as rm3 } from "node:fs/promises";
|
|
30689
|
-
import { join as
|
|
31825
|
+
import { join as join24 } from "node:path";
|
|
30690
31826
|
|
|
30691
31827
|
// src/domains/skills/skills-backup-manager.ts
|
|
30692
31828
|
init_logger();
|
|
30693
31829
|
init_types2();
|
|
30694
|
-
var
|
|
30695
|
-
import { copyFile, mkdir as mkdir7, readdir as readdir7, rm as rm2, stat as
|
|
30696
|
-
import { basename as basename2, join as
|
|
31830
|
+
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
31831
|
+
import { copyFile, mkdir as mkdir7, readdir as readdir7, rm as rm2, stat as stat4 } from "node:fs/promises";
|
|
31832
|
+
import { basename as basename2, join as join22, normalize as normalize4 } from "node:path";
|
|
30697
31833
|
function validatePath(path9, paramName) {
|
|
30698
31834
|
if (!path9 || typeof path9 !== "string") {
|
|
30699
31835
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30713,13 +31849,13 @@ class SkillsBackupManager {
|
|
|
30713
31849
|
if (parentDir) {
|
|
30714
31850
|
validatePath(parentDir, "parentDir");
|
|
30715
31851
|
}
|
|
30716
|
-
if (!await
|
|
31852
|
+
if (!await import_fs_extra13.pathExists(skillsDir)) {
|
|
30717
31853
|
throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
|
|
30718
31854
|
}
|
|
30719
31855
|
const timestamp = Date.now();
|
|
30720
31856
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
30721
31857
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
30722
|
-
const backupDir = parentDir ?
|
|
31858
|
+
const backupDir = parentDir ? join22(parentDir, backupDirName) : join22(skillsDir, "..", backupDirName);
|
|
30723
31859
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
30724
31860
|
try {
|
|
30725
31861
|
await mkdir7(backupDir, { recursive: true });
|
|
@@ -30736,12 +31872,12 @@ class SkillsBackupManager {
|
|
|
30736
31872
|
static async restoreBackup(backupDir, targetDir) {
|
|
30737
31873
|
validatePath(backupDir, "backupDir");
|
|
30738
31874
|
validatePath(targetDir, "targetDir");
|
|
30739
|
-
if (!await
|
|
31875
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30740
31876
|
throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
|
|
30741
31877
|
}
|
|
30742
31878
|
logger.info(`Restoring from backup: ${backupDir}`);
|
|
30743
31879
|
try {
|
|
30744
|
-
if (await
|
|
31880
|
+
if (await import_fs_extra13.pathExists(targetDir)) {
|
|
30745
31881
|
await rm2(targetDir, { recursive: true, force: true });
|
|
30746
31882
|
}
|
|
30747
31883
|
await mkdir7(targetDir, { recursive: true });
|
|
@@ -30752,7 +31888,7 @@ class SkillsBackupManager {
|
|
|
30752
31888
|
}
|
|
30753
31889
|
}
|
|
30754
31890
|
static async deleteBackup(backupDir) {
|
|
30755
|
-
if (!await
|
|
31891
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30756
31892
|
logger.warning(`Backup directory does not exist: ${backupDir}`);
|
|
30757
31893
|
return;
|
|
30758
31894
|
}
|
|
@@ -30765,12 +31901,12 @@ class SkillsBackupManager {
|
|
|
30765
31901
|
}
|
|
30766
31902
|
}
|
|
30767
31903
|
static async listBackups(parentDir) {
|
|
30768
|
-
if (!await
|
|
31904
|
+
if (!await import_fs_extra13.pathExists(parentDir)) {
|
|
30769
31905
|
return [];
|
|
30770
31906
|
}
|
|
30771
31907
|
try {
|
|
30772
31908
|
const entries = await readdir7(parentDir, { withFileTypes: true });
|
|
30773
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
31909
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join22(parentDir, entry.name));
|
|
30774
31910
|
backups.sort().reverse();
|
|
30775
31911
|
return backups;
|
|
30776
31912
|
} catch (error) {
|
|
@@ -30790,7 +31926,7 @@ class SkillsBackupManager {
|
|
|
30790
31926
|
}
|
|
30791
31927
|
}
|
|
30792
31928
|
static async getBackupSize(backupDir) {
|
|
30793
|
-
if (!await
|
|
31929
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30794
31930
|
return 0;
|
|
30795
31931
|
}
|
|
30796
31932
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
@@ -30798,8 +31934,8 @@ class SkillsBackupManager {
|
|
|
30798
31934
|
static async copyDirectory(sourceDir, destDir) {
|
|
30799
31935
|
const entries = await readdir7(sourceDir, { withFileTypes: true });
|
|
30800
31936
|
for (const entry of entries) {
|
|
30801
|
-
const sourcePath =
|
|
30802
|
-
const destPath =
|
|
31937
|
+
const sourcePath = join22(sourceDir, entry.name);
|
|
31938
|
+
const destPath = join22(destDir, entry.name);
|
|
30803
31939
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30804
31940
|
continue;
|
|
30805
31941
|
}
|
|
@@ -30815,14 +31951,14 @@ class SkillsBackupManager {
|
|
|
30815
31951
|
let size = 0;
|
|
30816
31952
|
const entries = await readdir7(dirPath, { withFileTypes: true });
|
|
30817
31953
|
for (const entry of entries) {
|
|
30818
|
-
const fullPath =
|
|
31954
|
+
const fullPath = join22(dirPath, entry.name);
|
|
30819
31955
|
if (entry.isSymbolicLink()) {
|
|
30820
31956
|
continue;
|
|
30821
31957
|
}
|
|
30822
31958
|
if (entry.isDirectory()) {
|
|
30823
31959
|
size += await SkillsBackupManager.getDirectorySize(fullPath);
|
|
30824
31960
|
} else if (entry.isFile()) {
|
|
30825
|
-
const stats = await
|
|
31961
|
+
const stats = await stat4(fullPath);
|
|
30826
31962
|
size += stats.size;
|
|
30827
31963
|
}
|
|
30828
31964
|
}
|
|
@@ -30842,11 +31978,11 @@ class SkillsBackupManager {
|
|
|
30842
31978
|
// src/domains/skills/skills-customization-scanner.ts
|
|
30843
31979
|
init_logger();
|
|
30844
31980
|
init_types2();
|
|
30845
|
-
var
|
|
31981
|
+
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
30846
31982
|
import { createHash as createHash3 } from "node:crypto";
|
|
30847
31983
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
30848
|
-
import { readFile as
|
|
30849
|
-
import { join as
|
|
31984
|
+
import { readFile as readFile14, readdir as readdir8 } from "node:fs/promises";
|
|
31985
|
+
import { join as join23, normalize as normalize5, relative as relative6 } from "node:path";
|
|
30850
31986
|
function validatePath2(path9, paramName) {
|
|
30851
31987
|
if (!path9 || typeof path9 !== "string") {
|
|
30852
31988
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30925,7 +32061,7 @@ class SkillsCustomizationScanner {
|
|
|
30925
32061
|
static async detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
30926
32062
|
const changes = [];
|
|
30927
32063
|
const currentFiles = await SkillsCustomizationScanner.getAllFiles(currentSkillPath);
|
|
30928
|
-
const baselineFiles = await
|
|
32064
|
+
const baselineFiles = await import_fs_extra14.pathExists(baselineSkillPath) ? await SkillsCustomizationScanner.getAllFiles(baselineSkillPath) : [];
|
|
30929
32065
|
const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
|
|
30930
32066
|
const relPath = relative6(currentSkillPath, f3);
|
|
30931
32067
|
const hash = await SkillsCustomizationScanner.hashFile(f3);
|
|
@@ -30985,7 +32121,7 @@ class SkillsCustomizationScanner {
|
|
|
30985
32121
|
return false;
|
|
30986
32122
|
}
|
|
30987
32123
|
static async scanSkillsDirectory(skillsDir) {
|
|
30988
|
-
if (!await
|
|
32124
|
+
if (!await import_fs_extra14.pathExists(skillsDir)) {
|
|
30989
32125
|
return ["flat", []];
|
|
30990
32126
|
}
|
|
30991
32127
|
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
@@ -30993,13 +32129,13 @@ class SkillsCustomizationScanner {
|
|
|
30993
32129
|
if (dirs.length === 0) {
|
|
30994
32130
|
return ["flat", []];
|
|
30995
32131
|
}
|
|
30996
|
-
const firstDirPath =
|
|
32132
|
+
const firstDirPath = join23(skillsDir, dirs[0].name);
|
|
30997
32133
|
const subEntries = await readdir8(firstDirPath, { withFileTypes: true });
|
|
30998
32134
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30999
32135
|
if (subdirs.length > 0) {
|
|
31000
32136
|
let skillLikeCount = 0;
|
|
31001
32137
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
31002
|
-
const subdirPath =
|
|
32138
|
+
const subdirPath = join23(firstDirPath, subdir.name);
|
|
31003
32139
|
const subdirFiles = await readdir8(subdirPath, { withFileTypes: true });
|
|
31004
32140
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
31005
32141
|
if (hasSkillMarker) {
|
|
@@ -31009,7 +32145,7 @@ class SkillsCustomizationScanner {
|
|
|
31009
32145
|
if (skillLikeCount > 0) {
|
|
31010
32146
|
const skills = [];
|
|
31011
32147
|
for (const dir of dirs) {
|
|
31012
|
-
const categoryPath =
|
|
32148
|
+
const categoryPath = join23(skillsDir, dir.name);
|
|
31013
32149
|
const skillDirs = await readdir8(categoryPath, { withFileTypes: true });
|
|
31014
32150
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
31015
32151
|
}
|
|
@@ -31019,8 +32155,8 @@ class SkillsCustomizationScanner {
|
|
|
31019
32155
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
31020
32156
|
}
|
|
31021
32157
|
static async findSkillPath(skillsDir, skillName) {
|
|
31022
|
-
const flatPath =
|
|
31023
|
-
if (await
|
|
32158
|
+
const flatPath = join23(skillsDir, skillName);
|
|
32159
|
+
if (await import_fs_extra14.pathExists(flatPath)) {
|
|
31024
32160
|
return { path: flatPath, category: undefined };
|
|
31025
32161
|
}
|
|
31026
32162
|
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
@@ -31028,9 +32164,9 @@ class SkillsCustomizationScanner {
|
|
|
31028
32164
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
31029
32165
|
continue;
|
|
31030
32166
|
}
|
|
31031
|
-
const categoryPath =
|
|
31032
|
-
const skillPath =
|
|
31033
|
-
if (await
|
|
32167
|
+
const categoryPath = join23(skillsDir, entry.name);
|
|
32168
|
+
const skillPath = join23(categoryPath, skillName);
|
|
32169
|
+
if (await import_fs_extra14.pathExists(skillPath)) {
|
|
31034
32170
|
return { path: skillPath, category: entry.name };
|
|
31035
32171
|
}
|
|
31036
32172
|
}
|
|
@@ -31040,7 +32176,7 @@ class SkillsCustomizationScanner {
|
|
|
31040
32176
|
const files = [];
|
|
31041
32177
|
const entries = await readdir8(dirPath, { withFileTypes: true });
|
|
31042
32178
|
for (const entry of entries) {
|
|
31043
|
-
const fullPath =
|
|
32179
|
+
const fullPath = join23(dirPath, entry.name);
|
|
31044
32180
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31045
32181
|
continue;
|
|
31046
32182
|
}
|
|
@@ -31073,7 +32209,7 @@ class SkillsCustomizationScanner {
|
|
|
31073
32209
|
files.sort();
|
|
31074
32210
|
for (const file of files) {
|
|
31075
32211
|
const relativePath = relative6(dirPath, file);
|
|
31076
|
-
const content = await
|
|
32212
|
+
const content = await readFile14(file);
|
|
31077
32213
|
hash.update(relativePath);
|
|
31078
32214
|
hash.update(content);
|
|
31079
32215
|
}
|
|
@@ -31283,7 +32419,7 @@ class SkillsMigrator {
|
|
|
31283
32419
|
}
|
|
31284
32420
|
}
|
|
31285
32421
|
if (options.backup && !options.dryRun) {
|
|
31286
|
-
const claudeDir =
|
|
32422
|
+
const claudeDir = join24(currentSkillsDir, "..");
|
|
31287
32423
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
31288
32424
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
31289
32425
|
}
|
|
@@ -31335,14 +32471,14 @@ class SkillsMigrator {
|
|
|
31335
32471
|
const migrated = [];
|
|
31336
32472
|
const preserved = [];
|
|
31337
32473
|
const errors2 = [];
|
|
31338
|
-
const tempDir =
|
|
32474
|
+
const tempDir = join24(currentSkillsDir, "..", ".skills-migration-temp");
|
|
31339
32475
|
await mkdir8(tempDir, { recursive: true });
|
|
31340
32476
|
try {
|
|
31341
32477
|
for (const mapping of mappings) {
|
|
31342
32478
|
try {
|
|
31343
32479
|
const skillName = mapping.skillName;
|
|
31344
32480
|
const currentSkillPath = mapping.oldPath;
|
|
31345
|
-
if (!await
|
|
32481
|
+
if (!await import_fs_extra15.pathExists(currentSkillPath)) {
|
|
31346
32482
|
logger.warning(`Skill not found, skipping: ${skillName}`);
|
|
31347
32483
|
continue;
|
|
31348
32484
|
}
|
|
@@ -31356,9 +32492,9 @@ class SkillsMigrator {
|
|
|
31356
32492
|
}
|
|
31357
32493
|
}
|
|
31358
32494
|
const category = mapping.category;
|
|
31359
|
-
const targetPath = category ?
|
|
32495
|
+
const targetPath = category ? join24(tempDir, category, skillName) : join24(tempDir, skillName);
|
|
31360
32496
|
if (category) {
|
|
31361
|
-
await mkdir8(
|
|
32497
|
+
await mkdir8(join24(tempDir, category), { recursive: true });
|
|
31362
32498
|
}
|
|
31363
32499
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
31364
32500
|
migrated.push(skillName);
|
|
@@ -31392,8 +32528,8 @@ class SkillsMigrator {
|
|
|
31392
32528
|
await mkdir8(destDir, { recursive: true });
|
|
31393
32529
|
const entries = await readdir9(sourceDir, { withFileTypes: true });
|
|
31394
32530
|
for (const entry of entries) {
|
|
31395
|
-
const sourcePath =
|
|
31396
|
-
const destPath =
|
|
32531
|
+
const sourcePath = join24(sourceDir, entry.name);
|
|
32532
|
+
const destPath = join24(destDir, entry.name);
|
|
31397
32533
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31398
32534
|
continue;
|
|
31399
32535
|
}
|
|
@@ -31981,31 +33117,31 @@ class PromptsManager {
|
|
|
31981
33117
|
|
|
31982
33118
|
// src/services/file-operations/file-scanner.ts
|
|
31983
33119
|
init_logger();
|
|
31984
|
-
import { join as
|
|
31985
|
-
var
|
|
33120
|
+
import { join as join28, relative as relative7, resolve as resolve5 } from "node:path";
|
|
33121
|
+
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31986
33122
|
|
|
31987
33123
|
class FileScanner {
|
|
31988
33124
|
static async getFiles(dirPath, relativeTo) {
|
|
31989
33125
|
const basePath = relativeTo || dirPath;
|
|
31990
33126
|
const files = [];
|
|
31991
|
-
if (!await
|
|
33127
|
+
if (!await import_fs_extra16.pathExists(dirPath)) {
|
|
31992
33128
|
return files;
|
|
31993
33129
|
}
|
|
31994
33130
|
try {
|
|
31995
|
-
const entries = await
|
|
33131
|
+
const entries = await import_fs_extra16.readdir(dirPath, { encoding: "utf8" });
|
|
31996
33132
|
for (const entry of entries) {
|
|
31997
33133
|
if (SKIP_DIRS_ALL.includes(entry)) {
|
|
31998
33134
|
logger.debug(`Skipping directory: ${entry}`);
|
|
31999
33135
|
continue;
|
|
32000
33136
|
}
|
|
32001
|
-
const fullPath =
|
|
33137
|
+
const fullPath = join28(dirPath, entry);
|
|
32002
33138
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
32003
33139
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
32004
33140
|
continue;
|
|
32005
33141
|
}
|
|
32006
33142
|
let stats;
|
|
32007
33143
|
try {
|
|
32008
|
-
stats = await
|
|
33144
|
+
stats = await import_fs_extra16.lstat(fullPath);
|
|
32009
33145
|
} catch (error) {
|
|
32010
33146
|
if (error instanceof Error && "code" in error && (error.code === "EACCES" || error.code === "EPERM")) {
|
|
32011
33147
|
logger.warning(`Skipping inaccessible path: ${entry}`);
|
|
@@ -32033,8 +33169,8 @@ class FileScanner {
|
|
|
32033
33169
|
return files;
|
|
32034
33170
|
}
|
|
32035
33171
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
32036
|
-
const destSubDir =
|
|
32037
|
-
const sourceSubDir =
|
|
33172
|
+
const destSubDir = join28(destDir, subPath);
|
|
33173
|
+
const sourceSubDir = join28(sourceDir, subPath);
|
|
32038
33174
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
32039
33175
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
32040
33176
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -32044,7 +33180,7 @@ class FileScanner {
|
|
|
32044
33180
|
const sourceFiles = await FileScanner.getFiles(sourceSubDir, sourceDir);
|
|
32045
33181
|
logger.debug(`findCustomFiles - destFiles count: ${destFiles.length}`);
|
|
32046
33182
|
logger.debug(`findCustomFiles - sourceFiles count: ${sourceFiles.length}`);
|
|
32047
|
-
const sourceExists = await
|
|
33183
|
+
const sourceExists = await import_fs_extra16.pathExists(sourceSubDir);
|
|
32048
33184
|
if (sourceExists && sourceFiles.length === 0 && destFiles.length > 100) {
|
|
32049
33185
|
logger.warning(`Source directory exists but is empty while destination has ${destFiles.length} files. This may indicate an extraction issue. Skipping custom file detection.`);
|
|
32050
33186
|
return [];
|
|
@@ -32072,10 +33208,10 @@ class FileScanner {
|
|
|
32072
33208
|
}
|
|
32073
33209
|
|
|
32074
33210
|
// src/services/transformers/commands-prefix.ts
|
|
32075
|
-
import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as
|
|
32076
|
-
import { join as
|
|
33211
|
+
import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as stat5 } from "node:fs/promises";
|
|
33212
|
+
import { join as join29 } from "node:path";
|
|
32077
33213
|
init_logger();
|
|
32078
|
-
var
|
|
33214
|
+
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
32079
33215
|
function stripWindowsDrivePrefix(path9) {
|
|
32080
33216
|
if (path9.length >= 2 && /[a-zA-Z]/.test(path9[0]) && path9[1] === ":") {
|
|
32081
33217
|
return path9.slice(2);
|
|
@@ -32114,14 +33250,14 @@ function validatePath4(path9, paramName) {
|
|
|
32114
33250
|
class CommandsPrefix {
|
|
32115
33251
|
static async applyPrefix(extractDir) {
|
|
32116
33252
|
validatePath4(extractDir, "extractDir");
|
|
32117
|
-
const commandsDir =
|
|
32118
|
-
if (!await
|
|
33253
|
+
const commandsDir = join29(extractDir, ".claude", "commands");
|
|
33254
|
+
if (!await import_fs_extra17.pathExists(commandsDir)) {
|
|
32119
33255
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
32120
33256
|
return;
|
|
32121
33257
|
}
|
|
32122
33258
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
32123
|
-
const backupDir =
|
|
32124
|
-
const tempDir =
|
|
33259
|
+
const backupDir = join29(extractDir, ".commands-backup");
|
|
33260
|
+
const tempDir = join29(extractDir, ".commands-prefix-temp");
|
|
32125
33261
|
try {
|
|
32126
33262
|
const entries = await readdir11(commandsDir);
|
|
32127
33263
|
if (entries.length === 0) {
|
|
@@ -32129,28 +33265,28 @@ class CommandsPrefix {
|
|
|
32129
33265
|
return;
|
|
32130
33266
|
}
|
|
32131
33267
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
32132
|
-
const ckDir2 =
|
|
32133
|
-
const ckStat = await
|
|
33268
|
+
const ckDir2 = join29(commandsDir, "ck");
|
|
33269
|
+
const ckStat = await stat5(ckDir2);
|
|
32134
33270
|
if (ckStat.isDirectory()) {
|
|
32135
33271
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
32136
33272
|
return;
|
|
32137
33273
|
}
|
|
32138
33274
|
}
|
|
32139
|
-
await
|
|
33275
|
+
await import_fs_extra17.copy(commandsDir, backupDir);
|
|
32140
33276
|
logger.verbose("Created backup of commands directory");
|
|
32141
33277
|
await mkdir10(tempDir, { recursive: true });
|
|
32142
|
-
const ckDir =
|
|
33278
|
+
const ckDir = join29(tempDir, "ck");
|
|
32143
33279
|
await mkdir10(ckDir, { recursive: true });
|
|
32144
33280
|
let processedCount = 0;
|
|
32145
33281
|
for (const entry of entries) {
|
|
32146
|
-
const sourcePath =
|
|
33282
|
+
const sourcePath = join29(commandsDir, entry);
|
|
32147
33283
|
const stats = await lstat3(sourcePath);
|
|
32148
33284
|
if (stats.isSymbolicLink()) {
|
|
32149
33285
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
32150
33286
|
continue;
|
|
32151
33287
|
}
|
|
32152
|
-
const destPath =
|
|
32153
|
-
await
|
|
33288
|
+
const destPath = join29(ckDir, entry);
|
|
33289
|
+
await import_fs_extra17.copy(sourcePath, destPath, {
|
|
32154
33290
|
overwrite: false,
|
|
32155
33291
|
errorOnExist: true
|
|
32156
33292
|
});
|
|
@@ -32159,35 +33295,35 @@ class CommandsPrefix {
|
|
|
32159
33295
|
}
|
|
32160
33296
|
if (processedCount === 0) {
|
|
32161
33297
|
logger.warning("No files to move (all were symlinks or invalid)");
|
|
32162
|
-
await
|
|
32163
|
-
await
|
|
33298
|
+
await import_fs_extra17.remove(backupDir);
|
|
33299
|
+
await import_fs_extra17.remove(tempDir);
|
|
32164
33300
|
return;
|
|
32165
33301
|
}
|
|
32166
|
-
await
|
|
32167
|
-
await
|
|
32168
|
-
await
|
|
33302
|
+
await import_fs_extra17.remove(commandsDir);
|
|
33303
|
+
await import_fs_extra17.move(tempDir, commandsDir);
|
|
33304
|
+
await import_fs_extra17.remove(backupDir);
|
|
32169
33305
|
logger.success("Successfully applied /ck: prefix to all commands");
|
|
32170
33306
|
} catch (error) {
|
|
32171
|
-
if (await
|
|
33307
|
+
if (await import_fs_extra17.pathExists(backupDir)) {
|
|
32172
33308
|
try {
|
|
32173
|
-
await
|
|
32174
|
-
await
|
|
33309
|
+
await import_fs_extra17.remove(commandsDir).catch(() => {});
|
|
33310
|
+
await import_fs_extra17.move(backupDir, commandsDir);
|
|
32175
33311
|
logger.info("Restored original commands directory from backup");
|
|
32176
33312
|
} catch (rollbackError) {
|
|
32177
33313
|
logger.error(`Rollback failed: ${rollbackError}`);
|
|
32178
33314
|
}
|
|
32179
33315
|
}
|
|
32180
|
-
if (await
|
|
32181
|
-
await
|
|
33316
|
+
if (await import_fs_extra17.pathExists(tempDir)) {
|
|
33317
|
+
await import_fs_extra17.remove(tempDir).catch(() => {});
|
|
32182
33318
|
}
|
|
32183
33319
|
logger.error("Failed to apply /ck: prefix to commands");
|
|
32184
33320
|
throw error;
|
|
32185
33321
|
} finally {
|
|
32186
|
-
if (await
|
|
32187
|
-
await
|
|
33322
|
+
if (await import_fs_extra17.pathExists(backupDir)) {
|
|
33323
|
+
await import_fs_extra17.remove(backupDir).catch(() => {});
|
|
32188
33324
|
}
|
|
32189
|
-
if (await
|
|
32190
|
-
await
|
|
33325
|
+
if (await import_fs_extra17.pathExists(tempDir)) {
|
|
33326
|
+
await import_fs_extra17.remove(tempDir).catch(() => {});
|
|
32191
33327
|
}
|
|
32192
33328
|
}
|
|
32193
33329
|
}
|
|
@@ -32197,15 +33333,15 @@ class CommandsPrefix {
|
|
|
32197
33333
|
static async cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
32198
33334
|
const { dryRun = false, forceOverwrite = false } = options;
|
|
32199
33335
|
validatePath4(targetDir, "targetDir");
|
|
32200
|
-
const claudeDir = isGlobal ? targetDir :
|
|
32201
|
-
const commandsDir =
|
|
33336
|
+
const claudeDir = isGlobal ? targetDir : join29(targetDir, ".claude");
|
|
33337
|
+
const commandsDir = join29(claudeDir, "commands");
|
|
32202
33338
|
const result = {
|
|
32203
33339
|
results: [],
|
|
32204
33340
|
deletedCount: 0,
|
|
32205
33341
|
preservedCount: 0,
|
|
32206
33342
|
wasDryRun: dryRun
|
|
32207
33343
|
};
|
|
32208
|
-
if (!await
|
|
33344
|
+
if (!await import_fs_extra17.pathExists(commandsDir)) {
|
|
32209
33345
|
logger.verbose(`Commands directory does not exist: ${commandsDir}`);
|
|
32210
33346
|
return result;
|
|
32211
33347
|
}
|
|
@@ -32215,7 +33351,8 @@ class CommandsPrefix {
|
|
|
32215
33351
|
logger.info("Checking ownership before cleanup...");
|
|
32216
33352
|
}
|
|
32217
33353
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
32218
|
-
|
|
33354
|
+
const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
|
|
33355
|
+
if (!metadata || allTrackedFiles.length === 0) {
|
|
32219
33356
|
logger.verbose("No ownership metadata found - skipping cleanup (legacy/fresh install)");
|
|
32220
33357
|
logger.verbose("All existing files will be preserved as user-owned");
|
|
32221
33358
|
return result;
|
|
@@ -32226,7 +33363,7 @@ class CommandsPrefix {
|
|
|
32226
33363
|
return result;
|
|
32227
33364
|
}
|
|
32228
33365
|
for (const entry of entries) {
|
|
32229
|
-
const entryPath =
|
|
33366
|
+
const entryPath = join29(commandsDir, entry);
|
|
32230
33367
|
const stats = await lstat3(entryPath);
|
|
32231
33368
|
if (stats.isSymbolicLink()) {
|
|
32232
33369
|
logger.warning(`Skipping symlink: ${entry}`);
|
|
@@ -32252,7 +33389,7 @@ class CommandsPrefix {
|
|
|
32252
33389
|
action: "delete"
|
|
32253
33390
|
});
|
|
32254
33391
|
if (!dryRun) {
|
|
32255
|
-
await
|
|
33392
|
+
await import_fs_extra17.remove(file);
|
|
32256
33393
|
logger.verbose(`Deleted CK file: ${relativePath}`);
|
|
32257
33394
|
}
|
|
32258
33395
|
result.deletedCount++;
|
|
@@ -32265,7 +33402,7 @@ class CommandsPrefix {
|
|
|
32265
33402
|
reason: "force overwrite"
|
|
32266
33403
|
});
|
|
32267
33404
|
if (!dryRun) {
|
|
32268
|
-
await
|
|
33405
|
+
await import_fs_extra17.remove(file);
|
|
32269
33406
|
logger.verbose(`Force-deleted modified file: ${relativePath}`);
|
|
32270
33407
|
}
|
|
32271
33408
|
result.deletedCount++;
|
|
@@ -32289,7 +33426,7 @@ class CommandsPrefix {
|
|
|
32289
33426
|
reason: "force overwrite"
|
|
32290
33427
|
});
|
|
32291
33428
|
if (!dryRun) {
|
|
32292
|
-
await
|
|
33429
|
+
await import_fs_extra17.remove(file);
|
|
32293
33430
|
logger.verbose(`Force-deleted user file: ${relativePath}`);
|
|
32294
33431
|
}
|
|
32295
33432
|
result.deletedCount++;
|
|
@@ -32307,7 +33444,7 @@ class CommandsPrefix {
|
|
|
32307
33444
|
}
|
|
32308
33445
|
}
|
|
32309
33446
|
if (canDeleteDir && !dryRun) {
|
|
32310
|
-
await
|
|
33447
|
+
await import_fs_extra17.remove(entryPath);
|
|
32311
33448
|
logger.verbose(`Removed directory: ${entry}`);
|
|
32312
33449
|
}
|
|
32313
33450
|
} else {
|
|
@@ -32320,7 +33457,7 @@ class CommandsPrefix {
|
|
|
32320
33457
|
action: "delete"
|
|
32321
33458
|
});
|
|
32322
33459
|
if (!dryRun) {
|
|
32323
|
-
await
|
|
33460
|
+
await import_fs_extra17.remove(entryPath);
|
|
32324
33461
|
logger.verbose(`Deleted CK file: ${entry}`);
|
|
32325
33462
|
}
|
|
32326
33463
|
result.deletedCount++;
|
|
@@ -32333,7 +33470,7 @@ class CommandsPrefix {
|
|
|
32333
33470
|
reason: "force overwrite"
|
|
32334
33471
|
});
|
|
32335
33472
|
if (!dryRun) {
|
|
32336
|
-
await
|
|
33473
|
+
await import_fs_extra17.remove(entryPath);
|
|
32337
33474
|
logger.verbose(`Force-deleted modified file: ${entry}`);
|
|
32338
33475
|
}
|
|
32339
33476
|
result.deletedCount++;
|
|
@@ -32356,7 +33493,7 @@ class CommandsPrefix {
|
|
|
32356
33493
|
reason: "force overwrite"
|
|
32357
33494
|
});
|
|
32358
33495
|
if (!dryRun) {
|
|
32359
|
-
await
|
|
33496
|
+
await import_fs_extra17.remove(entryPath);
|
|
32360
33497
|
logger.verbose(`Force-deleted user file: ${entry}`);
|
|
32361
33498
|
}
|
|
32362
33499
|
result.deletedCount++;
|
|
@@ -32392,7 +33529,7 @@ class CommandsPrefix {
|
|
|
32392
33529
|
const files = [];
|
|
32393
33530
|
const entries = await readdir11(dir);
|
|
32394
33531
|
for (const entry of entries) {
|
|
32395
|
-
const fullPath =
|
|
33532
|
+
const fullPath = join29(dir, entry);
|
|
32396
33533
|
const stats = await lstat3(fullPath);
|
|
32397
33534
|
if (stats.isSymbolicLink()) {
|
|
32398
33535
|
continue;
|
|
@@ -32410,9 +33547,9 @@ class CommandsPrefix {
|
|
|
32410
33547
|
// src/services/transformers/folder-path-transformer.ts
|
|
32411
33548
|
init_logger();
|
|
32412
33549
|
init_types2();
|
|
32413
|
-
var
|
|
32414
|
-
import { readFile as
|
|
32415
|
-
import { join as
|
|
33550
|
+
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
33551
|
+
import { readFile as readFile16, readdir as readdir12, rename as rename3, writeFile as writeFile14 } from "node:fs/promises";
|
|
33552
|
+
import { join as join30, relative as relative8 } from "node:path";
|
|
32416
33553
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
32417
33554
|
".md",
|
|
32418
33555
|
".txt",
|
|
@@ -32458,34 +33595,34 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
32458
33595
|
}
|
|
32459
33596
|
const dirsToRename = [];
|
|
32460
33597
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
32461
|
-
const docsPath =
|
|
32462
|
-
if (await
|
|
33598
|
+
const docsPath = join30(extractDir, DEFAULT_FOLDERS.docs);
|
|
33599
|
+
if (await import_fs_extra18.pathExists(docsPath)) {
|
|
32463
33600
|
dirsToRename.push({
|
|
32464
33601
|
from: docsPath,
|
|
32465
|
-
to:
|
|
33602
|
+
to: join30(extractDir, folders.docs)
|
|
32466
33603
|
});
|
|
32467
33604
|
}
|
|
32468
|
-
const claudeDocsPath =
|
|
32469
|
-
if (await
|
|
33605
|
+
const claudeDocsPath = join30(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
33606
|
+
if (await import_fs_extra18.pathExists(claudeDocsPath)) {
|
|
32470
33607
|
dirsToRename.push({
|
|
32471
33608
|
from: claudeDocsPath,
|
|
32472
|
-
to:
|
|
33609
|
+
to: join30(extractDir, ".claude", folders.docs)
|
|
32473
33610
|
});
|
|
32474
33611
|
}
|
|
32475
33612
|
}
|
|
32476
33613
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
32477
|
-
const plansPath =
|
|
32478
|
-
if (await
|
|
33614
|
+
const plansPath = join30(extractDir, DEFAULT_FOLDERS.plans);
|
|
33615
|
+
if (await import_fs_extra18.pathExists(plansPath)) {
|
|
32479
33616
|
dirsToRename.push({
|
|
32480
33617
|
from: plansPath,
|
|
32481
|
-
to:
|
|
33618
|
+
to: join30(extractDir, folders.plans)
|
|
32482
33619
|
});
|
|
32483
33620
|
}
|
|
32484
|
-
const claudePlansPath =
|
|
32485
|
-
if (await
|
|
33621
|
+
const claudePlansPath = join30(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
33622
|
+
if (await import_fs_extra18.pathExists(claudePlansPath)) {
|
|
32486
33623
|
dirsToRename.push({
|
|
32487
33624
|
from: claudePlansPath,
|
|
32488
|
-
to:
|
|
33625
|
+
to: join30(extractDir, ".claude", folders.plans)
|
|
32489
33626
|
});
|
|
32490
33627
|
}
|
|
32491
33628
|
}
|
|
@@ -32522,7 +33659,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32522
33659
|
let replacementsCount = 0;
|
|
32523
33660
|
const entries = await readdir12(dir, { withFileTypes: true });
|
|
32524
33661
|
for (const entry of entries) {
|
|
32525
|
-
const fullPath =
|
|
33662
|
+
const fullPath = join30(dir, entry.name);
|
|
32526
33663
|
if (entry.isDirectory()) {
|
|
32527
33664
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
32528
33665
|
continue;
|
|
@@ -32535,7 +33672,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32535
33672
|
if (!shouldTransform)
|
|
32536
33673
|
continue;
|
|
32537
33674
|
try {
|
|
32538
|
-
const content = await
|
|
33675
|
+
const content = await readFile16(fullPath, "utf-8");
|
|
32539
33676
|
let newContent = content;
|
|
32540
33677
|
let changeCount = 0;
|
|
32541
33678
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -32551,7 +33688,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32551
33688
|
if (options.dryRun) {
|
|
32552
33689
|
logger.debug(`[dry-run] Would update ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
32553
33690
|
} else {
|
|
32554
|
-
await
|
|
33691
|
+
await writeFile14(fullPath, newContent, "utf-8");
|
|
32555
33692
|
logger.debug(`Updated ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
32556
33693
|
}
|
|
32557
33694
|
filesChanged++;
|
|
@@ -32631,9 +33768,9 @@ function validateFolderName(name2) {
|
|
|
32631
33768
|
|
|
32632
33769
|
// src/services/transformers/global-path-transformer.ts
|
|
32633
33770
|
init_logger();
|
|
32634
|
-
import { readFile as
|
|
33771
|
+
import { readFile as readFile17, readdir as readdir13, writeFile as writeFile15 } from "node:fs/promises";
|
|
32635
33772
|
import { platform as platform9 } from "node:os";
|
|
32636
|
-
import { extname, join as
|
|
33773
|
+
import { extname, join as join31 } from "node:path";
|
|
32637
33774
|
var IS_WINDOWS2 = platform9() === "win32";
|
|
32638
33775
|
var HOME_PREFIX = IS_WINDOWS2 ? "%USERPROFILE%" : "$HOME";
|
|
32639
33776
|
function getHomeDirPrefix() {
|
|
@@ -32725,7 +33862,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
32725
33862
|
async function processDirectory(dir) {
|
|
32726
33863
|
const entries = await readdir13(dir, { withFileTypes: true });
|
|
32727
33864
|
for (const entry of entries) {
|
|
32728
|
-
const fullPath =
|
|
33865
|
+
const fullPath = join31(dir, entry.name);
|
|
32729
33866
|
if (entry.isDirectory()) {
|
|
32730
33867
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
32731
33868
|
continue;
|
|
@@ -32733,10 +33870,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
32733
33870
|
await processDirectory(fullPath);
|
|
32734
33871
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
32735
33872
|
try {
|
|
32736
|
-
const content = await
|
|
33873
|
+
const content = await readFile17(fullPath, "utf-8");
|
|
32737
33874
|
const { transformed, changes } = transformContent(content);
|
|
32738
33875
|
if (changes > 0) {
|
|
32739
|
-
await
|
|
33876
|
+
await writeFile15(fullPath, transformed, "utf-8");
|
|
32740
33877
|
filesTransformed++;
|
|
32741
33878
|
totalChanges += changes;
|
|
32742
33879
|
if (options.verbose) {
|
|
@@ -32767,7 +33904,7 @@ init_environment();
|
|
|
32767
33904
|
init_logger();
|
|
32768
33905
|
init_output_manager();
|
|
32769
33906
|
init_types2();
|
|
32770
|
-
var
|
|
33907
|
+
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
32771
33908
|
async function initCommand(options) {
|
|
32772
33909
|
const prompts = new PromptsManager;
|
|
32773
33910
|
prompts.intro("\uD83D\uDD27 ClaudeKit - Initialize/Update Project");
|
|
@@ -32786,8 +33923,8 @@ async function initCommand(options) {
|
|
|
32786
33923
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
32787
33924
|
const cwdResolved = resolve6(process.cwd());
|
|
32788
33925
|
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve6(globalKitDir, "..");
|
|
32789
|
-
const localSettingsPath =
|
|
32790
|
-
if (!isInGlobalDir && await
|
|
33926
|
+
const localSettingsPath = join32(process.cwd(), ".claude", "settings.json");
|
|
33927
|
+
if (!isInGlobalDir && await import_fs_extra19.pathExists(localSettingsPath)) {
|
|
32791
33928
|
if (isNonInteractive2) {
|
|
32792
33929
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
32793
33930
|
logger.warning("Consider removing local installation: rm -rf .claude");
|
|
@@ -32798,9 +33935,9 @@ async function initCommand(options) {
|
|
|
32798
33935
|
return;
|
|
32799
33936
|
}
|
|
32800
33937
|
if (choice === "remove") {
|
|
32801
|
-
const localClaudeDir =
|
|
33938
|
+
const localClaudeDir = join32(process.cwd(), ".claude");
|
|
32802
33939
|
try {
|
|
32803
|
-
await
|
|
33940
|
+
await import_fs_extra19.remove(localClaudeDir);
|
|
32804
33941
|
logger.success("Removed local .claude/ directory");
|
|
32805
33942
|
} catch (error) {
|
|
32806
33943
|
logger.error(`Failed to remove local installation: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -32844,7 +33981,7 @@ async function initCommand(options) {
|
|
|
32844
33981
|
}
|
|
32845
33982
|
const resolvedDir = resolve6(targetDir);
|
|
32846
33983
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32847
|
-
if (!await
|
|
33984
|
+
if (!await import_fs_extra19.pathExists(resolvedDir)) {
|
|
32848
33985
|
if (validOptions.global) {
|
|
32849
33986
|
const { mkdir: mkdir11 } = await import("node:fs/promises");
|
|
32850
33987
|
await mkdir11(resolvedDir, { recursive: true });
|
|
@@ -32857,7 +33994,7 @@ async function initCommand(options) {
|
|
|
32857
33994
|
}
|
|
32858
33995
|
if (validOptions.fresh) {
|
|
32859
33996
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
32860
|
-
const claudeDir2 = prefix ?
|
|
33997
|
+
const claudeDir2 = prefix ? join32(resolvedDir, prefix) : resolvedDir;
|
|
32861
33998
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
32862
33999
|
if (!canProceed) {
|
|
32863
34000
|
return;
|
|
@@ -32885,7 +34022,7 @@ async function initCommand(options) {
|
|
|
32885
34022
|
logger.info("Fetching available versions...");
|
|
32886
34023
|
let currentVersion = null;
|
|
32887
34024
|
try {
|
|
32888
|
-
const metadataPath = validOptions.global ?
|
|
34025
|
+
const metadataPath = validOptions.global ? join32(PathResolver.getGlobalKitDir(), "metadata.json") : join32(resolvedDir, ".claude", "metadata.json");
|
|
32889
34026
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
32890
34027
|
currentVersion = metadata?.version || null;
|
|
32891
34028
|
if (currentVersion) {
|
|
@@ -33010,9 +34147,9 @@ async function initCommand(options) {
|
|
|
33010
34147
|
}
|
|
33011
34148
|
}
|
|
33012
34149
|
if (!validOptions.fresh) {
|
|
33013
|
-
const newSkillsDir =
|
|
34150
|
+
const newSkillsDir = join32(extractDir, ".claude", "skills");
|
|
33014
34151
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
33015
|
-
if (await
|
|
34152
|
+
if (await import_fs_extra19.pathExists(newSkillsDir) && await import_fs_extra19.pathExists(currentSkillsDir)) {
|
|
33016
34153
|
logger.info("Checking for skills directory migration...");
|
|
33017
34154
|
const migrationDetection = await SkillsMigrationDetector.detectMigration(newSkillsDir, currentSkillsDir);
|
|
33018
34155
|
if (migrationDetection.status === "recommended" || migrationDetection.status === "required") {
|
|
@@ -33035,7 +34172,7 @@ async function initCommand(options) {
|
|
|
33035
34172
|
let customClaudeFiles = [];
|
|
33036
34173
|
if (!validOptions.fresh) {
|
|
33037
34174
|
logger.info("Scanning for custom .claude files...");
|
|
33038
|
-
const scanSourceDir = validOptions.global ?
|
|
34175
|
+
const scanSourceDir = validOptions.global ? join32(extractDir, ".claude") : extractDir;
|
|
33039
34176
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
33040
34177
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
33041
34178
|
} else {
|
|
@@ -33070,9 +34207,12 @@ async function initCommand(options) {
|
|
|
33070
34207
|
}
|
|
33071
34208
|
merger.setGlobalFlag(validOptions.global);
|
|
33072
34209
|
merger.setForceOverwriteSettings(validOptions.forceOverwriteSettings);
|
|
33073
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
34210
|
+
const claudeDir = validOptions.global ? resolvedDir : join32(resolvedDir, ".claude");
|
|
33074
34211
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
33075
|
-
if (
|
|
34212
|
+
if (releaseManifest) {
|
|
34213
|
+
merger.setManifest(releaseManifest);
|
|
34214
|
+
}
|
|
34215
|
+
if (!validOptions.fresh && await import_fs_extra19.pathExists(claudeDir)) {
|
|
33076
34216
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
33077
34217
|
if (legacyDetection.isLegacy && releaseManifest) {
|
|
33078
34218
|
logger.info("Legacy installation detected - migrating to ownership tracking...");
|
|
@@ -33092,7 +34232,7 @@ async function initCommand(options) {
|
|
|
33092
34232
|
return;
|
|
33093
34233
|
}
|
|
33094
34234
|
}
|
|
33095
|
-
const sourceDir = validOptions.global ?
|
|
34235
|
+
const sourceDir = validOptions.global ? join32(extractDir, ".claude") : extractDir;
|
|
33096
34236
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
33097
34237
|
const manifestWriter = new ManifestWriter;
|
|
33098
34238
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -33101,7 +34241,7 @@ async function initCommand(options) {
|
|
|
33101
34241
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
33102
34242
|
continue;
|
|
33103
34243
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
33104
|
-
const filePath =
|
|
34244
|
+
const filePath = join32(claudeDir, relativePath);
|
|
33105
34245
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
33106
34246
|
const ownership = manifestEntry ? "ck" : "user";
|
|
33107
34247
|
filesToTrack.push({
|
|
@@ -33120,13 +34260,13 @@ async function initCommand(options) {
|
|
|
33120
34260
|
}
|
|
33121
34261
|
});
|
|
33122
34262
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
33123
|
-
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
34263
|
+
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local", kit);
|
|
33124
34264
|
if (validOptions.global) {
|
|
33125
|
-
const claudeMdSource =
|
|
33126
|
-
const claudeMdDest =
|
|
33127
|
-
if (await
|
|
33128
|
-
if (!await
|
|
33129
|
-
await
|
|
34265
|
+
const claudeMdSource = join32(extractDir, "CLAUDE.md");
|
|
34266
|
+
const claudeMdDest = join32(resolvedDir, "CLAUDE.md");
|
|
34267
|
+
if (await import_fs_extra19.pathExists(claudeMdSource)) {
|
|
34268
|
+
if (!await import_fs_extra19.pathExists(claudeMdDest)) {
|
|
34269
|
+
await import_fs_extra19.copy(claudeMdSource, claudeMdDest);
|
|
33130
34270
|
logger.success("Copied CLAUDE.md to global directory");
|
|
33131
34271
|
} else {
|
|
33132
34272
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -33165,8 +34305,8 @@ async function initCommand(options) {
|
|
|
33165
34305
|
}
|
|
33166
34306
|
}
|
|
33167
34307
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
33168
|
-
const envPath =
|
|
33169
|
-
if (!await
|
|
34308
|
+
const envPath = join32(claudeDir, ".env");
|
|
34309
|
+
if (!await import_fs_extra19.pathExists(envPath)) {
|
|
33170
34310
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
33171
34311
|
if (shouldSetup) {
|
|
33172
34312
|
await runSetupWizard({
|
|
@@ -33196,13 +34336,13 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
33196
34336
|
}
|
|
33197
34337
|
|
|
33198
34338
|
// src/commands/new.ts
|
|
33199
|
-
import { join as
|
|
34339
|
+
import { join as join33, resolve as resolve7 } from "node:path";
|
|
33200
34340
|
init_package_installer();
|
|
33201
34341
|
init_environment();
|
|
33202
34342
|
init_logger();
|
|
33203
34343
|
init_output_manager();
|
|
33204
34344
|
init_types2();
|
|
33205
|
-
var
|
|
34345
|
+
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
33206
34346
|
async function newCommand(options) {
|
|
33207
34347
|
const prompts = new PromptsManager;
|
|
33208
34348
|
prompts.intro("\uD83D\uDE80 ClaudeKit - Create New Project");
|
|
@@ -33229,8 +34369,8 @@ async function newCommand(options) {
|
|
|
33229
34369
|
}
|
|
33230
34370
|
const resolvedDir = resolve7(targetDir);
|
|
33231
34371
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
33232
|
-
if (await
|
|
33233
|
-
const files = await
|
|
34372
|
+
if (await import_fs_extra20.pathExists(resolvedDir)) {
|
|
34373
|
+
const files = await import_fs_extra20.readdir(resolvedDir);
|
|
33234
34374
|
const isEmpty = files.length === 0;
|
|
33235
34375
|
if (!isEmpty) {
|
|
33236
34376
|
if (isNonInteractive2) {
|
|
@@ -33377,7 +34517,7 @@ async function newCommand(options) {
|
|
|
33377
34517
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
33378
34518
|
}
|
|
33379
34519
|
await merger.merge(extractDir, resolvedDir, true);
|
|
33380
|
-
const claudeDir =
|
|
34520
|
+
const claudeDir = join33(resolvedDir, ".claude");
|
|
33381
34521
|
const manifestWriter = new ManifestWriter;
|
|
33382
34522
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
33383
34523
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -33386,7 +34526,7 @@ async function newCommand(options) {
|
|
|
33386
34526
|
if (!installedPath.startsWith(".claude/"))
|
|
33387
34527
|
continue;
|
|
33388
34528
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
33389
|
-
const filePath =
|
|
34529
|
+
const filePath = join33(claudeDir, relativePath);
|
|
33390
34530
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
33391
34531
|
const ownership = manifestEntry ? "ck" : "user";
|
|
33392
34532
|
filesToTrack.push({
|
|
@@ -33439,10 +34579,10 @@ async function newCommand(options) {
|
|
|
33439
34579
|
|
|
33440
34580
|
// src/commands/uninstall.ts
|
|
33441
34581
|
import { readdirSync, rmSync } from "node:fs";
|
|
33442
|
-
import { dirname as dirname7, join as
|
|
34582
|
+
import { dirname as dirname7, join as join34 } from "node:path";
|
|
33443
34583
|
init_logger();
|
|
33444
34584
|
init_types2();
|
|
33445
|
-
var
|
|
34585
|
+
var import_fs_extra21 = __toESM(require_lib(), 1);
|
|
33446
34586
|
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
33447
34587
|
async function detectInstallations() {
|
|
33448
34588
|
const installations = [];
|
|
@@ -33451,14 +34591,14 @@ async function detectInstallations() {
|
|
|
33451
34591
|
installations.push({
|
|
33452
34592
|
type: "local",
|
|
33453
34593
|
path: setup.project.path,
|
|
33454
|
-
exists: await
|
|
34594
|
+
exists: await import_fs_extra21.pathExists(setup.project.path)
|
|
33455
34595
|
});
|
|
33456
34596
|
}
|
|
33457
34597
|
if (setup.global.path && setup.global.metadata) {
|
|
33458
34598
|
installations.push({
|
|
33459
34599
|
type: "global",
|
|
33460
34600
|
path: setup.global.path,
|
|
33461
|
-
exists: await
|
|
34601
|
+
exists: await import_fs_extra21.pathExists(setup.global.path)
|
|
33462
34602
|
});
|
|
33463
34603
|
}
|
|
33464
34604
|
return installations.filter((i) => i.exists);
|
|
@@ -33491,14 +34631,26 @@ async function promptScope(installations) {
|
|
|
33491
34631
|
}
|
|
33492
34632
|
return selected;
|
|
33493
34633
|
}
|
|
33494
|
-
async function confirmUninstall(scope) {
|
|
34634
|
+
async function confirmUninstall(scope, kitLabel = "") {
|
|
33495
34635
|
const scopeText = scope === "all" ? "all ClaudeKit installations" : scope === "local" ? "local ClaudeKit installation" : "global ClaudeKit installation";
|
|
33496
34636
|
const confirmed = await se({
|
|
33497
|
-
message: `Continue with uninstalling ${scopeText}?`,
|
|
34637
|
+
message: `Continue with uninstalling ${scopeText}${kitLabel}?`,
|
|
33498
34638
|
initialValue: false
|
|
33499
34639
|
});
|
|
33500
34640
|
return confirmed === true;
|
|
33501
34641
|
}
|
|
34642
|
+
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
34643
|
+
if (ownership === "ck") {
|
|
34644
|
+
return { action: "delete", reason: deleteReason };
|
|
34645
|
+
}
|
|
34646
|
+
if (ownership === "ck-modified") {
|
|
34647
|
+
if (forceOverwrite) {
|
|
34648
|
+
return { action: "delete", reason: "force overwrite" };
|
|
34649
|
+
}
|
|
34650
|
+
return { action: "preserve", reason: "modified by user" };
|
|
34651
|
+
}
|
|
34652
|
+
return { action: "preserve", reason: "user-created" };
|
|
34653
|
+
}
|
|
33502
34654
|
async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
33503
34655
|
let cleaned = 0;
|
|
33504
34656
|
let currentDir = dirname7(filePath);
|
|
@@ -33519,33 +34671,57 @@ async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
|
33519
34671
|
}
|
|
33520
34672
|
return cleaned;
|
|
33521
34673
|
}
|
|
33522
|
-
async function analyzeInstallation(installation, forceOverwrite) {
|
|
33523
|
-
const result = {
|
|
34674
|
+
async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
34675
|
+
const result = {
|
|
34676
|
+
toDelete: [],
|
|
34677
|
+
toPreserve: [],
|
|
34678
|
+
remainingKits: []
|
|
34679
|
+
};
|
|
33524
34680
|
const metadata = await ManifestWriter.readManifest(installation.path);
|
|
33525
|
-
|
|
33526
|
-
|
|
33527
|
-
|
|
33528
|
-
|
|
34681
|
+
const uninstallManifest = await ManifestWriter.getUninstallManifest(installation.path, kit);
|
|
34682
|
+
result.remainingKits = uninstallManifest.remainingKits;
|
|
34683
|
+
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
34684
|
+
const kitFiles = metadata.kits[kit].files || [];
|
|
34685
|
+
for (const trackedFile of kitFiles) {
|
|
34686
|
+
const filePath = join34(installation.path, trackedFile.path);
|
|
34687
|
+
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
34688
|
+
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
34689
|
+
continue;
|
|
34690
|
+
}
|
|
34691
|
+
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
34692
|
+
if (!ownershipResult.exists)
|
|
34693
|
+
continue;
|
|
34694
|
+
const classification = classifyFileByOwnership(ownershipResult.ownership, forceOverwrite, `${kit} kit (pristine)`);
|
|
34695
|
+
if (classification.action === "delete") {
|
|
34696
|
+
result.toDelete.push({ path: trackedFile.path, reason: classification.reason });
|
|
34697
|
+
} else {
|
|
34698
|
+
result.toPreserve.push({ path: trackedFile.path, reason: classification.reason });
|
|
34699
|
+
}
|
|
34700
|
+
}
|
|
34701
|
+
if (result.remainingKits.length === 0) {
|
|
34702
|
+
result.toDelete.push({ path: "metadata.json", reason: "metadata file" });
|
|
34703
|
+
}
|
|
34704
|
+
return result;
|
|
34705
|
+
}
|
|
34706
|
+
const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
|
|
34707
|
+
if (!metadata || allTrackedFiles.length === 0) {
|
|
34708
|
+
for (const item of uninstallManifest.filesToRemove) {
|
|
34709
|
+
if (!uninstallManifest.filesToPreserve.includes(item)) {
|
|
33529
34710
|
result.toDelete.push({ path: item, reason: "legacy installation" });
|
|
33530
34711
|
}
|
|
33531
34712
|
}
|
|
33532
34713
|
return result;
|
|
33533
34714
|
}
|
|
33534
|
-
for (const trackedFile of
|
|
33535
|
-
const filePath =
|
|
34715
|
+
for (const trackedFile of allTrackedFiles) {
|
|
34716
|
+
const filePath = join34(installation.path, trackedFile.path);
|
|
33536
34717
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
33537
34718
|
if (!ownershipResult.exists)
|
|
33538
34719
|
continue;
|
|
33539
|
-
|
|
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.1",
|
|
33835
35044
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
33836
35045
|
type: "module",
|
|
33837
35046
|
repository: {
|
|
@@ -33851,7 +35060,7 @@ var package_default2 = {
|
|
|
33851
35060
|
],
|
|
33852
35061
|
scripts: {
|
|
33853
35062
|
dev: "bun run src/index.ts",
|
|
33854
|
-
build: "bun build src/index.ts --outdir dist --target node --external
|
|
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");
|