claudekit-cli 3.12.1 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +803 -546
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4094,24 +4094,10 @@ function supportsUnicode() {
|
|
|
4094
4094
|
function isTTY() {
|
|
4095
4095
|
return process.stdout.isTTY === true;
|
|
4096
4096
|
}
|
|
4097
|
-
|
|
4098
|
-
return supportsUnicode() ? UNICODE_SYMBOLS : ASCII_SYMBOLS;
|
|
4099
|
-
}
|
|
4100
|
-
var import_picocolors, UNICODE_SYMBOLS, ASCII_SYMBOLS, COLOR_PALETTE;
|
|
4097
|
+
var import_picocolors, COLOR_PALETTE;
|
|
4101
4098
|
var init_terminal_utils = __esm(() => {
|
|
4099
|
+
init_output_manager();
|
|
4102
4100
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
4103
|
-
UNICODE_SYMBOLS = {
|
|
4104
|
-
pass: "✓",
|
|
4105
|
-
warn: "⚠",
|
|
4106
|
-
fail: "✗",
|
|
4107
|
-
info: "ℹ"
|
|
4108
|
-
};
|
|
4109
|
-
ASCII_SYMBOLS = {
|
|
4110
|
-
pass: "[PASS]",
|
|
4111
|
-
warn: "[WARN]",
|
|
4112
|
-
fail: "[FAIL]",
|
|
4113
|
-
info: "[INFO]"
|
|
4114
|
-
};
|
|
4115
4101
|
COLOR_PALETTE = {
|
|
4116
4102
|
pass: import_picocolors.default.green,
|
|
4117
4103
|
warn: import_picocolors.default.yellow,
|
|
@@ -4123,6 +4109,16 @@ var init_terminal_utils = __esm(() => {
|
|
|
4123
4109
|
});
|
|
4124
4110
|
|
|
4125
4111
|
// src/shared/output-manager.ts
|
|
4112
|
+
function getStatusSymbols() {
|
|
4113
|
+
const symbolSet = supportsUnicode() ? SYMBOLS.unicode : SYMBOLS.ascii;
|
|
4114
|
+
return {
|
|
4115
|
+
pass: symbolSet.pass,
|
|
4116
|
+
warn: symbolSet.warn,
|
|
4117
|
+
fail: symbolSet.fail,
|
|
4118
|
+
info: symbolSet.infoStatus
|
|
4119
|
+
};
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4126
4122
|
class OutputManager {
|
|
4127
4123
|
config = {
|
|
4128
4124
|
verbose: false,
|
|
@@ -4132,6 +4128,7 @@ class OutputManager {
|
|
|
4132
4128
|
jsonBuffer = [];
|
|
4133
4129
|
unicodeSupported;
|
|
4134
4130
|
flushPromise = null;
|
|
4131
|
+
flushQueued = false;
|
|
4135
4132
|
constructor() {
|
|
4136
4133
|
this.unicodeSupported = supportsUnicode();
|
|
4137
4134
|
}
|
|
@@ -4237,8 +4234,12 @@ class OutputManager {
|
|
|
4237
4234
|
...entry,
|
|
4238
4235
|
timestamp: new Date().toISOString()
|
|
4239
4236
|
});
|
|
4240
|
-
if (this.jsonBuffer.length >= 1000 && !this.flushPromise) {
|
|
4241
|
-
|
|
4237
|
+
if (this.jsonBuffer.length >= 1000 && !this.flushPromise && !this.flushQueued) {
|
|
4238
|
+
this.flushQueued = true;
|
|
4239
|
+
queueMicrotask(() => {
|
|
4240
|
+
this.flushQueued = false;
|
|
4241
|
+
this.flushJson();
|
|
4242
|
+
});
|
|
4242
4243
|
}
|
|
4243
4244
|
}
|
|
4244
4245
|
addJsonResult(data) {
|
|
@@ -4268,6 +4269,7 @@ class OutputManager {
|
|
|
4268
4269
|
this.config = { verbose: false, json: false, quiet: false };
|
|
4269
4270
|
this.jsonBuffer = [];
|
|
4270
4271
|
this.flushPromise = null;
|
|
4272
|
+
this.flushQueued = false;
|
|
4271
4273
|
this.unicodeSupported = supportsUnicode();
|
|
4272
4274
|
}
|
|
4273
4275
|
}
|
|
@@ -4285,7 +4287,11 @@ var init_output_manager = __esm(() => {
|
|
|
4285
4287
|
line: "│",
|
|
4286
4288
|
selected: "●",
|
|
4287
4289
|
unselected: "○",
|
|
4288
|
-
pointer: ">"
|
|
4290
|
+
pointer: ">",
|
|
4291
|
+
pass: "✓",
|
|
4292
|
+
warn: "⚠",
|
|
4293
|
+
fail: "✗",
|
|
4294
|
+
infoStatus: "ℹ"
|
|
4289
4295
|
},
|
|
4290
4296
|
ascii: {
|
|
4291
4297
|
prompt: "?",
|
|
@@ -4296,7 +4302,11 @@ var init_output_manager = __esm(() => {
|
|
|
4296
4302
|
line: "|",
|
|
4297
4303
|
selected: ">",
|
|
4298
4304
|
unselected: " ",
|
|
4299
|
-
pointer: ">"
|
|
4305
|
+
pointer: ">",
|
|
4306
|
+
pass: "[PASS]",
|
|
4307
|
+
warn: "[WARN]",
|
|
4308
|
+
fail: "[FAIL]",
|
|
4309
|
+
infoStatus: "[INFO]"
|
|
4300
4310
|
}
|
|
4301
4311
|
};
|
|
4302
4312
|
output = new OutputManager;
|
|
@@ -4308,6 +4318,7 @@ import { createWriteStream } from "node:fs";
|
|
|
4308
4318
|
class Logger {
|
|
4309
4319
|
verboseEnabled = false;
|
|
4310
4320
|
logFileStream;
|
|
4321
|
+
exitHandlerRegistered = false;
|
|
4311
4322
|
info(message) {
|
|
4312
4323
|
const symbols = output.getSymbols();
|
|
4313
4324
|
console.log(import_picocolors3.default.blue(symbols.info), message);
|
|
@@ -4362,9 +4373,49 @@ class Logger {
|
|
|
4362
4373
|
flags: "a",
|
|
4363
4374
|
mode: 384
|
|
4364
4375
|
});
|
|
4376
|
+
this.registerExitHandler();
|
|
4365
4377
|
this.verbose(`Logging to file: ${path}`);
|
|
4366
4378
|
}
|
|
4367
4379
|
}
|
|
4380
|
+
close() {
|
|
4381
|
+
if (this.logFileStream) {
|
|
4382
|
+
this.logFileStream.end();
|
|
4383
|
+
this.logFileStream = undefined;
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
registerExitHandler() {
|
|
4387
|
+
if (this.exitHandlerRegistered)
|
|
4388
|
+
return;
|
|
4389
|
+
this.exitHandlerRegistered = true;
|
|
4390
|
+
const cleanup = () => {
|
|
4391
|
+
if (this.logFileStream) {
|
|
4392
|
+
try {
|
|
4393
|
+
this.logFileStream.end();
|
|
4394
|
+
} catch {}
|
|
4395
|
+
this.logFileStream = undefined;
|
|
4396
|
+
}
|
|
4397
|
+
};
|
|
4398
|
+
process.on("exit", cleanup);
|
|
4399
|
+
process.on("SIGINT", () => {
|
|
4400
|
+
cleanup();
|
|
4401
|
+
process.exit(130);
|
|
4402
|
+
});
|
|
4403
|
+
process.on("SIGTERM", () => {
|
|
4404
|
+
cleanup();
|
|
4405
|
+
process.exit(143);
|
|
4406
|
+
});
|
|
4407
|
+
process.on("uncaughtException", (error) => {
|
|
4408
|
+
if (this.logFileStream) {
|
|
4409
|
+
const timestamp = new Date().toISOString();
|
|
4410
|
+
this.logFileStream.write(`${timestamp} [FATAL] Uncaught exception: ${error.message}
|
|
4411
|
+
`);
|
|
4412
|
+
this.logFileStream.write(`${error.stack}
|
|
4413
|
+
`);
|
|
4414
|
+
}
|
|
4415
|
+
cleanup();
|
|
4416
|
+
process.exit(1);
|
|
4417
|
+
});
|
|
4418
|
+
}
|
|
4368
4419
|
sanitize(text) {
|
|
4369
4420
|
return text.replace(/ghp_[a-zA-Z0-9]{36}/g, "ghp_***").replace(/github_pat_[a-zA-Z0-9_]{82}/g, "github_pat_***").replace(/gho_[a-zA-Z0-9]{36}/g, "gho_***").replace(/ghu_[a-zA-Z0-9]{36}/g, "ghu_***").replace(/ghs_[a-zA-Z0-9]{36}/g, "ghs_***").replace(/ghr_[a-zA-Z0-9]{36}/g, "ghr_***").replace(/Bearer [a-zA-Z0-9_-]+/g, "Bearer ***").replace(/token=[a-zA-Z0-9_-]+/g, "token=***");
|
|
4370
4421
|
}
|
|
@@ -6487,6 +6538,35 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
6487
6538
|
};
|
|
6488
6539
|
});
|
|
6489
6540
|
|
|
6541
|
+
// src/shared/environment.ts
|
|
6542
|
+
function isCIEnvironment() {
|
|
6543
|
+
return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
|
|
6544
|
+
}
|
|
6545
|
+
function isNonInteractive() {
|
|
6546
|
+
return !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
6547
|
+
}
|
|
6548
|
+
function isMacOS() {
|
|
6549
|
+
return process.platform === "darwin";
|
|
6550
|
+
}
|
|
6551
|
+
function isWindows() {
|
|
6552
|
+
return process.platform === "win32";
|
|
6553
|
+
}
|
|
6554
|
+
function getOptimalConcurrency() {
|
|
6555
|
+
if (isMacOS())
|
|
6556
|
+
return PLATFORM_CONCURRENCY.MACOS;
|
|
6557
|
+
if (isWindows())
|
|
6558
|
+
return PLATFORM_CONCURRENCY.WINDOWS;
|
|
6559
|
+
return PLATFORM_CONCURRENCY.LINUX;
|
|
6560
|
+
}
|
|
6561
|
+
var PLATFORM_CONCURRENCY;
|
|
6562
|
+
var init_environment = __esm(() => {
|
|
6563
|
+
PLATFORM_CONCURRENCY = {
|
|
6564
|
+
MACOS: 10,
|
|
6565
|
+
WINDOWS: 15,
|
|
6566
|
+
LINUX: 20
|
|
6567
|
+
};
|
|
6568
|
+
});
|
|
6569
|
+
|
|
6490
6570
|
// src/types/kit.ts
|
|
6491
6571
|
var KitType, KitConfigSchema, AVAILABLE_KITS, NEVER_COPY_PATTERNS, USER_CONFIG_PATTERNS, PROTECTED_PATTERNS;
|
|
6492
6572
|
var init_kit = __esm(() => {
|
|
@@ -6561,6 +6641,7 @@ var init_commands = __esm(() => {
|
|
|
6561
6641
|
opencode: exports_external.boolean().default(false),
|
|
6562
6642
|
gemini: exports_external.boolean().default(false),
|
|
6563
6643
|
installSkills: exports_external.boolean().default(false),
|
|
6644
|
+
withSudo: exports_external.boolean().default(false),
|
|
6564
6645
|
prefix: exports_external.boolean().default(false),
|
|
6565
6646
|
beta: exports_external.boolean().default(false),
|
|
6566
6647
|
dryRun: exports_external.boolean().default(false),
|
|
@@ -6578,6 +6659,7 @@ var init_commands = __esm(() => {
|
|
|
6578
6659
|
global: exports_external.boolean().default(false),
|
|
6579
6660
|
fresh: exports_external.boolean().default(false),
|
|
6580
6661
|
installSkills: exports_external.boolean().default(false),
|
|
6662
|
+
withSudo: exports_external.boolean().default(false),
|
|
6581
6663
|
prefix: exports_external.boolean().default(false),
|
|
6582
6664
|
beta: exports_external.boolean().default(false),
|
|
6583
6665
|
dryRun: exports_external.boolean().default(false),
|
|
@@ -6914,35 +6996,6 @@ var require_umd = __commonJS((exports, module) => {
|
|
|
6914
6996
|
});
|
|
6915
6997
|
});
|
|
6916
6998
|
|
|
6917
|
-
// src/shared/environment.ts
|
|
6918
|
-
function isCIEnvironment() {
|
|
6919
|
-
return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
|
|
6920
|
-
}
|
|
6921
|
-
function isNonInteractive() {
|
|
6922
|
-
return !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
6923
|
-
}
|
|
6924
|
-
function isMacOS() {
|
|
6925
|
-
return process.platform === "darwin";
|
|
6926
|
-
}
|
|
6927
|
-
function isWindows4() {
|
|
6928
|
-
return process.platform === "win32";
|
|
6929
|
-
}
|
|
6930
|
-
function getOptimalConcurrency() {
|
|
6931
|
-
if (isMacOS())
|
|
6932
|
-
return PLATFORM_CONCURRENCY.MACOS;
|
|
6933
|
-
if (isWindows4())
|
|
6934
|
-
return PLATFORM_CONCURRENCY.WINDOWS;
|
|
6935
|
-
return PLATFORM_CONCURRENCY.LINUX;
|
|
6936
|
-
}
|
|
6937
|
-
var PLATFORM_CONCURRENCY;
|
|
6938
|
-
var init_environment = __esm(() => {
|
|
6939
|
-
PLATFORM_CONCURRENCY = {
|
|
6940
|
-
MACOS: 10,
|
|
6941
|
-
WINDOWS: 15,
|
|
6942
|
-
LINUX: 20
|
|
6943
|
-
};
|
|
6944
|
-
});
|
|
6945
|
-
|
|
6946
6999
|
// node_modules/sisteransi/src/index.js
|
|
6947
7000
|
var require_src = __commonJS((exports, module) => {
|
|
6948
7001
|
var ESC = "\x1B";
|
|
@@ -7891,9 +7944,8 @@ function validatePackageName(packageName) {
|
|
|
7891
7944
|
function validateScriptPath(skillsDir, scriptPath) {
|
|
7892
7945
|
const skillsDirResolved = resolve2(skillsDir);
|
|
7893
7946
|
const scriptPathResolved = resolve2(scriptPath);
|
|
7894
|
-
const
|
|
7895
|
-
const
|
|
7896
|
-
const scriptPathNormalized = isWindows5 ? scriptPathResolved.toLowerCase() : scriptPathResolved;
|
|
7947
|
+
const skillsDirNormalized = isWindows() ? skillsDirResolved.toLowerCase() : skillsDirResolved;
|
|
7948
|
+
const scriptPathNormalized = isWindows() ? scriptPathResolved.toLowerCase() : scriptPathResolved;
|
|
7897
7949
|
if (!scriptPathNormalized.startsWith(skillsDirNormalized)) {
|
|
7898
7950
|
throw new Error(`Script path outside skills directory: ${scriptPath}`);
|
|
7899
7951
|
}
|
|
@@ -7908,6 +7960,7 @@ function validateScriptPath(skillsDir, scriptPath) {
|
|
|
7908
7960
|
}
|
|
7909
7961
|
var NPM_PACKAGE_REGEX;
|
|
7910
7962
|
var init_validators = __esm(() => {
|
|
7963
|
+
init_environment();
|
|
7911
7964
|
init_logger();
|
|
7912
7965
|
NPM_PACKAGE_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
7913
7966
|
});
|
|
@@ -8239,7 +8292,8 @@ var init_install_error_handler = __esm(() => {
|
|
|
8239
8292
|
|
|
8240
8293
|
// src/services/package-installer/skills-installer.ts
|
|
8241
8294
|
import { join as join18 } from "node:path";
|
|
8242
|
-
async function installSkillsDependencies(skillsDir) {
|
|
8295
|
+
async function installSkillsDependencies(skillsDir, options = {}) {
|
|
8296
|
+
const { skipConfirm = false, withSudo = false } = options;
|
|
8243
8297
|
const displayName = "Skills Dependencies";
|
|
8244
8298
|
if (isCIEnvironment()) {
|
|
8245
8299
|
logger.info("CI environment detected: skipping skills installation");
|
|
@@ -8249,7 +8303,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
8249
8303
|
error: "Installation skipped in CI environment"
|
|
8250
8304
|
};
|
|
8251
8305
|
}
|
|
8252
|
-
if (isNonInteractive()) {
|
|
8306
|
+
if (isNonInteractive() && !skipConfirm) {
|
|
8253
8307
|
logger.info("Running in non-interactive mode. Skipping skills installation.");
|
|
8254
8308
|
logger.info("See INSTALLATION.md for manual installation instructions.");
|
|
8255
8309
|
return {
|
|
@@ -8311,11 +8365,15 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
8311
8365
|
logger.verbose("Could not preview script contents");
|
|
8312
8366
|
}
|
|
8313
8367
|
}
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8368
|
+
let shouldProceed = skipConfirm;
|
|
8369
|
+
if (!skipConfirm) {
|
|
8370
|
+
const userChoice = await clack.confirm({
|
|
8371
|
+
message: "Execute this installation script?",
|
|
8372
|
+
initialValue: false
|
|
8373
|
+
});
|
|
8374
|
+
shouldProceed = !clack.isCancel(userChoice) && userChoice;
|
|
8375
|
+
}
|
|
8376
|
+
if (!shouldProceed) {
|
|
8319
8377
|
logger.info("Installation cancelled by user");
|
|
8320
8378
|
logger.info("");
|
|
8321
8379
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
@@ -8333,8 +8391,8 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
8333
8391
|
logger.info(`Running: ${scriptPath}`);
|
|
8334
8392
|
const scriptArgs = ["--yes"];
|
|
8335
8393
|
if (hasInstallState(skillsDir)) {
|
|
8336
|
-
if (isNonInteractive()) {
|
|
8337
|
-
logger.info("Resuming previous installation
|
|
8394
|
+
if (skipConfirm || isNonInteractive()) {
|
|
8395
|
+
logger.info("Resuming previous installation...");
|
|
8338
8396
|
scriptArgs.push("--resume");
|
|
8339
8397
|
} else {
|
|
8340
8398
|
const shouldResume = await clack.confirm({
|
|
@@ -8350,9 +8408,27 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
8350
8408
|
if (platform5 === "linux") {
|
|
8351
8409
|
const needsSudo = await checkNeedsSudoPackages();
|
|
8352
8410
|
if (needsSudo) {
|
|
8353
|
-
if (
|
|
8354
|
-
logger.info("
|
|
8355
|
-
logger.
|
|
8411
|
+
if (withSudo) {
|
|
8412
|
+
logger.info("");
|
|
8413
|
+
logger.warning("Installing system packages with sudo:");
|
|
8414
|
+
logger.info(" • ffmpeg - Video/audio processing");
|
|
8415
|
+
logger.info(" • imagemagick - Image editing & conversion");
|
|
8416
|
+
logger.info("");
|
|
8417
|
+
logger.info("sudo will run: apt-get install -y ffmpeg imagemagick");
|
|
8418
|
+
logger.info("");
|
|
8419
|
+
scriptArgs.push("--with-sudo");
|
|
8420
|
+
} else if (skipConfirm || isNonInteractive()) {
|
|
8421
|
+
logger.info("");
|
|
8422
|
+
logger.warning("System packages skipped (not included without --with-sudo):");
|
|
8423
|
+
logger.info(" • ffmpeg - Video/audio processing");
|
|
8424
|
+
logger.info(" • imagemagick - Image editing & conversion");
|
|
8425
|
+
logger.info("");
|
|
8426
|
+
logger.info("To include system packages, run with --with-sudo flag:");
|
|
8427
|
+
logger.info(" ck init -g -y --install-skills --with-sudo");
|
|
8428
|
+
logger.info("");
|
|
8429
|
+
logger.info("Or install manually:");
|
|
8430
|
+
logger.info(" sudo apt-get install -y ffmpeg imagemagick");
|
|
8431
|
+
logger.info("");
|
|
8356
8432
|
} else {
|
|
8357
8433
|
logger.info("");
|
|
8358
8434
|
logger.info("System packages (requires sudo):");
|
|
@@ -8364,6 +8440,8 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
8364
8440
|
initialValue: true
|
|
8365
8441
|
});
|
|
8366
8442
|
if (!clack.isCancel(shouldInstallSudo) && shouldInstallSudo) {
|
|
8443
|
+
logger.info("");
|
|
8444
|
+
logger.info("sudo will run: apt-get install -y ffmpeg imagemagick");
|
|
8367
8445
|
scriptArgs.push("--with-sudo");
|
|
8368
8446
|
} else {
|
|
8369
8447
|
logger.info("Skipping system packages. Install manually later:");
|
|
@@ -8440,9 +8518,9 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
8440
8518
|
};
|
|
8441
8519
|
}
|
|
8442
8520
|
}
|
|
8443
|
-
async function handleSkillsInstallation(skillsDir) {
|
|
8521
|
+
async function handleSkillsInstallation(skillsDir, options = {}) {
|
|
8444
8522
|
try {
|
|
8445
|
-
const skillsResult = await installSkillsDependencies(skillsDir);
|
|
8523
|
+
const skillsResult = await installSkillsDependencies(skillsDir, options);
|
|
8446
8524
|
if (skillsResult.success) {
|
|
8447
8525
|
if (skillsResult.version === PARTIAL_INSTALL_VERSION) {
|
|
8448
8526
|
logger.success("Skills core dependencies installed (some optional packages skipped)");
|
|
@@ -8630,7 +8708,6 @@ import { existsSync as existsSync14 } from "node:fs";
|
|
|
8630
8708
|
import { mkdir as mkdir6, symlink as symlink2 } from "node:fs/promises";
|
|
8631
8709
|
import { dirname as dirname4, join as join21 } from "node:path";
|
|
8632
8710
|
async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
8633
|
-
const isWindows5 = process.platform === "win32";
|
|
8634
8711
|
const linkDir = dirname4(linkPath);
|
|
8635
8712
|
if (!existsSync14(linkDir)) {
|
|
8636
8713
|
await mkdir6(linkDir, { recursive: true });
|
|
@@ -8645,7 +8722,7 @@ async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
|
8645
8722
|
symlinkTarget = isLocalConfig ? "../.mcp.json" : targetPath;
|
|
8646
8723
|
}
|
|
8647
8724
|
try {
|
|
8648
|
-
await symlink2(symlinkTarget, linkPath,
|
|
8725
|
+
await symlink2(symlinkTarget, linkPath, isWindows() ? "file" : undefined);
|
|
8649
8726
|
logger.debug(`Created symlink: ${linkPath} → ${symlinkTarget}`);
|
|
8650
8727
|
return { success: true, method: "symlink", targetPath, geminiSettingsPath: linkPath };
|
|
8651
8728
|
} catch (error) {
|
|
@@ -8658,6 +8735,7 @@ async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
|
8658
8735
|
}
|
|
8659
8736
|
}
|
|
8660
8737
|
var init_linker_core = __esm(() => {
|
|
8738
|
+
init_environment();
|
|
8661
8739
|
init_logger();
|
|
8662
8740
|
init_validation();
|
|
8663
8741
|
});
|
|
@@ -15745,9 +15823,19 @@ import { exec as exec4 } from "node:child_process";
|
|
|
15745
15823
|
import { promisify as promisify4 } from "node:util";
|
|
15746
15824
|
|
|
15747
15825
|
// src/services/package-installer/dependency-checker.ts
|
|
15748
|
-
init_logger();
|
|
15749
15826
|
import { exec } from "node:child_process";
|
|
15750
15827
|
import { promisify } from "node:util";
|
|
15828
|
+
|
|
15829
|
+
// src/shared/error-utils.ts
|
|
15830
|
+
function operationError(operation, subject, details) {
|
|
15831
|
+
return `${operation} failed for '${subject}': ${details}`;
|
|
15832
|
+
}
|
|
15833
|
+
function notFoundError(type, name, hint) {
|
|
15834
|
+
return hint ? `${type} not found: ${name} (${hint})` : `${type} not found: ${name}`;
|
|
15835
|
+
}
|
|
15836
|
+
|
|
15837
|
+
// src/services/package-installer/dependency-checker.ts
|
|
15838
|
+
init_logger();
|
|
15751
15839
|
var execAsync = promisify(exec);
|
|
15752
15840
|
function shouldSkipExpensiveOperations() {
|
|
15753
15841
|
if (process.env.CK_TEST_HOME) {
|
|
@@ -15780,13 +15868,30 @@ function getCICommandPath(command) {
|
|
|
15780
15868
|
const osInfo = getOSInfo();
|
|
15781
15869
|
switch (command) {
|
|
15782
15870
|
case "node":
|
|
15783
|
-
|
|
15871
|
+
if (osInfo.isWindows) {
|
|
15872
|
+
return process.env.NODE_PATH ? `${process.env.NODE_PATH}\\node.exe` : "C:\\Program Files\\nodejs\\node.exe";
|
|
15873
|
+
}
|
|
15874
|
+
return "/usr/bin/node";
|
|
15784
15875
|
case "python3":
|
|
15785
15876
|
case "python":
|
|
15786
|
-
|
|
15877
|
+
if (osInfo.isWindows) {
|
|
15878
|
+
const pythonDir = process.env.PYTHON;
|
|
15879
|
+
if (pythonDir) {
|
|
15880
|
+
return `${pythonDir}\\python.exe`;
|
|
15881
|
+
}
|
|
15882
|
+
return "C:\\Windows\\py.exe";
|
|
15883
|
+
}
|
|
15884
|
+
return "/usr/bin/python3";
|
|
15787
15885
|
case "pip3":
|
|
15788
15886
|
case "pip":
|
|
15789
|
-
|
|
15887
|
+
if (osInfo.isWindows) {
|
|
15888
|
+
const pythonDir = process.env.PYTHON;
|
|
15889
|
+
if (pythonDir) {
|
|
15890
|
+
return `${pythonDir}\\Scripts\\pip.exe`;
|
|
15891
|
+
}
|
|
15892
|
+
return "C:\\Windows\\py.exe -m pip";
|
|
15893
|
+
}
|
|
15894
|
+
return "/usr/bin/pip3";
|
|
15790
15895
|
default:
|
|
15791
15896
|
return null;
|
|
15792
15897
|
}
|
|
@@ -15932,7 +16037,7 @@ async function checkDependency(config) {
|
|
|
15932
16037
|
installed: false,
|
|
15933
16038
|
meetsRequirements: false,
|
|
15934
16039
|
minVersion: config.minVersion,
|
|
15935
|
-
message:
|
|
16040
|
+
message: notFoundError(config.name, "PATH", "check installation")
|
|
15936
16041
|
};
|
|
15937
16042
|
}
|
|
15938
16043
|
async function checkAllDependencies() {
|
|
@@ -16412,8 +16517,8 @@ class PathResolver {
|
|
|
16412
16517
|
static getTestHomeDir() {
|
|
16413
16518
|
return process.env.CK_TEST_HOME;
|
|
16414
16519
|
}
|
|
16415
|
-
static
|
|
16416
|
-
if (!
|
|
16520
|
+
static isValidComponentName(name) {
|
|
16521
|
+
if (!name || typeof name !== "string") {
|
|
16417
16522
|
return false;
|
|
16418
16523
|
}
|
|
16419
16524
|
const dangerousPatterns = [
|
|
@@ -16421,17 +16526,17 @@ class PathResolver {
|
|
|
16421
16526
|
"~"
|
|
16422
16527
|
];
|
|
16423
16528
|
for (const pattern of dangerousPatterns) {
|
|
16424
|
-
if (
|
|
16529
|
+
if (name.includes(pattern)) {
|
|
16425
16530
|
return false;
|
|
16426
16531
|
}
|
|
16427
16532
|
}
|
|
16428
|
-
const normalized = normalize(
|
|
16533
|
+
const normalized = normalize(name);
|
|
16429
16534
|
for (const pattern of dangerousPatterns) {
|
|
16430
16535
|
if (normalized.includes(pattern)) {
|
|
16431
16536
|
return false;
|
|
16432
16537
|
}
|
|
16433
16538
|
}
|
|
16434
|
-
if (
|
|
16539
|
+
if (name.startsWith("/") || normalized.startsWith("/") || /^[a-zA-Z]:/.test(name)) {
|
|
16435
16540
|
return false;
|
|
16436
16541
|
}
|
|
16437
16542
|
return true;
|
|
@@ -16495,7 +16600,7 @@ class PathResolver {
|
|
|
16495
16600
|
return join(baseDir, "skills");
|
|
16496
16601
|
}
|
|
16497
16602
|
static buildComponentPath(baseDir, component, global2) {
|
|
16498
|
-
if (!PathResolver.
|
|
16603
|
+
if (!PathResolver.isValidComponentName(component)) {
|
|
16499
16604
|
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "workflows", "skills", or "hooks".`);
|
|
16500
16605
|
}
|
|
16501
16606
|
const prefix = PathResolver.getPathPrefix(global2);
|
|
@@ -16685,11 +16790,11 @@ function isValidVersion(version) {
|
|
|
16685
16790
|
return /^[a-zA-Z0-9._-]+$/.test(version);
|
|
16686
16791
|
}
|
|
16687
16792
|
// src/domains/installation/package-managers/npm-detector.ts
|
|
16688
|
-
|
|
16793
|
+
init_environment();
|
|
16689
16794
|
function getNpmQuery() {
|
|
16690
16795
|
return {
|
|
16691
16796
|
pm: "npm",
|
|
16692
|
-
cmd: isWindows ? "npm.cmd ls -g claudekit-cli --depth=0 --json" : "npm ls -g claudekit-cli --depth=0 --json",
|
|
16797
|
+
cmd: isWindows() ? "npm.cmd ls -g claudekit-cli --depth=0 --json" : "npm ls -g claudekit-cli --depth=0 --json",
|
|
16693
16798
|
checkFn: (stdout) => {
|
|
16694
16799
|
try {
|
|
16695
16800
|
const data = JSON.parse(stdout);
|
|
@@ -16701,7 +16806,7 @@ function getNpmQuery() {
|
|
|
16701
16806
|
};
|
|
16702
16807
|
}
|
|
16703
16808
|
function getNpmVersionCommand() {
|
|
16704
|
-
return isWindows ? "npm.cmd --version" : "npm --version";
|
|
16809
|
+
return isWindows() ? "npm.cmd --version" : "npm --version";
|
|
16705
16810
|
}
|
|
16706
16811
|
async function getNpmVersion() {
|
|
16707
16812
|
try {
|
|
@@ -16719,7 +16824,7 @@ function getNpmUpdateCommand(packageName, version) {
|
|
|
16719
16824
|
throw new Error(`Invalid version: ${version}`);
|
|
16720
16825
|
}
|
|
16721
16826
|
const versionSuffix = version ? `@${version}` : "@latest";
|
|
16722
|
-
return isWindows ? `npm.cmd install -g ${packageName}${versionSuffix}` : `npm install -g ${packageName}${versionSuffix}`;
|
|
16827
|
+
return isWindows() ? `npm.cmd install -g ${packageName}${versionSuffix}` : `npm install -g ${packageName}${versionSuffix}`;
|
|
16723
16828
|
}
|
|
16724
16829
|
// src/domains/installation/package-managers/bun-detector.ts
|
|
16725
16830
|
function getBunQuery() {
|
|
@@ -16751,16 +16856,16 @@ function getBunUpdateCommand(packageName, version) {
|
|
|
16751
16856
|
return `bun add -g ${packageName}${versionSuffix}`;
|
|
16752
16857
|
}
|
|
16753
16858
|
// src/domains/installation/package-managers/yarn-detector.ts
|
|
16754
|
-
|
|
16859
|
+
init_environment();
|
|
16755
16860
|
function getYarnQuery() {
|
|
16756
16861
|
return {
|
|
16757
16862
|
pm: "yarn",
|
|
16758
|
-
cmd:
|
|
16863
|
+
cmd: isWindows() ? "yarn.cmd global list --pattern claudekit-cli" : "yarn global list --pattern claudekit-cli",
|
|
16759
16864
|
checkFn: (stdout) => stdout.includes("claudekit-cli")
|
|
16760
16865
|
};
|
|
16761
16866
|
}
|
|
16762
16867
|
function getYarnVersionCommand() {
|
|
16763
|
-
return
|
|
16868
|
+
return isWindows() ? "yarn.cmd --version" : "yarn --version";
|
|
16764
16869
|
}
|
|
16765
16870
|
async function getYarnVersion() {
|
|
16766
16871
|
try {
|
|
@@ -16778,19 +16883,19 @@ function getYarnUpdateCommand(packageName, version) {
|
|
|
16778
16883
|
throw new Error(`Invalid version: ${version}`);
|
|
16779
16884
|
}
|
|
16780
16885
|
const versionSuffix = version ? `@${version}` : "@latest";
|
|
16781
|
-
return
|
|
16886
|
+
return isWindows() ? `yarn.cmd global add ${packageName}${versionSuffix}` : `yarn global add ${packageName}${versionSuffix}`;
|
|
16782
16887
|
}
|
|
16783
16888
|
// src/domains/installation/package-managers/pnpm-detector.ts
|
|
16784
|
-
|
|
16889
|
+
init_environment();
|
|
16785
16890
|
function getPnpmQuery() {
|
|
16786
16891
|
return {
|
|
16787
16892
|
pm: "pnpm",
|
|
16788
|
-
cmd:
|
|
16893
|
+
cmd: isWindows() ? "pnpm.cmd ls -g claudekit-cli" : "pnpm ls -g claudekit-cli",
|
|
16789
16894
|
checkFn: (stdout) => stdout.includes("claudekit-cli")
|
|
16790
16895
|
};
|
|
16791
16896
|
}
|
|
16792
16897
|
function getPnpmVersionCommand() {
|
|
16793
|
-
return
|
|
16898
|
+
return isWindows() ? "pnpm.cmd --version" : "pnpm --version";
|
|
16794
16899
|
}
|
|
16795
16900
|
async function getPnpmVersion() {
|
|
16796
16901
|
try {
|
|
@@ -16808,7 +16913,7 @@ function getPnpmUpdateCommand(packageName, version) {
|
|
|
16808
16913
|
throw new Error(`Invalid version: ${version}`);
|
|
16809
16914
|
}
|
|
16810
16915
|
const versionSuffix = version ? `@${version}` : "@latest";
|
|
16811
|
-
return
|
|
16916
|
+
return isWindows() ? `pnpm.cmd add -g ${packageName}${versionSuffix}` : `pnpm add -g ${packageName}${versionSuffix}`;
|
|
16812
16917
|
}
|
|
16813
16918
|
// src/domains/installation/package-managers/detection-core.ts
|
|
16814
16919
|
init_logger();
|
|
@@ -19808,6 +19913,7 @@ function normalizeVersionTag(version) {
|
|
|
19808
19913
|
return trimmed.startsWith("v") ? trimmed : `v${trimmed}`;
|
|
19809
19914
|
}
|
|
19810
19915
|
// src/domains/versioning/selection/selection-ui.ts
|
|
19916
|
+
init_environment();
|
|
19811
19917
|
init_logger();
|
|
19812
19918
|
init_dist2();
|
|
19813
19919
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
@@ -19965,6 +20071,11 @@ This could be due to:
|
|
|
19965
20071
|
if (!allowManualEntry) {
|
|
19966
20072
|
throw new Error(`No releases available for ${kit.name}`);
|
|
19967
20073
|
}
|
|
20074
|
+
if (isNonInteractive()) {
|
|
20075
|
+
logger.warning(`Non-interactive mode: no releases found for ${kit.name}`);
|
|
20076
|
+
logger.info("Provide a specific version with --version flag or run in interactive mode");
|
|
20077
|
+
return null;
|
|
20078
|
+
}
|
|
19968
20079
|
const tryManual = await se({
|
|
19969
20080
|
message: "Would you like to enter a version manually?"
|
|
19970
20081
|
});
|
|
@@ -19974,6 +20085,11 @@ This could be due to:
|
|
|
19974
20085
|
return await getManualVersion(kit);
|
|
19975
20086
|
}
|
|
19976
20087
|
async function getManualVersion(kit) {
|
|
20088
|
+
if (isNonInteractive()) {
|
|
20089
|
+
logger.warning("Non-interactive mode: cannot prompt for manual version entry");
|
|
20090
|
+
logger.info("Provide a specific version with --version flag");
|
|
20091
|
+
return null;
|
|
20092
|
+
}
|
|
19977
20093
|
const version = await te({
|
|
19978
20094
|
message: `Enter version tag for ${kit.name}:`,
|
|
19979
20095
|
placeholder: "v1.0.0",
|
|
@@ -19993,6 +20109,19 @@ async function getManualVersion(kit) {
|
|
|
19993
20109
|
return normalizeVersionTag(version);
|
|
19994
20110
|
}
|
|
19995
20111
|
async function createVersionPrompt(kit, choices, _defaultIndex, allowManualEntry, releases, currentVersion = null) {
|
|
20112
|
+
if (isNonInteractive()) {
|
|
20113
|
+
const latestStable2 = releases.find((r2) => r2.isLatestStable && !r2.prerelease);
|
|
20114
|
+
if (latestStable2) {
|
|
20115
|
+
logger.info(`Non-interactive mode: selecting latest stable version ${latestStable2.tag_name}`);
|
|
20116
|
+
return latestStable2.tag_name;
|
|
20117
|
+
}
|
|
20118
|
+
if (releases.length > 0) {
|
|
20119
|
+
logger.info(`Non-interactive mode: selecting version ${releases[0].tag_name}`);
|
|
20120
|
+
return releases[0].tag_name;
|
|
20121
|
+
}
|
|
20122
|
+
logger.warning("Non-interactive mode: no versions available");
|
|
20123
|
+
return null;
|
|
20124
|
+
}
|
|
19996
20125
|
const clackChoices = [];
|
|
19997
20126
|
const latestStable = releases.find((r2) => r2.isLatestStable && !r2.prerelease);
|
|
19998
20127
|
if (latestStable) {
|
|
@@ -20060,6 +20189,10 @@ async function handleSelectionError(error, kit, allowManualEntry, retryCallback)
|
|
|
20060
20189
|
} else {
|
|
20061
20190
|
le(VersionDisplayFormatter.formatError(error.message || "Unknown error occurred", "Please try again or contact support"), import_picocolors10.default.red("Error"));
|
|
20062
20191
|
}
|
|
20192
|
+
if (isNonInteractive()) {
|
|
20193
|
+
logger.warning("Non-interactive mode: version selection failed, cannot retry");
|
|
20194
|
+
return null;
|
|
20195
|
+
}
|
|
20063
20196
|
if (allowManualEntry) {
|
|
20064
20197
|
const retry2 = await se({
|
|
20065
20198
|
message: "Would you like to try entering a version manually?"
|
|
@@ -27629,10 +27762,10 @@ import path6 from "node:path";
|
|
|
27629
27762
|
// node_modules/tar/dist/esm/get-write-flag.js
|
|
27630
27763
|
import fs6 from "fs";
|
|
27631
27764
|
var platform6 = process.env.__FAKE_PLATFORM__ || process.platform;
|
|
27632
|
-
var
|
|
27765
|
+
var isWindows2 = platform6 === "win32";
|
|
27633
27766
|
var { O_CREAT, O_TRUNC, O_WRONLY } = fs6.constants;
|
|
27634
27767
|
var UV_FS_O_FILEMAP = Number(process.env.__FAKE_FS_O_FILENAME__) || fs6.constants.UV_FS_O_FILEMAP || 0;
|
|
27635
|
-
var fMapEnabled =
|
|
27768
|
+
var fMapEnabled = isWindows2 && !!UV_FS_O_FILEMAP;
|
|
27636
27769
|
var fMapLimit = 512 * 1024;
|
|
27637
27770
|
var fMapFlag = UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY;
|
|
27638
27771
|
var getWriteFlag = !fMapEnabled ? () => "w" : (size) => size < fMapLimit ? fMapFlag : "w";
|
|
@@ -27921,7 +28054,7 @@ var normalizeUnicode = (s) => {
|
|
|
27921
28054
|
|
|
27922
28055
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
27923
28056
|
var platform7 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
27924
|
-
var
|
|
28057
|
+
var isWindows3 = platform7 === "win32";
|
|
27925
28058
|
var getDirs = (path6) => {
|
|
27926
28059
|
const dirs = path6.split("/").slice(0, -1).reduce((set, path7) => {
|
|
27927
28060
|
const s = set[set.length - 1];
|
|
@@ -27939,7 +28072,7 @@ class PathReservations {
|
|
|
27939
28072
|
#reservations = new Map;
|
|
27940
28073
|
#running = new Set;
|
|
27941
28074
|
reserve(paths, fn) {
|
|
27942
|
-
paths =
|
|
28075
|
+
paths = isWindows3 ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
27943
28076
|
return stripTrailingSlashes(join25(normalizeUnicode(p))).toLowerCase();
|
|
27944
28077
|
});
|
|
27945
28078
|
const dirs = new Set(paths.map((path6) => getDirs(path6)).reduce((a3, b3) => a3.concat(b3)));
|
|
@@ -28068,10 +28201,10 @@ var UID = Symbol("uid");
|
|
|
28068
28201
|
var GID = Symbol("gid");
|
|
28069
28202
|
var CHECKED_CWD = Symbol("checkedCwd");
|
|
28070
28203
|
var platform8 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
28071
|
-
var
|
|
28204
|
+
var isWindows4 = platform8 === "win32";
|
|
28072
28205
|
var DEFAULT_MAX_DEPTH = 1024;
|
|
28073
28206
|
var unlinkFile = (path7, cb) => {
|
|
28074
|
-
if (!
|
|
28207
|
+
if (!isWindows4) {
|
|
28075
28208
|
return fs9.unlink(path7, cb);
|
|
28076
28209
|
}
|
|
28077
28210
|
const name2 = path7 + ".DELETE." + randomBytes(16).toString("hex");
|
|
@@ -28083,7 +28216,7 @@ var unlinkFile = (path7, cb) => {
|
|
|
28083
28216
|
});
|
|
28084
28217
|
};
|
|
28085
28218
|
var unlinkFileSync = (path7) => {
|
|
28086
|
-
if (!
|
|
28219
|
+
if (!isWindows4) {
|
|
28087
28220
|
return fs9.unlinkSync(path7);
|
|
28088
28221
|
}
|
|
28089
28222
|
const name2 = path7 + ".DELETE." + randomBytes(16).toString("hex");
|
|
@@ -28153,7 +28286,7 @@ class Unpack extends Parser {
|
|
|
28153
28286
|
this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? process.getgid() : undefined;
|
|
28154
28287
|
this.maxDepth = typeof opt.maxDepth === "number" ? opt.maxDepth : DEFAULT_MAX_DEPTH;
|
|
28155
28288
|
this.forceChown = opt.forceChown === true;
|
|
28156
|
-
this.win32 = !!opt.win32 ||
|
|
28289
|
+
this.win32 = !!opt.win32 || isWindows4;
|
|
28157
28290
|
this.newer = !!opt.newer;
|
|
28158
28291
|
this.keep = !!opt.keep;
|
|
28159
28292
|
this.noMtime = !!opt.noMtime;
|
|
@@ -28208,7 +28341,7 @@ class Unpack extends Parser {
|
|
|
28208
28341
|
return false;
|
|
28209
28342
|
}
|
|
28210
28343
|
if (!this.preservePaths) {
|
|
28211
|
-
if (parts.includes("..") ||
|
|
28344
|
+
if (parts.includes("..") || isWindows4 && /^[a-z]:\.\.$/i.test(parts[0] ?? "")) {
|
|
28212
28345
|
this.warn("TAR_ENTRY_ERROR", `path contains '..'`, {
|
|
28213
28346
|
entry,
|
|
28214
28347
|
path: p
|
|
@@ -28422,7 +28555,7 @@ class Unpack extends Parser {
|
|
|
28422
28555
|
entry.resume();
|
|
28423
28556
|
}
|
|
28424
28557
|
[ISREUSABLE](entry, st) {
|
|
28425
|
-
return entry.type === "File" && !this.unlink && st.isFile() && st.nlink <= 1 && !
|
|
28558
|
+
return entry.type === "File" && !this.unlink && st.isFile() && st.nlink <= 1 && !isWindows4;
|
|
28426
28559
|
}
|
|
28427
28560
|
[CHECKFS](entry) {
|
|
28428
28561
|
this[PEND]();
|
|
@@ -29316,23 +29449,22 @@ Solutions:
|
|
|
29316
29449
|
}
|
|
29317
29450
|
}
|
|
29318
29451
|
|
|
29319
|
-
// src/
|
|
29452
|
+
// src/domains/installation/download-extractor.ts
|
|
29320
29453
|
init_logger();
|
|
29321
29454
|
init_output_manager();
|
|
29322
|
-
async function
|
|
29323
|
-
|
|
29324
|
-
|
|
29325
|
-
const downloadInfo = GitHubClient.getDownloadableAsset(ctx.release);
|
|
29455
|
+
async function downloadAndExtract(options) {
|
|
29456
|
+
const { release, kit, exclude } = options;
|
|
29457
|
+
const downloadInfo = GitHubClient.getDownloadableAsset(release);
|
|
29326
29458
|
logger.verbose("Release info", {
|
|
29327
|
-
tag:
|
|
29328
|
-
prerelease:
|
|
29459
|
+
tag: release.tag_name,
|
|
29460
|
+
prerelease: release.prerelease,
|
|
29329
29461
|
downloadType: downloadInfo.type,
|
|
29330
29462
|
assetSize: downloadInfo.size
|
|
29331
29463
|
});
|
|
29332
29464
|
output.section("Downloading");
|
|
29333
29465
|
const downloadManager = new DownloadManager;
|
|
29334
|
-
if (
|
|
29335
|
-
downloadManager.setExcludePatterns(
|
|
29466
|
+
if (exclude && exclude.length > 0) {
|
|
29467
|
+
downloadManager.setExcludePatterns(exclude);
|
|
29336
29468
|
}
|
|
29337
29469
|
const tempDir = await downloadManager.createTempDir();
|
|
29338
29470
|
const { token } = await AuthManager.getToken();
|
|
@@ -29350,8 +29482,8 @@ async function handleDownload(ctx) {
|
|
|
29350
29482
|
logger.warning("Asset download failed, falling back to GitHub tarball...");
|
|
29351
29483
|
const tarballInfo = {
|
|
29352
29484
|
type: "github-tarball",
|
|
29353
|
-
url:
|
|
29354
|
-
name: `${
|
|
29485
|
+
url: release.tarball_url,
|
|
29486
|
+
name: `${kit.repo}-${release.tag_name}.tar.gz`,
|
|
29355
29487
|
size: 0
|
|
29356
29488
|
};
|
|
29357
29489
|
archivePath = await downloadManager.downloadFile({
|
|
@@ -29370,14 +29502,30 @@ async function handleDownload(ctx) {
|
|
|
29370
29502
|
await downloadManager.extractArchive(archivePath, extractDir);
|
|
29371
29503
|
await downloadManager.validateExtraction(extractDir);
|
|
29372
29504
|
return {
|
|
29373
|
-
...ctx,
|
|
29374
29505
|
tempDir,
|
|
29375
29506
|
archivePath,
|
|
29376
29507
|
extractDir
|
|
29377
29508
|
};
|
|
29378
29509
|
}
|
|
29510
|
+
|
|
29511
|
+
// src/commands/init/phases/download-handler.ts
|
|
29512
|
+
async function handleDownload(ctx) {
|
|
29513
|
+
if (ctx.cancelled || !ctx.release || !ctx.kit)
|
|
29514
|
+
return ctx;
|
|
29515
|
+
const result = await downloadAndExtract({
|
|
29516
|
+
release: ctx.release,
|
|
29517
|
+
kit: ctx.kit,
|
|
29518
|
+
exclude: ctx.options.exclude
|
|
29519
|
+
});
|
|
29520
|
+
return {
|
|
29521
|
+
...ctx,
|
|
29522
|
+
tempDir: result.tempDir,
|
|
29523
|
+
archivePath: result.archivePath,
|
|
29524
|
+
extractDir: result.extractDir
|
|
29525
|
+
};
|
|
29526
|
+
}
|
|
29379
29527
|
// src/commands/init/phases/merge-handler.ts
|
|
29380
|
-
import { join as
|
|
29528
|
+
import { join as join43 } from "node:path";
|
|
29381
29529
|
|
|
29382
29530
|
// src/domains/installation/file-merger.ts
|
|
29383
29531
|
init_logger();
|
|
@@ -29561,7 +29709,7 @@ class OwnershipChecker {
|
|
|
29561
29709
|
});
|
|
29562
29710
|
stream.on("error", (err) => {
|
|
29563
29711
|
stream.destroy();
|
|
29564
|
-
reject(new Error(
|
|
29712
|
+
reject(new Error(operationError("Checksum calculation", filePath, err.message)));
|
|
29565
29713
|
});
|
|
29566
29714
|
});
|
|
29567
29715
|
}
|
|
@@ -31383,6 +31531,7 @@ class SettingsMerger {
|
|
|
31383
31531
|
}
|
|
31384
31532
|
|
|
31385
31533
|
// src/domains/installation/merger/settings-processor.ts
|
|
31534
|
+
init_environment();
|
|
31386
31535
|
init_logger();
|
|
31387
31536
|
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
31388
31537
|
|
|
@@ -31398,16 +31547,15 @@ class SettingsProcessor {
|
|
|
31398
31547
|
async processSettingsJson(sourceFile, destFile) {
|
|
31399
31548
|
try {
|
|
31400
31549
|
const sourceContent = await import_fs_extra6.readFile(sourceFile, "utf-8");
|
|
31401
|
-
const isWindows8 = process.platform === "win32";
|
|
31402
31550
|
let transformedSource = sourceContent;
|
|
31403
31551
|
if (this.isGlobal) {
|
|
31404
|
-
const homeVar =
|
|
31552
|
+
const homeVar = isWindows() ? '"%USERPROFILE%"' : '"$HOME"';
|
|
31405
31553
|
transformedSource = this.transformClaudePaths(sourceContent, homeVar);
|
|
31406
31554
|
if (transformedSource !== sourceContent) {
|
|
31407
31555
|
logger.debug(`Transformed .claude/ paths to ${homeVar}/.claude/ in settings.json for global installation`);
|
|
31408
31556
|
}
|
|
31409
31557
|
} else {
|
|
31410
|
-
const projectDirVar =
|
|
31558
|
+
const projectDirVar = isWindows() ? '"%CLAUDE_PROJECT_DIR%"' : '"$CLAUDE_PROJECT_DIR"';
|
|
31411
31559
|
transformedSource = this.transformClaudePaths(sourceContent, projectDirVar);
|
|
31412
31560
|
if (transformedSource !== sourceContent) {
|
|
31413
31561
|
logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
|
|
@@ -31657,7 +31805,7 @@ class FileMerger {
|
|
|
31657
31805
|
|
|
31658
31806
|
// src/domains/migration/legacy-migration.ts
|
|
31659
31807
|
import { readdir as readdir9, stat as stat6 } from "node:fs/promises";
|
|
31660
|
-
import { join as
|
|
31808
|
+
import { join as join38, relative as relative6 } from "node:path";
|
|
31661
31809
|
|
|
31662
31810
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
31663
31811
|
import { join as join34 } from "node:path";
|
|
@@ -31767,6 +31915,43 @@ async function getUninstallManifest(claudeDir, kit) {
|
|
|
31767
31915
|
};
|
|
31768
31916
|
}
|
|
31769
31917
|
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
31918
|
+
import { join as join37 } from "node:path";
|
|
31919
|
+
|
|
31920
|
+
// src/domains/migration/release-manifest.ts
|
|
31921
|
+
init_logger();
|
|
31922
|
+
init_zod();
|
|
31923
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
31924
|
+
import { join as join35 } from "node:path";
|
|
31925
|
+
var ReleaseManifestFileSchema = exports_external.object({
|
|
31926
|
+
path: exports_external.string(),
|
|
31927
|
+
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
31928
|
+
size: exports_external.number()
|
|
31929
|
+
});
|
|
31930
|
+
var ReleaseManifestSchema = exports_external.object({
|
|
31931
|
+
version: exports_external.string(),
|
|
31932
|
+
generatedAt: exports_external.string(),
|
|
31933
|
+
files: exports_external.array(ReleaseManifestFileSchema)
|
|
31934
|
+
});
|
|
31935
|
+
|
|
31936
|
+
class ReleaseManifestLoader {
|
|
31937
|
+
static async load(extractDir) {
|
|
31938
|
+
const manifestPath = join35(extractDir, "release-manifest.json");
|
|
31939
|
+
try {
|
|
31940
|
+
const content = await import_fs_extra9.readFile(manifestPath, "utf-8");
|
|
31941
|
+
const parsed = JSON.parse(content);
|
|
31942
|
+
return ReleaseManifestSchema.parse(parsed);
|
|
31943
|
+
} catch (error) {
|
|
31944
|
+
logger.debug(`Release manifest not found or invalid: ${error}`);
|
|
31945
|
+
return null;
|
|
31946
|
+
}
|
|
31947
|
+
}
|
|
31948
|
+
static findFile(manifest, relativePath) {
|
|
31949
|
+
return manifest.files.find((f3) => f3.path === relativePath);
|
|
31950
|
+
}
|
|
31951
|
+
}
|
|
31952
|
+
|
|
31953
|
+
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
31954
|
+
init_environment();
|
|
31770
31955
|
init_logger();
|
|
31771
31956
|
|
|
31772
31957
|
// node_modules/yocto-queue/index.js
|
|
@@ -31909,111 +32094,31 @@ function validateConcurrency(concurrency) {
|
|
|
31909
32094
|
}
|
|
31910
32095
|
}
|
|
31911
32096
|
|
|
31912
|
-
// src/services/file-operations/manifest/manifest-
|
|
31913
|
-
|
|
31914
|
-
|
|
31915
|
-
|
|
31916
|
-
|
|
31917
|
-
|
|
31918
|
-
|
|
31919
|
-
|
|
31920
|
-
|
|
31921
|
-
|
|
31922
|
-
|
|
31923
|
-
|
|
31924
|
-
|
|
31925
|
-
|
|
31926
|
-
|
|
31927
|
-
const normalized = relativePath.replace(/\\/g, "/");
|
|
31928
|
-
this.userConfigFiles.add(normalized);
|
|
31929
|
-
}
|
|
31930
|
-
getInstalledFiles() {
|
|
31931
|
-
return Array.from(this.installedFiles).sort();
|
|
31932
|
-
}
|
|
31933
|
-
getUserConfigFiles() {
|
|
31934
|
-
return Array.from(this.userConfigFiles).sort();
|
|
31935
|
-
}
|
|
31936
|
-
async addTrackedFile(filePath, relativePath, ownership, installedVersion) {
|
|
31937
|
-
const checksum = await OwnershipChecker.calculateChecksum(filePath);
|
|
31938
|
-
const normalized = relativePath.replace(/\\/g, "/");
|
|
31939
|
-
this.trackedFiles.set(normalized, {
|
|
31940
|
-
path: normalized,
|
|
31941
|
-
checksum,
|
|
31942
|
-
ownership,
|
|
31943
|
-
installedVersion
|
|
32097
|
+
// src/services/file-operations/manifest/manifest-updater.ts
|
|
32098
|
+
import { join as join36 } from "node:path";
|
|
32099
|
+
init_logger();
|
|
32100
|
+
init_types2();
|
|
32101
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
32102
|
+
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
32103
|
+
async function writeManifest(claudeDir, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
|
|
32104
|
+
const metadataPath = join36(claudeDir, "metadata.json");
|
|
32105
|
+
const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
|
|
32106
|
+
await import_fs_extra10.ensureFile(metadataPath);
|
|
32107
|
+
let release = null;
|
|
32108
|
+
try {
|
|
32109
|
+
release = await import_proper_lockfile.lock(metadataPath, {
|
|
32110
|
+
retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
|
|
32111
|
+
stale: 60000
|
|
31944
32112
|
});
|
|
31945
|
-
|
|
31946
|
-
|
|
31947
|
-
|
|
31948
|
-
|
|
31949
|
-
|
|
31950
|
-
|
|
31951
|
-
|
|
32113
|
+
logger.debug(`Acquired lock on ${metadataPath}`);
|
|
32114
|
+
const migrationResult = await migrateToMultiKit(claudeDir);
|
|
32115
|
+
if (!migrationResult.success) {
|
|
32116
|
+
logger.warning(`Metadata migration warning: ${migrationResult.error}`);
|
|
32117
|
+
}
|
|
32118
|
+
let existingMetadata = { kits: {} };
|
|
32119
|
+
if (await import_fs_extra10.pathExists(metadataPath)) {
|
|
31952
32120
|
try {
|
|
31953
|
-
const
|
|
31954
|
-
const normalized = file.relativePath.replace(/\\/g, "/");
|
|
31955
|
-
this.trackedFiles.set(normalized, {
|
|
31956
|
-
path: normalized,
|
|
31957
|
-
checksum,
|
|
31958
|
-
ownership: file.ownership,
|
|
31959
|
-
installedVersion: file.installedVersion
|
|
31960
|
-
});
|
|
31961
|
-
this.installedFiles.add(normalized);
|
|
31962
|
-
return true;
|
|
31963
|
-
} catch (error) {
|
|
31964
|
-
logger.debug(`Failed to track file ${file.relativePath}: ${error}`);
|
|
31965
|
-
return false;
|
|
31966
|
-
}
|
|
31967
|
-
}));
|
|
31968
|
-
const progressInterval = Math.max(1, Math.floor(total / 20));
|
|
31969
|
-
let reportedProgress = 0;
|
|
31970
|
-
const results = await Promise.all(tasks.map(async (task, index) => {
|
|
31971
|
-
const result = await task;
|
|
31972
|
-
const completed = index + 1;
|
|
31973
|
-
if (completed % progressInterval === 0 || completed === total) {
|
|
31974
|
-
if (completed > reportedProgress) {
|
|
31975
|
-
reportedProgress = completed;
|
|
31976
|
-
onProgress?.(completed, total);
|
|
31977
|
-
}
|
|
31978
|
-
}
|
|
31979
|
-
return result;
|
|
31980
|
-
}));
|
|
31981
|
-
const success = results.filter(Boolean).length;
|
|
31982
|
-
const failed = total - success;
|
|
31983
|
-
if (failed > 0) {
|
|
31984
|
-
logger.warning(`Failed to track ${failed} of ${total} files (check debug logs for details)`);
|
|
31985
|
-
}
|
|
31986
|
-
return { success, failed, total };
|
|
31987
|
-
}
|
|
31988
|
-
getTrackedFiles() {
|
|
31989
|
-
return Array.from(this.trackedFiles.values()).sort((a3, b3) => a3.path.localeCompare(b3.path));
|
|
31990
|
-
}
|
|
31991
|
-
}
|
|
31992
|
-
// src/services/file-operations/manifest/manifest-updater.ts
|
|
31993
|
-
import { join as join35 } from "node:path";
|
|
31994
|
-
init_logger();
|
|
31995
|
-
init_types2();
|
|
31996
|
-
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
31997
|
-
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
31998
|
-
async function writeManifest(claudeDir, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
|
|
31999
|
-
const metadataPath = join35(claudeDir, "metadata.json");
|
|
32000
|
-
const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
|
|
32001
|
-
await import_fs_extra9.ensureFile(metadataPath);
|
|
32002
|
-
let release = null;
|
|
32003
|
-
try {
|
|
32004
|
-
release = await import_proper_lockfile.lock(metadataPath, {
|
|
32005
|
-
retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
|
|
32006
|
-
stale: 60000
|
|
32007
|
-
});
|
|
32008
|
-
logger.debug(`Acquired lock on ${metadataPath}`);
|
|
32009
|
-
const migrationResult = await migrateToMultiKit(claudeDir);
|
|
32010
|
-
if (!migrationResult.success) {
|
|
32011
|
-
logger.warning(`Metadata migration warning: ${migrationResult.error}`);
|
|
32012
|
-
}
|
|
32013
|
-
let existingMetadata = { kits: {} };
|
|
32014
|
-
if (await import_fs_extra9.pathExists(metadataPath)) {
|
|
32015
|
-
try {
|
|
32016
|
-
const content = await import_fs_extra9.readFile(metadataPath, "utf-8");
|
|
32121
|
+
const content = await import_fs_extra10.readFile(metadataPath, "utf-8");
|
|
32017
32122
|
const parsed = JSON.parse(content);
|
|
32018
32123
|
if (parsed && typeof parsed === "object" && Object.keys(parsed).length > 0) {
|
|
32019
32124
|
existingMetadata = parsed;
|
|
@@ -32040,7 +32145,7 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
32040
32145
|
userConfigFiles: [...USER_CONFIG_PATTERNS, ...userConfigFiles]
|
|
32041
32146
|
};
|
|
32042
32147
|
const validated = MetadataSchema.parse(metadata);
|
|
32043
|
-
await
|
|
32148
|
+
await import_fs_extra10.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
32044
32149
|
logger.debug(`Wrote manifest for kit "${kit}" with ${trackedFiles.length} tracked files`);
|
|
32045
32150
|
} finally {
|
|
32046
32151
|
if (release) {
|
|
@@ -32050,8 +32155,8 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
32050
32155
|
}
|
|
32051
32156
|
}
|
|
32052
32157
|
async function removeKitFromManifest(claudeDir, kit) {
|
|
32053
|
-
const metadataPath =
|
|
32054
|
-
if (!await
|
|
32158
|
+
const metadataPath = join36(claudeDir, "metadata.json");
|
|
32159
|
+
if (!await import_fs_extra10.pathExists(metadataPath))
|
|
32055
32160
|
return false;
|
|
32056
32161
|
let release = null;
|
|
32057
32162
|
try {
|
|
@@ -32072,7 +32177,7 @@ async function removeKitFromManifest(claudeDir, kit) {
|
|
|
32072
32177
|
...metadata,
|
|
32073
32178
|
kits: remainingKits
|
|
32074
32179
|
};
|
|
32075
|
-
await
|
|
32180
|
+
await import_fs_extra10.writeFile(metadataPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
32076
32181
|
logger.debug(`Removed kit "${kit}" from metadata, ${Object.keys(remainingKits).length} kit(s) remaining`);
|
|
32077
32182
|
return true;
|
|
32078
32183
|
} finally {
|
|
@@ -32082,6 +32187,126 @@ async function removeKitFromManifest(claudeDir, kit) {
|
|
|
32082
32187
|
}
|
|
32083
32188
|
}
|
|
32084
32189
|
}
|
|
32190
|
+
|
|
32191
|
+
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
32192
|
+
class ManifestTracker {
|
|
32193
|
+
installedFiles = new Set;
|
|
32194
|
+
userConfigFiles = new Set;
|
|
32195
|
+
trackedFiles = new Map;
|
|
32196
|
+
addInstalledFile(relativePath) {
|
|
32197
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
32198
|
+
this.installedFiles.add(normalized);
|
|
32199
|
+
}
|
|
32200
|
+
addInstalledFiles(relativePaths) {
|
|
32201
|
+
for (const path9 of relativePaths) {
|
|
32202
|
+
this.addInstalledFile(path9);
|
|
32203
|
+
}
|
|
32204
|
+
}
|
|
32205
|
+
addUserConfigFile(relativePath) {
|
|
32206
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
32207
|
+
this.userConfigFiles.add(normalized);
|
|
32208
|
+
}
|
|
32209
|
+
getInstalledFiles() {
|
|
32210
|
+
return Array.from(this.installedFiles).sort();
|
|
32211
|
+
}
|
|
32212
|
+
getUserConfigFiles() {
|
|
32213
|
+
return Array.from(this.userConfigFiles).sort();
|
|
32214
|
+
}
|
|
32215
|
+
async addTrackedFile(filePath, relativePath, ownership, installedVersion) {
|
|
32216
|
+
const checksum = await OwnershipChecker.calculateChecksum(filePath);
|
|
32217
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
32218
|
+
this.trackedFiles.set(normalized, {
|
|
32219
|
+
path: normalized,
|
|
32220
|
+
checksum,
|
|
32221
|
+
ownership,
|
|
32222
|
+
installedVersion
|
|
32223
|
+
});
|
|
32224
|
+
this.installedFiles.add(normalized);
|
|
32225
|
+
}
|
|
32226
|
+
async addTrackedFilesBatch(files, options = {}) {
|
|
32227
|
+
const { concurrency = 20, onProgress } = options;
|
|
32228
|
+
const limit = pLimit(concurrency);
|
|
32229
|
+
const total = files.length;
|
|
32230
|
+
const tasks = files.map((file) => limit(async () => {
|
|
32231
|
+
try {
|
|
32232
|
+
const checksum = await OwnershipChecker.calculateChecksum(file.filePath);
|
|
32233
|
+
const normalized = file.relativePath.replace(/\\/g, "/");
|
|
32234
|
+
this.trackedFiles.set(normalized, {
|
|
32235
|
+
path: normalized,
|
|
32236
|
+
checksum,
|
|
32237
|
+
ownership: file.ownership,
|
|
32238
|
+
installedVersion: file.installedVersion
|
|
32239
|
+
});
|
|
32240
|
+
this.installedFiles.add(normalized);
|
|
32241
|
+
return true;
|
|
32242
|
+
} catch (error) {
|
|
32243
|
+
logger.debug(`Failed to track file ${file.relativePath}: ${error}`);
|
|
32244
|
+
return false;
|
|
32245
|
+
}
|
|
32246
|
+
}));
|
|
32247
|
+
const progressInterval = Math.max(1, Math.floor(total / 20));
|
|
32248
|
+
let reportedProgress = 0;
|
|
32249
|
+
const results = await Promise.all(tasks.map(async (task, index) => {
|
|
32250
|
+
const result = await task;
|
|
32251
|
+
const completed = index + 1;
|
|
32252
|
+
if (completed % progressInterval === 0 || completed === total) {
|
|
32253
|
+
if (completed > reportedProgress) {
|
|
32254
|
+
reportedProgress = completed;
|
|
32255
|
+
onProgress?.(completed, total);
|
|
32256
|
+
}
|
|
32257
|
+
}
|
|
32258
|
+
return result;
|
|
32259
|
+
}));
|
|
32260
|
+
const success = results.filter(Boolean).length;
|
|
32261
|
+
const failed = total - success;
|
|
32262
|
+
if (failed > 0) {
|
|
32263
|
+
logger.warning(`Failed to track ${failed} of ${total} files (check debug logs for details)`);
|
|
32264
|
+
}
|
|
32265
|
+
return { success, failed, total };
|
|
32266
|
+
}
|
|
32267
|
+
getTrackedFiles() {
|
|
32268
|
+
return Array.from(this.trackedFiles.values()).sort((a3, b3) => a3.path.localeCompare(b3.path));
|
|
32269
|
+
}
|
|
32270
|
+
}
|
|
32271
|
+
function buildFileTrackingList(options) {
|
|
32272
|
+
const {
|
|
32273
|
+
installedFiles,
|
|
32274
|
+
claudeDir,
|
|
32275
|
+
releaseManifest,
|
|
32276
|
+
installedVersion,
|
|
32277
|
+
isGlobal = false
|
|
32278
|
+
} = options;
|
|
32279
|
+
const filesToTrack = [];
|
|
32280
|
+
for (const installedPath of installedFiles) {
|
|
32281
|
+
if (!isGlobal && !installedPath.startsWith(".claude/"))
|
|
32282
|
+
continue;
|
|
32283
|
+
const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
32284
|
+
const filePath = join37(claudeDir, relativePath);
|
|
32285
|
+
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
32286
|
+
const ownership = manifestEntry ? "ck" : "user";
|
|
32287
|
+
filesToTrack.push({
|
|
32288
|
+
filePath,
|
|
32289
|
+
relativePath,
|
|
32290
|
+
ownership,
|
|
32291
|
+
installedVersion
|
|
32292
|
+
});
|
|
32293
|
+
}
|
|
32294
|
+
return filesToTrack;
|
|
32295
|
+
}
|
|
32296
|
+
async function trackFilesWithProgress(filesToTrack, manifestOptions) {
|
|
32297
|
+
const tracker = new ManifestTracker;
|
|
32298
|
+
const trackingSpinner = createSpinner(`Tracking ${filesToTrack.length} installed files...`);
|
|
32299
|
+
trackingSpinner.start();
|
|
32300
|
+
const trackResult = await tracker.addTrackedFilesBatch(filesToTrack, {
|
|
32301
|
+
concurrency: getOptimalConcurrency(),
|
|
32302
|
+
onProgress: (processed, total) => {
|
|
32303
|
+
trackingSpinner.text = `Tracking files... (${processed}/${total})`;
|
|
32304
|
+
}
|
|
32305
|
+
});
|
|
32306
|
+
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
32307
|
+
await writeManifest(manifestOptions.claudeDir, manifestOptions.kitName, manifestOptions.releaseTag, manifestOptions.mode, manifestOptions.kitType, tracker.getTrackedFiles(), tracker.getUserConfigFiles());
|
|
32308
|
+
return trackResult;
|
|
32309
|
+
}
|
|
32085
32310
|
// src/services/file-operations/manifest-writer.ts
|
|
32086
32311
|
class ManifestWriter {
|
|
32087
32312
|
tracker = new ManifestTracker;
|
|
@@ -32129,41 +32354,6 @@ class ManifestWriter {
|
|
|
32129
32354
|
// src/domains/migration/legacy-migration.ts
|
|
32130
32355
|
init_logger();
|
|
32131
32356
|
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
32132
|
-
|
|
32133
|
-
// src/domains/migration/release-manifest.ts
|
|
32134
|
-
init_logger();
|
|
32135
|
-
init_zod();
|
|
32136
|
-
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
32137
|
-
import { join as join36 } from "node:path";
|
|
32138
|
-
var ReleaseManifestFileSchema = exports_external.object({
|
|
32139
|
-
path: exports_external.string(),
|
|
32140
|
-
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
32141
|
-
size: exports_external.number()
|
|
32142
|
-
});
|
|
32143
|
-
var ReleaseManifestSchema = exports_external.object({
|
|
32144
|
-
version: exports_external.string(),
|
|
32145
|
-
generatedAt: exports_external.string(),
|
|
32146
|
-
files: exports_external.array(ReleaseManifestFileSchema)
|
|
32147
|
-
});
|
|
32148
|
-
|
|
32149
|
-
class ReleaseManifestLoader {
|
|
32150
|
-
static async load(extractDir) {
|
|
32151
|
-
const manifestPath = join36(extractDir, "release-manifest.json");
|
|
32152
|
-
try {
|
|
32153
|
-
const content = await import_fs_extra10.readFile(manifestPath, "utf-8");
|
|
32154
|
-
const parsed = JSON.parse(content);
|
|
32155
|
-
return ReleaseManifestSchema.parse(parsed);
|
|
32156
|
-
} catch (error) {
|
|
32157
|
-
logger.debug(`Release manifest not found or invalid: ${error}`);
|
|
32158
|
-
return null;
|
|
32159
|
-
}
|
|
32160
|
-
}
|
|
32161
|
-
static findFile(manifest, relativePath) {
|
|
32162
|
-
return manifest.files.find((f3) => f3.path === relativePath);
|
|
32163
|
-
}
|
|
32164
|
-
}
|
|
32165
|
-
|
|
32166
|
-
// src/domains/migration/legacy-migration.ts
|
|
32167
32357
|
class LegacyMigration {
|
|
32168
32358
|
static async detectLegacy(claudeDir) {
|
|
32169
32359
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
@@ -32194,7 +32384,7 @@ class LegacyMigration {
|
|
|
32194
32384
|
for (const entry of entries) {
|
|
32195
32385
|
if (entry === "metadata.json")
|
|
32196
32386
|
continue;
|
|
32197
|
-
const fullPath =
|
|
32387
|
+
const fullPath = join38(dir, entry);
|
|
32198
32388
|
let stats;
|
|
32199
32389
|
try {
|
|
32200
32390
|
stats = await stat6(fullPath);
|
|
@@ -32296,7 +32486,7 @@ User-created files (sample):`);
|
|
|
32296
32486
|
];
|
|
32297
32487
|
if (filesToChecksum.length > 0) {
|
|
32298
32488
|
const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
|
|
32299
|
-
const fullPath =
|
|
32489
|
+
const fullPath = join38(claudeDir, relativePath);
|
|
32300
32490
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
32301
32491
|
return { relativePath, checksum, ownership };
|
|
32302
32492
|
}));
|
|
@@ -32317,7 +32507,7 @@ User-created files (sample):`);
|
|
|
32317
32507
|
installedAt: new Date().toISOString(),
|
|
32318
32508
|
files: trackedFiles
|
|
32319
32509
|
};
|
|
32320
|
-
const metadataPath =
|
|
32510
|
+
const metadataPath = join38(claudeDir, "metadata.json");
|
|
32321
32511
|
await import_fs_extra11.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
32322
32512
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
32323
32513
|
return true;
|
|
@@ -32325,8 +32515,8 @@ User-created files (sample):`);
|
|
|
32325
32515
|
}
|
|
32326
32516
|
|
|
32327
32517
|
// src/services/file-operations/file-scanner.ts
|
|
32518
|
+
import { join as join39, relative as relative7, resolve as resolve6 } from "node:path";
|
|
32328
32519
|
init_logger();
|
|
32329
|
-
import { join as join38, relative as relative7, resolve as resolve6 } from "node:path";
|
|
32330
32520
|
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
32331
32521
|
|
|
32332
32522
|
class FileScanner2 {
|
|
@@ -32343,7 +32533,7 @@ class FileScanner2 {
|
|
|
32343
32533
|
logger.debug(`Skipping directory: ${entry}`);
|
|
32344
32534
|
continue;
|
|
32345
32535
|
}
|
|
32346
|
-
const fullPath =
|
|
32536
|
+
const fullPath = join39(dirPath, entry);
|
|
32347
32537
|
if (!FileScanner2.isSafePath(basePath, fullPath)) {
|
|
32348
32538
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
32349
32539
|
continue;
|
|
@@ -32371,15 +32561,15 @@ class FileScanner2 {
|
|
|
32371
32561
|
}
|
|
32372
32562
|
}
|
|
32373
32563
|
} catch (error) {
|
|
32374
|
-
const errorMessage = error instanceof Error ?
|
|
32564
|
+
const errorMessage = error instanceof Error ? operationError("Directory scan", dirPath, error.message) : operationError("Directory scan", dirPath, "unknown error");
|
|
32375
32565
|
logger.error(errorMessage);
|
|
32376
32566
|
throw error;
|
|
32377
32567
|
}
|
|
32378
32568
|
return files;
|
|
32379
32569
|
}
|
|
32380
32570
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
32381
|
-
const destSubDir =
|
|
32382
|
-
const sourceSubDir =
|
|
32571
|
+
const destSubDir = join39(destDir, subPath);
|
|
32572
|
+
const sourceSubDir = join39(sourceDir, subPath);
|
|
32383
32573
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
32384
32574
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
32385
32575
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -32420,7 +32610,7 @@ class FileScanner2 {
|
|
|
32420
32610
|
init_logger();
|
|
32421
32611
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
32422
32612
|
import { lstat as lstat3, mkdir as mkdir13, readdir as readdir11, stat as stat7 } from "node:fs/promises";
|
|
32423
|
-
import { join as
|
|
32613
|
+
import { join as join40 } from "node:path";
|
|
32424
32614
|
|
|
32425
32615
|
// src/services/transformers/commands-prefix/prefix-utils.ts
|
|
32426
32616
|
init_logger();
|
|
@@ -32465,14 +32655,14 @@ function shouldApplyPrefix(options) {
|
|
|
32465
32655
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
32466
32656
|
async function applyPrefix(extractDir) {
|
|
32467
32657
|
validatePath(extractDir, "extractDir");
|
|
32468
|
-
const commandsDir =
|
|
32658
|
+
const commandsDir = join40(extractDir, ".claude", "commands");
|
|
32469
32659
|
if (!await import_fs_extra13.pathExists(commandsDir)) {
|
|
32470
32660
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
32471
32661
|
return;
|
|
32472
32662
|
}
|
|
32473
32663
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
32474
|
-
const backupDir =
|
|
32475
|
-
const tempDir =
|
|
32664
|
+
const backupDir = join40(extractDir, ".commands-backup");
|
|
32665
|
+
const tempDir = join40(extractDir, ".commands-prefix-temp");
|
|
32476
32666
|
try {
|
|
32477
32667
|
const entries = await readdir11(commandsDir);
|
|
32478
32668
|
if (entries.length === 0) {
|
|
@@ -32480,7 +32670,7 @@ async function applyPrefix(extractDir) {
|
|
|
32480
32670
|
return;
|
|
32481
32671
|
}
|
|
32482
32672
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
32483
|
-
const ckDir2 =
|
|
32673
|
+
const ckDir2 = join40(commandsDir, "ck");
|
|
32484
32674
|
const ckStat = await stat7(ckDir2);
|
|
32485
32675
|
if (ckStat.isDirectory()) {
|
|
32486
32676
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -32490,17 +32680,17 @@ async function applyPrefix(extractDir) {
|
|
|
32490
32680
|
await import_fs_extra13.copy(commandsDir, backupDir);
|
|
32491
32681
|
logger.verbose("Created backup of commands directory");
|
|
32492
32682
|
await mkdir13(tempDir, { recursive: true });
|
|
32493
|
-
const ckDir =
|
|
32683
|
+
const ckDir = join40(tempDir, "ck");
|
|
32494
32684
|
await mkdir13(ckDir, { recursive: true });
|
|
32495
32685
|
let processedCount = 0;
|
|
32496
32686
|
for (const entry of entries) {
|
|
32497
|
-
const sourcePath =
|
|
32687
|
+
const sourcePath = join40(commandsDir, entry);
|
|
32498
32688
|
const stats = await lstat3(sourcePath);
|
|
32499
32689
|
if (stats.isSymbolicLink()) {
|
|
32500
32690
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
32501
32691
|
continue;
|
|
32502
32692
|
}
|
|
32503
|
-
const destPath =
|
|
32693
|
+
const destPath = join40(ckDir, entry);
|
|
32504
32694
|
await import_fs_extra13.copy(sourcePath, destPath, {
|
|
32505
32695
|
overwrite: false,
|
|
32506
32696
|
errorOnExist: true
|
|
@@ -32545,20 +32735,20 @@ async function applyPrefix(extractDir) {
|
|
|
32545
32735
|
|
|
32546
32736
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
32547
32737
|
import { lstat as lstat5, readdir as readdir13 } from "node:fs/promises";
|
|
32548
|
-
import { join as
|
|
32738
|
+
import { join as join42 } from "node:path";
|
|
32549
32739
|
init_logger();
|
|
32550
32740
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
32551
32741
|
|
|
32552
32742
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
32553
32743
|
import { lstat as lstat4, readdir as readdir12 } from "node:fs/promises";
|
|
32554
|
-
import { join as
|
|
32744
|
+
import { join as join41 } from "node:path";
|
|
32555
32745
|
init_logger();
|
|
32556
32746
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
32557
32747
|
async function scanDirectoryFiles(dir) {
|
|
32558
32748
|
const files = [];
|
|
32559
32749
|
const entries = await readdir12(dir);
|
|
32560
32750
|
for (const entry of entries) {
|
|
32561
|
-
const fullPath =
|
|
32751
|
+
const fullPath = join41(dir, entry);
|
|
32562
32752
|
const stats = await lstat4(fullPath);
|
|
32563
32753
|
if (stats.isSymbolicLink()) {
|
|
32564
32754
|
continue;
|
|
@@ -32666,8 +32856,8 @@ function logCleanupSummary(deletedCount, preservedCount, dryRun, results) {
|
|
|
32666
32856
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
32667
32857
|
const { dryRun = false } = options;
|
|
32668
32858
|
validatePath(targetDir, "targetDir");
|
|
32669
|
-
const claudeDir = isGlobal ? targetDir :
|
|
32670
|
-
const commandsDir =
|
|
32859
|
+
const claudeDir = isGlobal ? targetDir : join42(targetDir, ".claude");
|
|
32860
|
+
const commandsDir = join42(claudeDir, "commands");
|
|
32671
32861
|
const accumulator = {
|
|
32672
32862
|
results: [],
|
|
32673
32863
|
deletedCount: 0,
|
|
@@ -32701,7 +32891,7 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
32701
32891
|
return result;
|
|
32702
32892
|
}
|
|
32703
32893
|
for (const entry of entries) {
|
|
32704
|
-
const entryPath =
|
|
32894
|
+
const entryPath = join42(commandsDir, entry);
|
|
32705
32895
|
const stats = await lstat5(entryPath);
|
|
32706
32896
|
if (stats.isSymbolicLink()) {
|
|
32707
32897
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -32743,7 +32933,6 @@ class CommandsPrefix {
|
|
|
32743
32933
|
}
|
|
32744
32934
|
|
|
32745
32935
|
// src/commands/init/phases/merge-handler.ts
|
|
32746
|
-
init_environment();
|
|
32747
32936
|
init_logger();
|
|
32748
32937
|
init_output_manager();
|
|
32749
32938
|
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
@@ -32754,7 +32943,7 @@ async function handleMerge(ctx) {
|
|
|
32754
32943
|
let customClaudeFiles = [];
|
|
32755
32944
|
if (!ctx.options.fresh) {
|
|
32756
32945
|
logger.info("Scanning for custom .claude files...");
|
|
32757
|
-
const scanSourceDir = ctx.options.global ?
|
|
32946
|
+
const scanSourceDir = ctx.options.global ? join43(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
32758
32947
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
32759
32948
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
32760
32949
|
} else {
|
|
@@ -32813,35 +33002,23 @@ async function handleMerge(ctx) {
|
|
|
32813
33002
|
return { ...ctx, cancelled: true };
|
|
32814
33003
|
}
|
|
32815
33004
|
}
|
|
32816
|
-
const sourceDir = ctx.options.global ?
|
|
33005
|
+
const sourceDir = ctx.options.global ? join43(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
32817
33006
|
await merger.merge(sourceDir, ctx.resolvedDir, false);
|
|
32818
|
-
const manifestWriter = new ManifestWriter;
|
|
32819
33007
|
const installedFiles = merger.getAllInstalledFiles();
|
|
32820
|
-
const filesToTrack =
|
|
32821
|
-
|
|
32822
|
-
|
|
32823
|
-
|
|
32824
|
-
|
|
32825
|
-
|
|
32826
|
-
|
|
32827
|
-
|
|
32828
|
-
|
|
32829
|
-
|
|
32830
|
-
|
|
32831
|
-
|
|
32832
|
-
|
|
32833
|
-
});
|
|
32834
|
-
}
|
|
32835
|
-
const trackingSpinner = createSpinner(`Tracking ${filesToTrack.length} installed files...`);
|
|
32836
|
-
trackingSpinner.start();
|
|
32837
|
-
const trackResult = await manifestWriter.addTrackedFilesBatch(filesToTrack, {
|
|
32838
|
-
concurrency: getOptimalConcurrency(),
|
|
32839
|
-
onProgress: (processed, total) => {
|
|
32840
|
-
trackingSpinner.text = `Tracking files... (${processed}/${total})`;
|
|
32841
|
-
}
|
|
33008
|
+
const filesToTrack = buildFileTrackingList({
|
|
33009
|
+
installedFiles,
|
|
33010
|
+
claudeDir: ctx.claudeDir,
|
|
33011
|
+
releaseManifest,
|
|
33012
|
+
installedVersion: ctx.release.tag_name,
|
|
33013
|
+
isGlobal: ctx.options.global
|
|
33014
|
+
});
|
|
33015
|
+
await trackFilesWithProgress(filesToTrack, {
|
|
33016
|
+
claudeDir: ctx.claudeDir,
|
|
33017
|
+
kitName: ctx.kit.name,
|
|
33018
|
+
releaseTag: ctx.release.tag_name,
|
|
33019
|
+
mode: ctx.options.global ? "global" : "local",
|
|
33020
|
+
kitType: ctx.kitType
|
|
32842
33021
|
});
|
|
32843
|
-
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
32844
|
-
await manifestWriter.writeManifest(ctx.claudeDir, ctx.kit.name, ctx.release.tag_name, ctx.options.global ? "global" : "local", ctx.kitType);
|
|
32845
33022
|
return {
|
|
32846
33023
|
...ctx,
|
|
32847
33024
|
customClaudeFiles,
|
|
@@ -32849,7 +33026,7 @@ async function handleMerge(ctx) {
|
|
|
32849
33026
|
};
|
|
32850
33027
|
}
|
|
32851
33028
|
// src/commands/init/phases/migration-handler.ts
|
|
32852
|
-
import { join as
|
|
33029
|
+
import { join as join51 } from "node:path";
|
|
32853
33030
|
|
|
32854
33031
|
// src/domains/skills/skills-detector.ts
|
|
32855
33032
|
init_logger();
|
|
@@ -32864,7 +33041,7 @@ init_types2();
|
|
|
32864
33041
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
32865
33042
|
import { createHash as createHash2 } from "node:crypto";
|
|
32866
33043
|
import { readFile as readFile14, readdir as readdir14, writeFile as writeFile12 } from "node:fs/promises";
|
|
32867
|
-
import { join as
|
|
33044
|
+
import { join as join44, relative as relative8 } from "node:path";
|
|
32868
33045
|
|
|
32869
33046
|
class SkillsManifestManager {
|
|
32870
33047
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
@@ -32886,12 +33063,12 @@ class SkillsManifestManager {
|
|
|
32886
33063
|
return manifest;
|
|
32887
33064
|
}
|
|
32888
33065
|
static async writeManifest(skillsDir, manifest) {
|
|
32889
|
-
const manifestPath =
|
|
33066
|
+
const manifestPath = join44(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
32890
33067
|
await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
32891
33068
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
32892
33069
|
}
|
|
32893
33070
|
static async readManifest(skillsDir) {
|
|
32894
|
-
const manifestPath =
|
|
33071
|
+
const manifestPath = join44(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
32895
33072
|
if (!await import_fs_extra17.pathExists(manifestPath)) {
|
|
32896
33073
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
32897
33074
|
return null;
|
|
@@ -32914,7 +33091,7 @@ class SkillsManifestManager {
|
|
|
32914
33091
|
return "flat";
|
|
32915
33092
|
}
|
|
32916
33093
|
for (const dir of dirs.slice(0, 3)) {
|
|
32917
|
-
const dirPath =
|
|
33094
|
+
const dirPath = join44(skillsDir, dir.name);
|
|
32918
33095
|
const subEntries = await readdir14(dirPath, { withFileTypes: true });
|
|
32919
33096
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
32920
33097
|
if (hasSubdirs) {
|
|
@@ -32933,7 +33110,7 @@ class SkillsManifestManager {
|
|
|
32933
33110
|
const entries = await readdir14(skillsDir, { withFileTypes: true });
|
|
32934
33111
|
for (const entry of entries) {
|
|
32935
33112
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
32936
|
-
const skillPath =
|
|
33113
|
+
const skillPath = join44(skillsDir, entry.name);
|
|
32937
33114
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
32938
33115
|
skills.push({
|
|
32939
33116
|
name: entry.name,
|
|
@@ -32945,11 +33122,11 @@ class SkillsManifestManager {
|
|
|
32945
33122
|
const categories = await readdir14(skillsDir, { withFileTypes: true });
|
|
32946
33123
|
for (const category of categories) {
|
|
32947
33124
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
32948
|
-
const categoryPath =
|
|
33125
|
+
const categoryPath = join44(skillsDir, category.name);
|
|
32949
33126
|
const skillEntries = await readdir14(categoryPath, { withFileTypes: true });
|
|
32950
33127
|
for (const skillEntry of skillEntries) {
|
|
32951
33128
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
32952
|
-
const skillPath =
|
|
33129
|
+
const skillPath = join44(categoryPath, skillEntry.name);
|
|
32953
33130
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
32954
33131
|
skills.push({
|
|
32955
33132
|
name: skillEntry.name,
|
|
@@ -32979,7 +33156,7 @@ class SkillsManifestManager {
|
|
|
32979
33156
|
const files = [];
|
|
32980
33157
|
const entries = await readdir14(dirPath, { withFileTypes: true });
|
|
32981
33158
|
for (const entry of entries) {
|
|
32982
|
-
const fullPath =
|
|
33159
|
+
const fullPath = join44(dirPath, entry.name);
|
|
32983
33160
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
32984
33161
|
continue;
|
|
32985
33162
|
}
|
|
@@ -33101,7 +33278,7 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
33101
33278
|
// src/domains/skills/detection/script-detector.ts
|
|
33102
33279
|
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
33103
33280
|
import { readdir as readdir15 } from "node:fs/promises";
|
|
33104
|
-
import { join as
|
|
33281
|
+
import { join as join45 } from "node:path";
|
|
33105
33282
|
async function scanDirectory(skillsDir) {
|
|
33106
33283
|
if (!await import_fs_extra18.pathExists(skillsDir)) {
|
|
33107
33284
|
return ["flat", []];
|
|
@@ -33114,12 +33291,12 @@ async function scanDirectory(skillsDir) {
|
|
|
33114
33291
|
let totalSkillLikeCount = 0;
|
|
33115
33292
|
const allSkills = [];
|
|
33116
33293
|
for (const dir of dirs) {
|
|
33117
|
-
const dirPath =
|
|
33294
|
+
const dirPath = join45(skillsDir, dir.name);
|
|
33118
33295
|
const subEntries = await readdir15(dirPath, { withFileTypes: true });
|
|
33119
33296
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
33120
33297
|
if (subdirs.length > 0) {
|
|
33121
33298
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
33122
|
-
const subdirPath =
|
|
33299
|
+
const subdirPath = join45(dirPath, subdir.name);
|
|
33123
33300
|
const subdirFiles = await readdir15(subdirPath, { withFileTypes: true });
|
|
33124
33301
|
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"));
|
|
33125
33302
|
if (hasSkillMarker) {
|
|
@@ -33276,19 +33453,25 @@ class SkillsMigrationDetector {
|
|
|
33276
33453
|
// src/domains/skills/skills-migrator.ts
|
|
33277
33454
|
init_logger();
|
|
33278
33455
|
init_types2();
|
|
33279
|
-
import { join as
|
|
33456
|
+
import { join as join50 } from "node:path";
|
|
33280
33457
|
|
|
33281
33458
|
// src/domains/skills/migrator/migration-executor.ts
|
|
33282
33459
|
init_logger();
|
|
33283
33460
|
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
33284
33461
|
import { copyFile as copyFile4, mkdir as mkdir14, readdir as readdir16, rm as rm3 } from "node:fs/promises";
|
|
33285
|
-
import { join as
|
|
33462
|
+
import { join as join46 } from "node:path";
|
|
33286
33463
|
|
|
33287
33464
|
// src/domains/skills/skills-migration-prompts.ts
|
|
33465
|
+
init_environment();
|
|
33466
|
+
init_logger();
|
|
33288
33467
|
init_dist2();
|
|
33289
33468
|
|
|
33290
33469
|
class SkillsMigrationPrompts {
|
|
33291
33470
|
static async promptMigrationDecision(detection) {
|
|
33471
|
+
if (isNonInteractive()) {
|
|
33472
|
+
logger.info("Non-interactive mode: proceeding with skills migration");
|
|
33473
|
+
return true;
|
|
33474
|
+
}
|
|
33292
33475
|
const customizedCount = detection.customizations.filter((c2) => c2.isCustomized).length;
|
|
33293
33476
|
const totalSkills = detection.skillMappings.length;
|
|
33294
33477
|
let message = `Skills directory structure migration available.
|
|
@@ -33334,6 +33517,10 @@ Would you like to migrate now?`;
|
|
|
33334
33517
|
if (customizations.length === 0) {
|
|
33335
33518
|
return "preserve";
|
|
33336
33519
|
}
|
|
33520
|
+
if (isNonInteractive()) {
|
|
33521
|
+
logger.info("Non-interactive mode: preserving all customizations");
|
|
33522
|
+
return "preserve";
|
|
33523
|
+
}
|
|
33337
33524
|
const result = await ie({
|
|
33338
33525
|
message: "How should customized skills be handled?",
|
|
33339
33526
|
options: [
|
|
@@ -33358,6 +33545,10 @@ Would you like to migrate now?`;
|
|
|
33358
33545
|
return result;
|
|
33359
33546
|
}
|
|
33360
33547
|
static async promptSkillMigration(skillName, customization) {
|
|
33548
|
+
if (isNonInteractive()) {
|
|
33549
|
+
logger.info(`Non-interactive mode: migrating skill ${skillName}`);
|
|
33550
|
+
return true;
|
|
33551
|
+
}
|
|
33361
33552
|
let message = `Migrate skill: ${skillName}?`;
|
|
33362
33553
|
if (customization.isCustomized && customization.changes) {
|
|
33363
33554
|
const changes = customization.changes;
|
|
@@ -33403,6 +33594,10 @@ Detected changes:`;
|
|
|
33403
33594
|
f2.message("");
|
|
33404
33595
|
}
|
|
33405
33596
|
static async promptBackup() {
|
|
33597
|
+
if (isNonInteractive()) {
|
|
33598
|
+
logger.info("Non-interactive mode: creating backup before migration");
|
|
33599
|
+
return true;
|
|
33600
|
+
}
|
|
33406
33601
|
const result = await se({
|
|
33407
33602
|
message: "Create backup of current skills directory before migration?",
|
|
33408
33603
|
initialValue: true
|
|
@@ -33428,8 +33623,8 @@ async function copySkillDirectory(sourceDir, destDir) {
|
|
|
33428
33623
|
await mkdir14(destDir, { recursive: true });
|
|
33429
33624
|
const entries = await readdir16(sourceDir, { withFileTypes: true });
|
|
33430
33625
|
for (const entry of entries) {
|
|
33431
|
-
const sourcePath =
|
|
33432
|
-
const destPath =
|
|
33626
|
+
const sourcePath = join46(sourceDir, entry.name);
|
|
33627
|
+
const destPath = join46(destDir, entry.name);
|
|
33433
33628
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
33434
33629
|
continue;
|
|
33435
33630
|
}
|
|
@@ -33444,7 +33639,7 @@ async function executeMigration(mappings, customizations, currentSkillsDir, inte
|
|
|
33444
33639
|
const migrated = [];
|
|
33445
33640
|
const preserved = [];
|
|
33446
33641
|
const errors2 = [];
|
|
33447
|
-
const tempDir =
|
|
33642
|
+
const tempDir = join46(currentSkillsDir, "..", ".skills-migration-temp");
|
|
33448
33643
|
await mkdir14(tempDir, { recursive: true });
|
|
33449
33644
|
try {
|
|
33450
33645
|
for (const mapping of mappings) {
|
|
@@ -33465,9 +33660,9 @@ async function executeMigration(mappings, customizations, currentSkillsDir, inte
|
|
|
33465
33660
|
}
|
|
33466
33661
|
}
|
|
33467
33662
|
const category = mapping.category;
|
|
33468
|
-
const targetPath = category ?
|
|
33663
|
+
const targetPath = category ? join46(tempDir, category, skillName) : join46(tempDir, skillName);
|
|
33469
33664
|
if (category) {
|
|
33470
|
-
await mkdir14(
|
|
33665
|
+
await mkdir14(join46(tempDir, category), { recursive: true });
|
|
33471
33666
|
}
|
|
33472
33667
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
33473
33668
|
migrated.push(skillName);
|
|
@@ -33529,7 +33724,7 @@ init_logger();
|
|
|
33529
33724
|
init_types2();
|
|
33530
33725
|
var import_fs_extra21 = __toESM(require_lib(), 1);
|
|
33531
33726
|
import { copyFile as copyFile5, mkdir as mkdir15, readdir as readdir17, rm as rm4, stat as stat8 } from "node:fs/promises";
|
|
33532
|
-
import { basename as basename2, join as
|
|
33727
|
+
import { basename as basename2, join as join47, normalize as normalize5 } from "node:path";
|
|
33533
33728
|
function validatePath2(path9, paramName) {
|
|
33534
33729
|
if (!path9 || typeof path9 !== "string") {
|
|
33535
33730
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -33555,7 +33750,7 @@ class SkillsBackupManager {
|
|
|
33555
33750
|
const timestamp = Date.now();
|
|
33556
33751
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
33557
33752
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
33558
|
-
const backupDir = parentDir ?
|
|
33753
|
+
const backupDir = parentDir ? join47(parentDir, backupDirName) : join47(skillsDir, "..", backupDirName);
|
|
33559
33754
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
33560
33755
|
try {
|
|
33561
33756
|
await mkdir15(backupDir, { recursive: true });
|
|
@@ -33606,7 +33801,7 @@ class SkillsBackupManager {
|
|
|
33606
33801
|
}
|
|
33607
33802
|
try {
|
|
33608
33803
|
const entries = await readdir17(parentDir, { withFileTypes: true });
|
|
33609
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
33804
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join47(parentDir, entry.name));
|
|
33610
33805
|
backups.sort().reverse();
|
|
33611
33806
|
return backups;
|
|
33612
33807
|
} catch (error) {
|
|
@@ -33634,8 +33829,8 @@ class SkillsBackupManager {
|
|
|
33634
33829
|
static async copyDirectory(sourceDir, destDir) {
|
|
33635
33830
|
const entries = await readdir17(sourceDir, { withFileTypes: true });
|
|
33636
33831
|
for (const entry of entries) {
|
|
33637
|
-
const sourcePath =
|
|
33638
|
-
const destPath =
|
|
33832
|
+
const sourcePath = join47(sourceDir, entry.name);
|
|
33833
|
+
const destPath = join47(destDir, entry.name);
|
|
33639
33834
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
33640
33835
|
continue;
|
|
33641
33836
|
}
|
|
@@ -33651,7 +33846,7 @@ class SkillsBackupManager {
|
|
|
33651
33846
|
let size = 0;
|
|
33652
33847
|
const entries = await readdir17(dirPath, { withFileTypes: true });
|
|
33653
33848
|
for (const entry of entries) {
|
|
33654
|
-
const fullPath =
|
|
33849
|
+
const fullPath = join47(dirPath, entry.name);
|
|
33655
33850
|
if (entry.isSymbolicLink()) {
|
|
33656
33851
|
continue;
|
|
33657
33852
|
}
|
|
@@ -33686,12 +33881,12 @@ import { relative as relative10 } from "node:path";
|
|
|
33686
33881
|
import { createHash as createHash3 } from "node:crypto";
|
|
33687
33882
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
33688
33883
|
import { readFile as readFile15, readdir as readdir18 } from "node:fs/promises";
|
|
33689
|
-
import { join as
|
|
33884
|
+
import { join as join48, relative as relative9 } from "node:path";
|
|
33690
33885
|
async function getAllFiles(dirPath) {
|
|
33691
33886
|
const files = [];
|
|
33692
33887
|
const entries = await readdir18(dirPath, { withFileTypes: true });
|
|
33693
33888
|
for (const entry of entries) {
|
|
33694
|
-
const fullPath =
|
|
33889
|
+
const fullPath = join48(dirPath, entry.name);
|
|
33695
33890
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
33696
33891
|
continue;
|
|
33697
33892
|
}
|
|
@@ -33818,7 +34013,7 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
33818
34013
|
init_types2();
|
|
33819
34014
|
var import_fs_extra23 = __toESM(require_lib(), 1);
|
|
33820
34015
|
import { readdir as readdir19 } from "node:fs/promises";
|
|
33821
|
-
import { join as
|
|
34016
|
+
import { join as join49, normalize as normalize6 } from "node:path";
|
|
33822
34017
|
function validatePath3(path9, paramName) {
|
|
33823
34018
|
if (!path9 || typeof path9 !== "string") {
|
|
33824
34019
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -33839,13 +34034,13 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
33839
34034
|
if (dirs.length === 0) {
|
|
33840
34035
|
return ["flat", []];
|
|
33841
34036
|
}
|
|
33842
|
-
const firstDirPath =
|
|
34037
|
+
const firstDirPath = join49(skillsDir, dirs[0].name);
|
|
33843
34038
|
const subEntries = await readdir19(firstDirPath, { withFileTypes: true });
|
|
33844
34039
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
33845
34040
|
if (subdirs.length > 0) {
|
|
33846
34041
|
let skillLikeCount = 0;
|
|
33847
34042
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
33848
|
-
const subdirPath =
|
|
34043
|
+
const subdirPath = join49(firstDirPath, subdir.name);
|
|
33849
34044
|
const subdirFiles = await readdir19(subdirPath, { withFileTypes: true });
|
|
33850
34045
|
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"));
|
|
33851
34046
|
if (hasSkillMarker) {
|
|
@@ -33855,7 +34050,7 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
33855
34050
|
if (skillLikeCount > 0) {
|
|
33856
34051
|
const skills = [];
|
|
33857
34052
|
for (const dir of dirs) {
|
|
33858
|
-
const categoryPath =
|
|
34053
|
+
const categoryPath = join49(skillsDir, dir.name);
|
|
33859
34054
|
const skillDirs = await readdir19(categoryPath, { withFileTypes: true });
|
|
33860
34055
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
33861
34056
|
}
|
|
@@ -33865,7 +34060,7 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
33865
34060
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
33866
34061
|
}
|
|
33867
34062
|
async function findSkillPath(skillsDir, skillName) {
|
|
33868
|
-
const flatPath =
|
|
34063
|
+
const flatPath = join49(skillsDir, skillName);
|
|
33869
34064
|
if (await import_fs_extra23.pathExists(flatPath)) {
|
|
33870
34065
|
return { path: flatPath, category: undefined };
|
|
33871
34066
|
}
|
|
@@ -33874,8 +34069,8 @@ async function findSkillPath(skillsDir, skillName) {
|
|
|
33874
34069
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
33875
34070
|
continue;
|
|
33876
34071
|
}
|
|
33877
|
-
const categoryPath =
|
|
33878
|
-
const skillPath =
|
|
34072
|
+
const categoryPath = join49(skillsDir, entry.name);
|
|
34073
|
+
const skillPath = join49(categoryPath, skillName);
|
|
33879
34074
|
if (await import_fs_extra23.pathExists(skillPath)) {
|
|
33880
34075
|
return { path: skillPath, category: entry.name };
|
|
33881
34076
|
}
|
|
@@ -33969,7 +34164,7 @@ class SkillsMigrator {
|
|
|
33969
34164
|
}
|
|
33970
34165
|
}
|
|
33971
34166
|
if (options.backup && !options.dryRun) {
|
|
33972
|
-
const claudeDir =
|
|
34167
|
+
const claudeDir = join50(currentSkillsDir, "..");
|
|
33973
34168
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
33974
34169
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
33975
34170
|
}
|
|
@@ -34029,7 +34224,7 @@ async function handleMigration(ctx) {
|
|
|
34029
34224
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
34030
34225
|
return ctx;
|
|
34031
34226
|
}
|
|
34032
|
-
const newSkillsDir =
|
|
34227
|
+
const newSkillsDir = join51(ctx.extractDir, ".claude", "skills");
|
|
34033
34228
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
34034
34229
|
if (!await import_fs_extra24.pathExists(newSkillsDir) || !await import_fs_extra24.pathExists(currentSkillsDir)) {
|
|
34035
34230
|
return ctx;
|
|
@@ -34057,7 +34252,7 @@ import { existsSync as existsSync15 } from "node:fs";
|
|
|
34057
34252
|
import { mkdir as mkdir16, readFile as readFile16, rename as rename2, rm as rm5, writeFile as writeFile13 } from "node:fs/promises";
|
|
34058
34253
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
34059
34254
|
import { platform as platform9 } from "node:os";
|
|
34060
|
-
import { join as
|
|
34255
|
+
import { join as join52 } from "node:path";
|
|
34061
34256
|
init_types2();
|
|
34062
34257
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
34063
34258
|
|
|
@@ -34065,7 +34260,7 @@ class ConfigManager {
|
|
|
34065
34260
|
static config = null;
|
|
34066
34261
|
static globalFlag = false;
|
|
34067
34262
|
static getProjectConfigDir(projectDir, global3) {
|
|
34068
|
-
return global3 ? projectDir :
|
|
34263
|
+
return global3 ? projectDir : join52(projectDir, ".claude");
|
|
34069
34264
|
}
|
|
34070
34265
|
static setGlobalFlag(global3) {
|
|
34071
34266
|
ConfigManager.globalFlag = global3;
|
|
@@ -34132,7 +34327,7 @@ class ConfigManager {
|
|
|
34132
34327
|
}
|
|
34133
34328
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
34134
34329
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
34135
|
-
const configPath =
|
|
34330
|
+
const configPath = join52(configDir, PROJECT_CONFIG_FILE);
|
|
34136
34331
|
try {
|
|
34137
34332
|
if (existsSync15(configPath)) {
|
|
34138
34333
|
const content = await readFile16(configPath, "utf-8");
|
|
@@ -34148,7 +34343,7 @@ class ConfigManager {
|
|
|
34148
34343
|
}
|
|
34149
34344
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
34150
34345
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
34151
|
-
const configPath =
|
|
34346
|
+
const configPath = join52(configDir, PROJECT_CONFIG_FILE);
|
|
34152
34347
|
try {
|
|
34153
34348
|
if (!existsSync15(configDir)) {
|
|
34154
34349
|
await mkdir16(configDir, { recursive: true });
|
|
@@ -34180,11 +34375,11 @@ class ConfigManager {
|
|
|
34180
34375
|
}
|
|
34181
34376
|
static projectConfigExists(projectDir, global3 = false) {
|
|
34182
34377
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
34183
|
-
return existsSync15(
|
|
34378
|
+
return existsSync15(join52(configDir, PROJECT_CONFIG_FILE));
|
|
34184
34379
|
}
|
|
34185
34380
|
static async migrateNestedConfig(globalDir) {
|
|
34186
|
-
const correctPath =
|
|
34187
|
-
const incorrectPath =
|
|
34381
|
+
const correctPath = join52(globalDir, PROJECT_CONFIG_FILE);
|
|
34382
|
+
const incorrectPath = join52(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
34188
34383
|
if (existsSync15(correctPath)) {
|
|
34189
34384
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
34190
34385
|
return false;
|
|
@@ -34194,7 +34389,7 @@ class ConfigManager {
|
|
|
34194
34389
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
34195
34390
|
await rename2(incorrectPath, correctPath);
|
|
34196
34391
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
34197
|
-
const nestedClaudeDir =
|
|
34392
|
+
const nestedClaudeDir = join52(globalDir, ".claude");
|
|
34198
34393
|
try {
|
|
34199
34394
|
await rm5(nestedClaudeDir, { recursive: false });
|
|
34200
34395
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -34231,6 +34426,7 @@ async function resolveOptions(ctx) {
|
|
|
34231
34426
|
docsDir: parsed.docsDir,
|
|
34232
34427
|
plansDir: parsed.plansDir,
|
|
34233
34428
|
installSkills: parsed.installSkills ?? false,
|
|
34429
|
+
withSudo: parsed.withSudo ?? false,
|
|
34234
34430
|
skipSetup: parsed.skipSetup ?? false,
|
|
34235
34431
|
forceOverwrite: parsed.forceOverwrite ?? false,
|
|
34236
34432
|
forceOverwriteSettings: parsed.forceOverwriteSettings ?? false,
|
|
@@ -34253,14 +34449,14 @@ async function resolveOptions(ctx) {
|
|
|
34253
34449
|
};
|
|
34254
34450
|
}
|
|
34255
34451
|
// src/commands/init/phases/post-install-handler.ts
|
|
34256
|
-
import { join as
|
|
34452
|
+
import { join as join55 } from "node:path";
|
|
34257
34453
|
|
|
34258
34454
|
// src/domains/installation/setup-wizard.ts
|
|
34259
|
-
import { join as
|
|
34455
|
+
import { join as join54 } from "node:path";
|
|
34260
34456
|
|
|
34261
34457
|
// src/domains/config/config-generator.ts
|
|
34262
34458
|
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
34263
|
-
import { join as
|
|
34459
|
+
import { join as join53 } from "node:path";
|
|
34264
34460
|
async function generateEnvFile(targetDir, values) {
|
|
34265
34461
|
const lines = [
|
|
34266
34462
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -34272,7 +34468,7 @@ async function generateEnvFile(targetDir, values) {
|
|
|
34272
34468
|
lines.push(`${key}=${value}`);
|
|
34273
34469
|
}
|
|
34274
34470
|
}
|
|
34275
|
-
const envPath =
|
|
34471
|
+
const envPath = join53(targetDir, ".env");
|
|
34276
34472
|
await import_fs_extra25.writeFile(envPath, `${lines.join(`
|
|
34277
34473
|
`)}
|
|
34278
34474
|
`, { mode: 384 });
|
|
@@ -34346,7 +34542,7 @@ async function parseEnvFile(path9) {
|
|
|
34346
34542
|
}
|
|
34347
34543
|
}
|
|
34348
34544
|
async function checkGlobalConfig() {
|
|
34349
|
-
const globalEnvPath =
|
|
34545
|
+
const globalEnvPath = join54(PathResolver.getGlobalKitDir(), ".env");
|
|
34350
34546
|
if (!await import_fs_extra26.pathExists(globalEnvPath))
|
|
34351
34547
|
return false;
|
|
34352
34548
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -34362,7 +34558,7 @@ async function runSetupWizard(options) {
|
|
|
34362
34558
|
let globalEnv = {};
|
|
34363
34559
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
34364
34560
|
if (!isGlobal) {
|
|
34365
|
-
const globalEnvPath =
|
|
34561
|
+
const globalEnvPath = join54(PathResolver.getGlobalKitDir(), ".env");
|
|
34366
34562
|
if (await import_fs_extra26.pathExists(globalEnvPath)) {
|
|
34367
34563
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
34368
34564
|
}
|
|
@@ -34415,7 +34611,7 @@ async function runSetupWizard(options) {
|
|
|
34415
34611
|
}
|
|
34416
34612
|
}
|
|
34417
34613
|
await generateEnvFile(targetDir, values);
|
|
34418
|
-
f2.success(`Configuration saved to ${
|
|
34614
|
+
f2.success(`Configuration saved to ${join54(targetDir, ".env")}`);
|
|
34419
34615
|
return true;
|
|
34420
34616
|
}
|
|
34421
34617
|
|
|
@@ -34427,8 +34623,8 @@ async function handlePostInstall(ctx) {
|
|
|
34427
34623
|
return ctx;
|
|
34428
34624
|
}
|
|
34429
34625
|
if (ctx.options.global) {
|
|
34430
|
-
const claudeMdSource =
|
|
34431
|
-
const claudeMdDest =
|
|
34626
|
+
const claudeMdSource = join55(ctx.extractDir, "CLAUDE.md");
|
|
34627
|
+
const claudeMdDest = join55(ctx.resolvedDir, "CLAUDE.md");
|
|
34432
34628
|
if (await import_fs_extra27.pathExists(claudeMdSource)) {
|
|
34433
34629
|
if (!await import_fs_extra27.pathExists(claudeMdDest)) {
|
|
34434
34630
|
await import_fs_extra27.copy(claudeMdSource, claudeMdDest);
|
|
@@ -34445,7 +34641,10 @@ async function handlePostInstall(ctx) {
|
|
|
34445
34641
|
if (installSkills) {
|
|
34446
34642
|
const { handleSkillsInstallation: handleSkillsInstallation2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
|
|
34447
34643
|
const skillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
34448
|
-
await handleSkillsInstallation2(skillsDir
|
|
34644
|
+
await handleSkillsInstallation2(skillsDir, {
|
|
34645
|
+
skipConfirm: ctx.isNonInteractive,
|
|
34646
|
+
withSudo: ctx.options.withSudo
|
|
34647
|
+
});
|
|
34449
34648
|
}
|
|
34450
34649
|
if (!ctx.isNonInteractive) {
|
|
34451
34650
|
const { isGeminiInstalled: isGeminiInstalled2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
|
|
@@ -34472,7 +34671,7 @@ async function handlePostInstall(ctx) {
|
|
|
34472
34671
|
}
|
|
34473
34672
|
}
|
|
34474
34673
|
if (!ctx.options.skipSetup && !ctx.isNonInteractive) {
|
|
34475
|
-
const envPath =
|
|
34674
|
+
const envPath = join55(ctx.claudeDir, ".env");
|
|
34476
34675
|
if (!await import_fs_extra27.pathExists(envPath)) {
|
|
34477
34676
|
const shouldSetup = await ctx.prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
34478
34677
|
if (shouldSetup) {
|
|
@@ -34494,11 +34693,11 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
|
|
|
34494
34693
|
}
|
|
34495
34694
|
// src/commands/init/phases/selection-handler.ts
|
|
34496
34695
|
import { mkdir as mkdir17 } from "node:fs/promises";
|
|
34497
|
-
import { join as
|
|
34696
|
+
import { join as join57, resolve as resolve7 } from "node:path";
|
|
34498
34697
|
|
|
34499
34698
|
// src/domains/installation/fresh-installer.ts
|
|
34500
34699
|
init_logger();
|
|
34501
|
-
import { join as
|
|
34700
|
+
import { join as join56 } from "node:path";
|
|
34502
34701
|
var import_fs_extra28 = __toESM(require_lib(), 1);
|
|
34503
34702
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
34504
34703
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
@@ -34517,7 +34716,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
34517
34716
|
const { rmSync } = await import("node:fs");
|
|
34518
34717
|
let removedCount = 0;
|
|
34519
34718
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
34520
|
-
const subdirPath =
|
|
34719
|
+
const subdirPath = join56(claudeDir, subdir);
|
|
34521
34720
|
if (await import_fs_extra28.pathExists(subdirPath)) {
|
|
34522
34721
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
34523
34722
|
removedCount++;
|
|
@@ -34582,7 +34781,7 @@ async function handleSelection(ctx) {
|
|
|
34582
34781
|
}
|
|
34583
34782
|
if (ctx.options.fresh) {
|
|
34584
34783
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
34585
|
-
const claudeDir = prefix ?
|
|
34784
|
+
const claudeDir = prefix ? join57(resolvedDir, prefix) : resolvedDir;
|
|
34586
34785
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
34587
34786
|
if (!canProceed) {
|
|
34588
34787
|
return { ...ctx, cancelled: true };
|
|
@@ -34610,7 +34809,7 @@ async function handleSelection(ctx) {
|
|
|
34610
34809
|
logger.info("Fetching available versions...");
|
|
34611
34810
|
let currentVersion = null;
|
|
34612
34811
|
try {
|
|
34613
|
-
const metadataPath = ctx.options.global ?
|
|
34812
|
+
const metadataPath = ctx.options.global ? join57(PathResolver.getGlobalKitDir(), "metadata.json") : join57(resolvedDir, ".claude", "metadata.json");
|
|
34614
34813
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
34615
34814
|
currentVersion = metadata?.version || null;
|
|
34616
34815
|
if (currentVersion) {
|
|
@@ -34664,7 +34863,7 @@ async function handleSelection(ctx) {
|
|
|
34664
34863
|
};
|
|
34665
34864
|
}
|
|
34666
34865
|
// src/commands/init/phases/transform-handler.ts
|
|
34667
|
-
import { join as
|
|
34866
|
+
import { join as join61 } from "node:path";
|
|
34668
34867
|
|
|
34669
34868
|
// src/services/transformers/folder-path-transformer.ts
|
|
34670
34869
|
init_logger();
|
|
@@ -34675,38 +34874,38 @@ init_logger();
|
|
|
34675
34874
|
init_types2();
|
|
34676
34875
|
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
34677
34876
|
import { rename as rename3 } from "node:fs/promises";
|
|
34678
|
-
import { join as
|
|
34877
|
+
import { join as join58, relative as relative11 } from "node:path";
|
|
34679
34878
|
async function collectDirsToRename(extractDir, folders) {
|
|
34680
34879
|
const dirsToRename = [];
|
|
34681
34880
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
34682
|
-
const docsPath =
|
|
34881
|
+
const docsPath = join58(extractDir, DEFAULT_FOLDERS.docs);
|
|
34683
34882
|
if (await import_fs_extra30.pathExists(docsPath)) {
|
|
34684
34883
|
dirsToRename.push({
|
|
34685
34884
|
from: docsPath,
|
|
34686
|
-
to:
|
|
34885
|
+
to: join58(extractDir, folders.docs)
|
|
34687
34886
|
});
|
|
34688
34887
|
}
|
|
34689
|
-
const claudeDocsPath =
|
|
34888
|
+
const claudeDocsPath = join58(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
34690
34889
|
if (await import_fs_extra30.pathExists(claudeDocsPath)) {
|
|
34691
34890
|
dirsToRename.push({
|
|
34692
34891
|
from: claudeDocsPath,
|
|
34693
|
-
to:
|
|
34892
|
+
to: join58(extractDir, ".claude", folders.docs)
|
|
34694
34893
|
});
|
|
34695
34894
|
}
|
|
34696
34895
|
}
|
|
34697
34896
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
34698
|
-
const plansPath =
|
|
34897
|
+
const plansPath = join58(extractDir, DEFAULT_FOLDERS.plans);
|
|
34699
34898
|
if (await import_fs_extra30.pathExists(plansPath)) {
|
|
34700
34899
|
dirsToRename.push({
|
|
34701
34900
|
from: plansPath,
|
|
34702
|
-
to:
|
|
34901
|
+
to: join58(extractDir, folders.plans)
|
|
34703
34902
|
});
|
|
34704
34903
|
}
|
|
34705
|
-
const claudePlansPath =
|
|
34904
|
+
const claudePlansPath = join58(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
34706
34905
|
if (await import_fs_extra30.pathExists(claudePlansPath)) {
|
|
34707
34906
|
dirsToRename.push({
|
|
34708
34907
|
from: claudePlansPath,
|
|
34709
|
-
to:
|
|
34908
|
+
to: join58(extractDir, ".claude", folders.plans)
|
|
34710
34909
|
});
|
|
34711
34910
|
}
|
|
34712
34911
|
}
|
|
@@ -34734,7 +34933,7 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
34734
34933
|
init_logger();
|
|
34735
34934
|
init_types2();
|
|
34736
34935
|
import { readFile as readFile18, readdir as readdir20, writeFile as writeFile15 } from "node:fs/promises";
|
|
34737
|
-
import { join as
|
|
34936
|
+
import { join as join59, relative as relative12 } from "node:path";
|
|
34738
34937
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
34739
34938
|
".md",
|
|
34740
34939
|
".txt",
|
|
@@ -34787,7 +34986,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
34787
34986
|
let replacementsCount = 0;
|
|
34788
34987
|
const entries = await readdir20(dir, { withFileTypes: true });
|
|
34789
34988
|
for (const entry of entries) {
|
|
34790
|
-
const fullPath =
|
|
34989
|
+
const fullPath = join59(dir, entry.name);
|
|
34791
34990
|
if (entry.isDirectory()) {
|
|
34792
34991
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
34793
34992
|
continue;
|
|
@@ -34924,7 +35123,7 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
34924
35123
|
init_logger();
|
|
34925
35124
|
import { readFile as readFile19, readdir as readdir21, writeFile as writeFile16 } from "node:fs/promises";
|
|
34926
35125
|
import { platform as platform10 } from "node:os";
|
|
34927
|
-
import { extname, join as
|
|
35126
|
+
import { extname, join as join60 } from "node:path";
|
|
34928
35127
|
var IS_WINDOWS3 = platform10() === "win32";
|
|
34929
35128
|
var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
|
|
34930
35129
|
function getHomeDirPrefix() {
|
|
@@ -35016,7 +35215,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
35016
35215
|
async function processDirectory2(dir) {
|
|
35017
35216
|
const entries = await readdir21(dir, { withFileTypes: true });
|
|
35018
35217
|
for (const entry of entries) {
|
|
35019
|
-
const fullPath =
|
|
35218
|
+
const fullPath = join60(dir, entry.name);
|
|
35020
35219
|
if (entry.isDirectory()) {
|
|
35021
35220
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
35022
35221
|
continue;
|
|
@@ -35092,7 +35291,7 @@ async function handleTransforms(ctx) {
|
|
|
35092
35291
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
35093
35292
|
}
|
|
35094
35293
|
}
|
|
35095
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
35294
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join61(ctx.resolvedDir, ".claude");
|
|
35096
35295
|
return {
|
|
35097
35296
|
...ctx,
|
|
35098
35297
|
foldersConfig,
|
|
@@ -35111,6 +35310,7 @@ function createInitContext(rawOptions, prompts) {
|
|
|
35111
35310
|
exclude: [],
|
|
35112
35311
|
only: [],
|
|
35113
35312
|
installSkills: false,
|
|
35313
|
+
withSudo: false,
|
|
35114
35314
|
skipSetup: false,
|
|
35115
35315
|
forceOverwrite: false,
|
|
35116
35316
|
forceOverwriteSettings: false,
|
|
@@ -35227,57 +35427,28 @@ async function directorySetup(validOptions, prompts) {
|
|
|
35227
35427
|
isNonInteractive: isNonInteractive2
|
|
35228
35428
|
};
|
|
35229
35429
|
}
|
|
35230
|
-
|
|
35231
|
-
|
|
35232
|
-
|
|
35233
|
-
|
|
35234
|
-
async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts) {
|
|
35235
|
-
let installOpenCode2 = validOptions.opencode;
|
|
35236
|
-
let installGemini2 = validOptions.gemini;
|
|
35237
|
-
let installSkills = validOptions.installSkills;
|
|
35238
|
-
if (!isNonInteractive2 && !installOpenCode2 && !installGemini2 && !installSkills) {
|
|
35239
|
-
const packageChoices = await prompts.promptPackageInstallations();
|
|
35240
|
-
installOpenCode2 = packageChoices.installOpenCode;
|
|
35241
|
-
installGemini2 = packageChoices.installGemini;
|
|
35242
|
-
installSkills = await prompts.promptSkillsInstallation();
|
|
35243
|
-
}
|
|
35244
|
-
if (installOpenCode2 || installGemini2) {
|
|
35245
|
-
logger.info("Installing optional packages...");
|
|
35246
|
-
try {
|
|
35247
|
-
const installationResults = await processPackageInstallations(installOpenCode2, installGemini2, resolvedDir);
|
|
35248
|
-
prompts.showPackageInstallationResults(installationResults);
|
|
35249
|
-
} catch (error) {
|
|
35250
|
-
logger.warning(`Package installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
35251
|
-
logger.info("You can install these packages manually later using npm install -g <package>");
|
|
35252
|
-
}
|
|
35253
|
-
}
|
|
35254
|
-
if (installSkills) {
|
|
35255
|
-
const { handleSkillsInstallation: handleSkillsInstallation2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
|
|
35256
|
-
const skillsDir = PathResolver.buildSkillsPath(resolvedDir, false);
|
|
35257
|
-
await handleSkillsInstallation2(skillsDir);
|
|
35430
|
+
async function handleDirectorySetup(ctx) {
|
|
35431
|
+
const result = await directorySetup(ctx.options, ctx.prompts);
|
|
35432
|
+
if (!result) {
|
|
35433
|
+
return { ...ctx, cancelled: true };
|
|
35258
35434
|
}
|
|
35435
|
+
return {
|
|
35436
|
+
...ctx,
|
|
35437
|
+
kit: result.kit,
|
|
35438
|
+
resolvedDir: result.resolvedDir,
|
|
35439
|
+
isNonInteractive: result.isNonInteractive
|
|
35440
|
+
};
|
|
35259
35441
|
}
|
|
35260
|
-
|
|
35261
35442
|
// src/commands/new/phases/project-creation.ts
|
|
35262
|
-
import { join as
|
|
35263
|
-
init_environment();
|
|
35443
|
+
import { join as join62 } from "node:path";
|
|
35264
35444
|
init_logger();
|
|
35265
35445
|
init_output_manager();
|
|
35266
35446
|
init_types2();
|
|
35267
|
-
|
|
35268
|
-
|
|
35269
|
-
|
|
35270
|
-
|
|
35271
|
-
|
|
35272
|
-
try {
|
|
35273
|
-
await github.checkAccess(kitConfig);
|
|
35274
|
-
spinner.succeed("Repository access verified");
|
|
35275
|
-
} catch (error) {
|
|
35276
|
-
spinner.fail("Access denied to repository");
|
|
35277
|
-
logger.error(error.message || `Cannot access ${kitConfig.name}`);
|
|
35278
|
-
return null;
|
|
35279
|
-
}
|
|
35280
|
-
let selectedVersion = validOptions.release;
|
|
35447
|
+
|
|
35448
|
+
// src/commands/new/phases/version-selection.ts
|
|
35449
|
+
init_logger();
|
|
35450
|
+
async function selectVersion2(kit, options, isNonInteractive2, prompts, github) {
|
|
35451
|
+
let selectedVersion = options.release;
|
|
35281
35452
|
if (!selectedVersion && isNonInteractive2) {
|
|
35282
35453
|
throw new Error("Interactive version selection unavailable in non-interactive mode. " + "Either: (1) use --release <tag> flag, or (2) set CI=false to enable interactive mode");
|
|
35283
35454
|
}
|
|
@@ -35285,11 +35456,11 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
35285
35456
|
logger.info("Fetching available versions...");
|
|
35286
35457
|
try {
|
|
35287
35458
|
const versionResult = await prompts.selectVersionEnhanced({
|
|
35288
|
-
kit
|
|
35289
|
-
includePrereleases:
|
|
35459
|
+
kit,
|
|
35460
|
+
includePrereleases: options.beta,
|
|
35290
35461
|
limit: 10,
|
|
35291
35462
|
allowManualEntry: true,
|
|
35292
|
-
forceRefresh:
|
|
35463
|
+
forceRefresh: options.refresh
|
|
35293
35464
|
});
|
|
35294
35465
|
if (!versionResult) {
|
|
35295
35466
|
logger.warning("Version selection cancelled by user");
|
|
@@ -35299,73 +35470,57 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
35299
35470
|
logger.success(`Selected version: ${selectedVersion}`);
|
|
35300
35471
|
} catch (error) {
|
|
35301
35472
|
logger.error("Failed to fetch versions, using latest release");
|
|
35302
|
-
|
|
35473
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35474
|
+
logger.debug(`Version selection error: ${message}`);
|
|
35303
35475
|
selectedVersion = undefined;
|
|
35304
35476
|
}
|
|
35305
35477
|
}
|
|
35306
35478
|
let release;
|
|
35307
35479
|
if (selectedVersion) {
|
|
35308
|
-
release = await github.getReleaseByTag(
|
|
35480
|
+
release = await github.getReleaseByTag(kit, selectedVersion);
|
|
35309
35481
|
} else {
|
|
35310
|
-
if (
|
|
35482
|
+
if (options.beta) {
|
|
35311
35483
|
logger.info("Fetching latest beta release...");
|
|
35312
35484
|
} else {
|
|
35313
35485
|
logger.info("Fetching latest release...");
|
|
35314
35486
|
}
|
|
35315
|
-
release = await github.getLatestRelease(
|
|
35487
|
+
release = await github.getLatestRelease(kit, options.beta);
|
|
35316
35488
|
if (release.prerelease) {
|
|
35317
35489
|
logger.success(`Found beta: ${release.tag_name}`);
|
|
35318
35490
|
} else {
|
|
35319
35491
|
logger.success(`Found: ${release.tag_name}`);
|
|
35320
35492
|
}
|
|
35321
35493
|
}
|
|
35322
|
-
|
|
35323
|
-
|
|
35324
|
-
|
|
35325
|
-
|
|
35326
|
-
|
|
35327
|
-
|
|
35328
|
-
|
|
35329
|
-
|
|
35330
|
-
const
|
|
35331
|
-
|
|
35332
|
-
|
|
35333
|
-
}
|
|
35334
|
-
const tempDir = await downloadManager.createTempDir();
|
|
35335
|
-
const { token } = await AuthManager.getToken();
|
|
35336
|
-
let archivePath;
|
|
35494
|
+
return {
|
|
35495
|
+
release,
|
|
35496
|
+
selectedVersion: release.tag_name
|
|
35497
|
+
};
|
|
35498
|
+
}
|
|
35499
|
+
|
|
35500
|
+
// src/commands/new/phases/project-creation.ts
|
|
35501
|
+
async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2, prompts) {
|
|
35502
|
+
const kitConfig = AVAILABLE_KITS[kit];
|
|
35503
|
+
const github = new GitHubClient;
|
|
35504
|
+
const spinner = createSpinner("Checking repository access...").start();
|
|
35505
|
+
logger.verbose("GitHub API check", { repo: kitConfig.repo, owner: kitConfig.owner });
|
|
35337
35506
|
try {
|
|
35338
|
-
|
|
35339
|
-
|
|
35340
|
-
name: downloadInfo.name,
|
|
35341
|
-
size: downloadInfo.size,
|
|
35342
|
-
destDir: tempDir,
|
|
35343
|
-
token
|
|
35344
|
-
});
|
|
35507
|
+
await github.checkAccess(kitConfig);
|
|
35508
|
+
spinner.succeed("Repository access verified");
|
|
35345
35509
|
} catch (error) {
|
|
35346
|
-
|
|
35347
|
-
|
|
35348
|
-
|
|
35349
|
-
type: "github-tarball",
|
|
35350
|
-
url: release.tarball_url,
|
|
35351
|
-
name: `${kitConfig.repo}-${release.tag_name}.tar.gz`,
|
|
35352
|
-
size: 0
|
|
35353
|
-
};
|
|
35354
|
-
archivePath = await downloadManager.downloadFile({
|
|
35355
|
-
url: tarballInfo.url,
|
|
35356
|
-
name: tarballInfo.name,
|
|
35357
|
-
size: tarballInfo.size,
|
|
35358
|
-
destDir: tempDir,
|
|
35359
|
-
token
|
|
35360
|
-
});
|
|
35361
|
-
} else {
|
|
35362
|
-
throw error;
|
|
35363
|
-
}
|
|
35510
|
+
spinner.fail("Access denied to repository");
|
|
35511
|
+
logger.error(error.message || `Cannot access ${kitConfig.name}`);
|
|
35512
|
+
return null;
|
|
35364
35513
|
}
|
|
35365
|
-
const
|
|
35366
|
-
|
|
35367
|
-
|
|
35368
|
-
|
|
35514
|
+
const versionResult = await selectVersion2(kitConfig, validOptions, isNonInteractive2, prompts, github);
|
|
35515
|
+
if (!versionResult) {
|
|
35516
|
+
return null;
|
|
35517
|
+
}
|
|
35518
|
+
const { release } = versionResult;
|
|
35519
|
+
const { extractDir } = await downloadAndExtract({
|
|
35520
|
+
release,
|
|
35521
|
+
kit: kitConfig,
|
|
35522
|
+
exclude: validOptions.exclude
|
|
35523
|
+
});
|
|
35369
35524
|
if (CommandsPrefix.shouldApplyPrefix(validOptions)) {
|
|
35370
35525
|
await CommandsPrefix.applyPrefix(extractDir);
|
|
35371
35526
|
}
|
|
@@ -35396,59 +35551,106 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
35396
35551
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
35397
35552
|
}
|
|
35398
35553
|
await merger.merge(extractDir, resolvedDir, true);
|
|
35399
|
-
const claudeDir =
|
|
35400
|
-
const manifestWriter = new ManifestWriter;
|
|
35554
|
+
const claudeDir = join62(resolvedDir, ".claude");
|
|
35401
35555
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
35402
35556
|
const installedFiles = merger.getAllInstalledFiles();
|
|
35403
|
-
const filesToTrack =
|
|
35404
|
-
|
|
35405
|
-
|
|
35406
|
-
|
|
35407
|
-
|
|
35408
|
-
|
|
35409
|
-
|
|
35410
|
-
|
|
35411
|
-
|
|
35412
|
-
|
|
35413
|
-
|
|
35414
|
-
|
|
35415
|
-
installedVersion: release.tag_name
|
|
35416
|
-
});
|
|
35417
|
-
}
|
|
35418
|
-
const trackingSpinner = createSpinner(`Tracking ${filesToTrack.length} installed files...`);
|
|
35419
|
-
trackingSpinner.start();
|
|
35420
|
-
const trackResult = await manifestWriter.addTrackedFilesBatch(filesToTrack, {
|
|
35421
|
-
concurrency: getOptimalConcurrency(),
|
|
35422
|
-
onProgress: (processed, total) => {
|
|
35423
|
-
trackingSpinner.text = `Tracking files... (${processed}/${total})`;
|
|
35424
|
-
}
|
|
35557
|
+
const filesToTrack = buildFileTrackingList({
|
|
35558
|
+
installedFiles,
|
|
35559
|
+
claudeDir,
|
|
35560
|
+
releaseManifest,
|
|
35561
|
+
installedVersion: release.tag_name,
|
|
35562
|
+
isGlobal: false
|
|
35563
|
+
});
|
|
35564
|
+
await trackFilesWithProgress(filesToTrack, {
|
|
35565
|
+
claudeDir,
|
|
35566
|
+
kitName: kitConfig.name,
|
|
35567
|
+
releaseTag: release.tag_name,
|
|
35568
|
+
mode: "local"
|
|
35425
35569
|
});
|
|
35426
|
-
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
35427
|
-
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, "local");
|
|
35428
35570
|
return {
|
|
35429
35571
|
releaseTag: release.tag_name,
|
|
35430
35572
|
installedFiles,
|
|
35431
35573
|
claudeDir
|
|
35432
35574
|
};
|
|
35433
35575
|
}
|
|
35434
|
-
|
|
35576
|
+
async function handleProjectCreation(ctx) {
|
|
35577
|
+
if (!ctx.kit || !ctx.resolvedDir) {
|
|
35578
|
+
return { ...ctx, cancelled: true };
|
|
35579
|
+
}
|
|
35580
|
+
const result = await projectCreation(ctx.kit, ctx.resolvedDir, ctx.options, ctx.isNonInteractive, ctx.prompts);
|
|
35581
|
+
if (!result) {
|
|
35582
|
+
return { ...ctx, cancelled: true };
|
|
35583
|
+
}
|
|
35584
|
+
return {
|
|
35585
|
+
...ctx,
|
|
35586
|
+
releaseTag: result.releaseTag,
|
|
35587
|
+
installedFiles: result.installedFiles,
|
|
35588
|
+
claudeDir: result.claudeDir
|
|
35589
|
+
};
|
|
35590
|
+
}
|
|
35591
|
+
// src/commands/new/phases/post-setup.ts
|
|
35592
|
+
init_package_installer();
|
|
35593
|
+
init_logger();
|
|
35594
|
+
async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts) {
|
|
35595
|
+
let installOpenCode2 = validOptions.opencode;
|
|
35596
|
+
let installGemini2 = validOptions.gemini;
|
|
35597
|
+
let installSkills = validOptions.installSkills;
|
|
35598
|
+
if (!isNonInteractive2 && !installOpenCode2 && !installGemini2 && !installSkills) {
|
|
35599
|
+
const packageChoices = await prompts.promptPackageInstallations();
|
|
35600
|
+
installOpenCode2 = packageChoices.installOpenCode;
|
|
35601
|
+
installGemini2 = packageChoices.installGemini;
|
|
35602
|
+
installSkills = await prompts.promptSkillsInstallation();
|
|
35603
|
+
}
|
|
35604
|
+
if (installOpenCode2 || installGemini2) {
|
|
35605
|
+
logger.info("Installing optional packages...");
|
|
35606
|
+
try {
|
|
35607
|
+
const installationResults = await processPackageInstallations(installOpenCode2, installGemini2, resolvedDir);
|
|
35608
|
+
prompts.showPackageInstallationResults(installationResults);
|
|
35609
|
+
} catch (error) {
|
|
35610
|
+
logger.warning(`Package installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
35611
|
+
logger.info("You can install these packages manually later using npm install -g <package>");
|
|
35612
|
+
}
|
|
35613
|
+
}
|
|
35614
|
+
if (installSkills) {
|
|
35615
|
+
const { handleSkillsInstallation: handleSkillsInstallation2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
|
|
35616
|
+
const skillsDir = PathResolver.buildSkillsPath(resolvedDir, false);
|
|
35617
|
+
await handleSkillsInstallation2(skillsDir, {
|
|
35618
|
+
skipConfirm: isNonInteractive2,
|
|
35619
|
+
withSudo: validOptions.withSudo
|
|
35620
|
+
});
|
|
35621
|
+
}
|
|
35622
|
+
}
|
|
35623
|
+
async function handlePostSetup(ctx) {
|
|
35624
|
+
if (!ctx.resolvedDir) {
|
|
35625
|
+
return { ...ctx, cancelled: true };
|
|
35626
|
+
}
|
|
35627
|
+
await postSetup(ctx.resolvedDir, ctx.options, ctx.isNonInteractive, ctx.prompts);
|
|
35628
|
+
return ctx;
|
|
35629
|
+
}
|
|
35435
35630
|
// src/commands/new/new-command.ts
|
|
35631
|
+
function createNewContext(options, prompts) {
|
|
35632
|
+
return {
|
|
35633
|
+
options,
|
|
35634
|
+
prompts,
|
|
35635
|
+
isNonInteractive: !process.stdin.isTTY || process.env.CI === "true",
|
|
35636
|
+
cancelled: false
|
|
35637
|
+
};
|
|
35638
|
+
}
|
|
35436
35639
|
async function newCommand(options) {
|
|
35437
35640
|
const prompts = new PromptsManager;
|
|
35438
35641
|
prompts.intro("\uD83D\uDE80 ClaudeKit - Create New Project");
|
|
35439
35642
|
try {
|
|
35440
|
-
|
|
35441
|
-
|
|
35442
|
-
if (
|
|
35643
|
+
let ctx = createNewContext(NewCommandOptionsSchema.parse(options), prompts);
|
|
35644
|
+
ctx = await handleDirectorySetup(ctx);
|
|
35645
|
+
if (ctx.cancelled)
|
|
35443
35646
|
return;
|
|
35444
|
-
|
|
35445
|
-
|
|
35446
|
-
const creationResult = await projectCreation(kit, resolvedDir, validOptions, isNonInteractive2, prompts);
|
|
35447
|
-
if (!creationResult) {
|
|
35647
|
+
ctx = await handleProjectCreation(ctx);
|
|
35648
|
+
if (ctx.cancelled)
|
|
35448
35649
|
return;
|
|
35449
|
-
|
|
35450
|
-
|
|
35451
|
-
|
|
35650
|
+
ctx = await handlePostSetup(ctx);
|
|
35651
|
+
if (ctx.cancelled)
|
|
35652
|
+
return;
|
|
35653
|
+
prompts.outro(`✨ Project created successfully at ${ctx.resolvedDir}`);
|
|
35452
35654
|
} catch (error) {
|
|
35453
35655
|
logger.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
35454
35656
|
process.exit(1);
|
|
@@ -35483,13 +35685,13 @@ async function detectInstallations() {
|
|
|
35483
35685
|
|
|
35484
35686
|
// src/commands/uninstall/removal-handler.ts
|
|
35485
35687
|
import { readdirSync as readdirSync2, rmSync as rmSync2 } from "node:fs";
|
|
35486
|
-
import { join as
|
|
35688
|
+
import { join as join64 } from "node:path";
|
|
35487
35689
|
init_logger();
|
|
35488
35690
|
var import_fs_extra33 = __toESM(require_lib(), 1);
|
|
35489
35691
|
|
|
35490
35692
|
// src/commands/uninstall/analysis-handler.ts
|
|
35491
35693
|
import { readdirSync, rmSync } from "node:fs";
|
|
35492
|
-
import { dirname as dirname8, join as
|
|
35694
|
+
import { dirname as dirname8, join as join63 } from "node:path";
|
|
35493
35695
|
init_logger();
|
|
35494
35696
|
var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
35495
35697
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -35536,7 +35738,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
35536
35738
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
35537
35739
|
const kitFiles = metadata.kits[kit].files || [];
|
|
35538
35740
|
for (const trackedFile of kitFiles) {
|
|
35539
|
-
const filePath =
|
|
35741
|
+
const filePath = join63(installation.path, trackedFile.path);
|
|
35540
35742
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
35541
35743
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
35542
35744
|
continue;
|
|
@@ -35566,7 +35768,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
35566
35768
|
return result;
|
|
35567
35769
|
}
|
|
35568
35770
|
for (const trackedFile of allTrackedFiles) {
|
|
35569
|
-
const filePath =
|
|
35771
|
+
const filePath = join63(installation.path, trackedFile.path);
|
|
35570
35772
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
35571
35773
|
if (!ownershipResult.exists)
|
|
35572
35774
|
continue;
|
|
@@ -35626,7 +35828,7 @@ async function removeInstallations(installations, options) {
|
|
|
35626
35828
|
let removedCount = 0;
|
|
35627
35829
|
let cleanedDirs = 0;
|
|
35628
35830
|
for (const item of analysis.toDelete) {
|
|
35629
|
-
const filePath =
|
|
35831
|
+
const filePath = join64(installation.path, item.path);
|
|
35630
35832
|
if (await import_fs_extra33.pathExists(filePath)) {
|
|
35631
35833
|
await import_fs_extra33.remove(filePath);
|
|
35632
35834
|
removedCount++;
|
|
@@ -35661,10 +35863,11 @@ async function removeInstallations(installations, options) {
|
|
|
35661
35863
|
}
|
|
35662
35864
|
|
|
35663
35865
|
// src/commands/uninstall/uninstall-command.ts
|
|
35866
|
+
var prompts = new PromptsManager;
|
|
35664
35867
|
function displayInstallations(installations, scope) {
|
|
35665
|
-
intro("ClaudeKit Uninstaller");
|
|
35868
|
+
prompts.intro("ClaudeKit Uninstaller");
|
|
35666
35869
|
const scopeLabel = scope === "all" ? "all" : scope === "local" ? "local only" : "global only";
|
|
35667
|
-
note(installations.map((i) => ` ${i.type === "local" ? "Local " : "Global"}: ${i.path}`).join(`
|
|
35870
|
+
prompts.note(installations.map((i) => ` ${i.type === "local" ? "Local " : "Global"}: ${i.path}`).join(`
|
|
35668
35871
|
`), `Detected ClaudeKit installations (${scopeLabel})`);
|
|
35669
35872
|
log.warn("[!] This will permanently delete ClaudeKit files from the above paths.");
|
|
35670
35873
|
}
|
|
@@ -35758,7 +35961,7 @@ async function uninstallCommand(options) {
|
|
|
35758
35961
|
forceOverwrite: validOptions.forceOverwrite,
|
|
35759
35962
|
kit: validOptions.kit
|
|
35760
35963
|
});
|
|
35761
|
-
outro("Dry-run complete. No changes were made.");
|
|
35964
|
+
prompts.outro("Dry-run complete. No changes were made.");
|
|
35762
35965
|
return;
|
|
35763
35966
|
}
|
|
35764
35967
|
if (validOptions.forceOverwrite) {
|
|
@@ -35779,7 +35982,7 @@ ${import_picocolors16.default.yellow("User modifications will be permanently del
|
|
|
35779
35982
|
kit: validOptions.kit
|
|
35780
35983
|
});
|
|
35781
35984
|
const kitMsg = validOptions.kit ? ` (${validOptions.kit} kit)` : "";
|
|
35782
|
-
outro(`ClaudeKit${kitMsg} uninstalled successfully!`);
|
|
35985
|
+
prompts.outro(`ClaudeKit${kitMsg} uninstalled successfully!`);
|
|
35783
35986
|
} catch (error) {
|
|
35784
35987
|
logger.error(error instanceof Error ? error.message : "Unknown error");
|
|
35785
35988
|
process.exit(1);
|
|
@@ -35932,7 +36135,7 @@ var import_compare_versions2 = __toESM(require_umd(), 1);
|
|
|
35932
36135
|
// package.json
|
|
35933
36136
|
var package_default = {
|
|
35934
36137
|
name: "claudekit-cli",
|
|
35935
|
-
version: "3.
|
|
36138
|
+
version: "3.13.0",
|
|
35936
36139
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
35937
36140
|
type: "module",
|
|
35938
36141
|
repository: {
|
|
@@ -36188,8 +36391,8 @@ ${import_picocolors17.default.bold(import_picocolors17.default.cyan(kitName))} -
|
|
|
36188
36391
|
Showing ${releases.length} ${releases.length === 1 ? "release" : "releases"}`));
|
|
36189
36392
|
}
|
|
36190
36393
|
async function versionCommand(options) {
|
|
36191
|
-
const
|
|
36192
|
-
|
|
36394
|
+
const prompts2 = new PromptsManager;
|
|
36395
|
+
prompts2.intro("\uD83D\uDCE6 ClaudeKit - Available Versions");
|
|
36193
36396
|
try {
|
|
36194
36397
|
const validOptions = VersionCommandOptionsSchema.parse(options);
|
|
36195
36398
|
const kitsToFetch = validOptions.kit ? [validOptions.kit] : Object.keys(AVAILABLE_KITS);
|
|
@@ -36225,7 +36428,7 @@ ${import_picocolors17.default.bold(import_picocolors17.default.cyan(result.kitCo
|
|
|
36225
36428
|
displayKitReleases(result.kitConfig.name, result.releases);
|
|
36226
36429
|
}
|
|
36227
36430
|
}
|
|
36228
|
-
|
|
36431
|
+
prompts2.outro("✨ Done");
|
|
36229
36432
|
} catch (error) {
|
|
36230
36433
|
logger.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
36231
36434
|
process.exit(1);
|
|
@@ -36235,13 +36438,13 @@ ${import_picocolors17.default.bold(import_picocolors17.default.cyan(result.kitCo
|
|
|
36235
36438
|
// src/cli/command-registry.ts
|
|
36236
36439
|
init_logger();
|
|
36237
36440
|
function registerCommands(cli) {
|
|
36238
|
-
cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
|
|
36441
|
+
cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
|
|
36239
36442
|
if (options.exclude && !Array.isArray(options.exclude)) {
|
|
36240
36443
|
options.exclude = [options.exclude];
|
|
36241
36444
|
}
|
|
36242
36445
|
await newCommand(options);
|
|
36243
36446
|
});
|
|
36244
|
-
cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
|
|
36447
|
+
cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
|
|
36245
36448
|
if (options.exclude && !Array.isArray(options.exclude)) {
|
|
36246
36449
|
options.exclude = [options.exclude];
|
|
36247
36450
|
}
|
|
@@ -36250,7 +36453,7 @@ function registerCommands(cli) {
|
|
|
36250
36453
|
}
|
|
36251
36454
|
await initCommand(options);
|
|
36252
36455
|
});
|
|
36253
|
-
cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "
|
|
36456
|
+
cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--beta", "Update to the latest beta version").option("--registry <url>", "Custom npm registry URL").option("--kit <kit>", "[DEPRECATED] Use 'ck init --kit <kit>' instead").option("-g, --global", "[DEPRECATED] Use 'ck init --global' instead").action(async (options) => {
|
|
36254
36457
|
if (options.kit || options.global) {
|
|
36255
36458
|
console.log();
|
|
36256
36459
|
const deprecatedFlags = [options.kit && "--kit", options.global && "--global"].filter(Boolean).join(" and ");
|
|
@@ -36280,7 +36483,7 @@ function registerCommands(cli) {
|
|
|
36280
36483
|
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) => {
|
|
36281
36484
|
await doctorCommand(options);
|
|
36282
36485
|
});
|
|
36283
|
-
cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "
|
|
36486
|
+
cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").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) => {
|
|
36284
36487
|
await uninstallCommand(options);
|
|
36285
36488
|
});
|
|
36286
36489
|
cli.command("easter-egg", "\uD83E\uDD5A Roll for a random discount code (Code Hunt 2025)").action(async () => {
|
|
@@ -36290,7 +36493,7 @@ function registerCommands(cli) {
|
|
|
36290
36493
|
|
|
36291
36494
|
// src/cli/version-display.ts
|
|
36292
36495
|
import { existsSync as existsSync17, readFileSync as readFileSync5 } from "node:fs";
|
|
36293
|
-
import { join as
|
|
36496
|
+
import { join as join66 } from "node:path";
|
|
36294
36497
|
|
|
36295
36498
|
// src/domains/versioning/checking/version-utils.ts
|
|
36296
36499
|
var import_compare_versions3 = __toESM(require_umd(), 1);
|
|
@@ -36317,13 +36520,13 @@ init_types2();
|
|
|
36317
36520
|
init_logger();
|
|
36318
36521
|
import { existsSync as existsSync16 } from "node:fs";
|
|
36319
36522
|
import { mkdir as mkdir18, readFile as readFile20, writeFile as writeFile17 } from "node:fs/promises";
|
|
36320
|
-
import { join as
|
|
36523
|
+
import { join as join65 } from "node:path";
|
|
36321
36524
|
class VersionCacheManager {
|
|
36322
36525
|
static CACHE_FILENAME = "version-check.json";
|
|
36323
36526
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
36324
36527
|
static getCacheFile() {
|
|
36325
36528
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
36326
|
-
return
|
|
36529
|
+
return join65(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
36327
36530
|
}
|
|
36328
36531
|
static async load() {
|
|
36329
36532
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -36566,9 +36769,9 @@ async function displayVersion() {
|
|
|
36566
36769
|
let localKitVersion = null;
|
|
36567
36770
|
let isGlobalOnlyKit = false;
|
|
36568
36771
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
36569
|
-
const globalMetadataPath =
|
|
36772
|
+
const globalMetadataPath = join66(globalKitDir, "metadata.json");
|
|
36570
36773
|
const prefix = PathResolver.getPathPrefix(false);
|
|
36571
|
-
const localMetadataPath = prefix ?
|
|
36774
|
+
const localMetadataPath = prefix ? join66(process.cwd(), prefix, "metadata.json") : join66(process.cwd(), "metadata.json");
|
|
36572
36775
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
36573
36776
|
if (!isLocalSameAsGlobal && existsSync17(localMetadataPath)) {
|
|
36574
36777
|
try {
|
|
@@ -36635,6 +36838,7 @@ import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
|
36635
36838
|
class Logger2 {
|
|
36636
36839
|
verboseEnabled = false;
|
|
36637
36840
|
logFileStream;
|
|
36841
|
+
exitHandlerRegistered = false;
|
|
36638
36842
|
info(message) {
|
|
36639
36843
|
const symbols = output.getSymbols();
|
|
36640
36844
|
console.log(import_picocolors19.default.blue(symbols.info), message);
|
|
@@ -36689,9 +36893,49 @@ class Logger2 {
|
|
|
36689
36893
|
flags: "a",
|
|
36690
36894
|
mode: 384
|
|
36691
36895
|
});
|
|
36896
|
+
this.registerExitHandler();
|
|
36692
36897
|
this.verbose(`Logging to file: ${path9}`);
|
|
36693
36898
|
}
|
|
36694
36899
|
}
|
|
36900
|
+
close() {
|
|
36901
|
+
if (this.logFileStream) {
|
|
36902
|
+
this.logFileStream.end();
|
|
36903
|
+
this.logFileStream = undefined;
|
|
36904
|
+
}
|
|
36905
|
+
}
|
|
36906
|
+
registerExitHandler() {
|
|
36907
|
+
if (this.exitHandlerRegistered)
|
|
36908
|
+
return;
|
|
36909
|
+
this.exitHandlerRegistered = true;
|
|
36910
|
+
const cleanup = () => {
|
|
36911
|
+
if (this.logFileStream) {
|
|
36912
|
+
try {
|
|
36913
|
+
this.logFileStream.end();
|
|
36914
|
+
} catch {}
|
|
36915
|
+
this.logFileStream = undefined;
|
|
36916
|
+
}
|
|
36917
|
+
};
|
|
36918
|
+
process.on("exit", cleanup);
|
|
36919
|
+
process.on("SIGINT", () => {
|
|
36920
|
+
cleanup();
|
|
36921
|
+
process.exit(130);
|
|
36922
|
+
});
|
|
36923
|
+
process.on("SIGTERM", () => {
|
|
36924
|
+
cleanup();
|
|
36925
|
+
process.exit(143);
|
|
36926
|
+
});
|
|
36927
|
+
process.on("uncaughtException", (error) => {
|
|
36928
|
+
if (this.logFileStream) {
|
|
36929
|
+
const timestamp = new Date().toISOString();
|
|
36930
|
+
this.logFileStream.write(`${timestamp} [FATAL] Uncaught exception: ${error.message}
|
|
36931
|
+
`);
|
|
36932
|
+
this.logFileStream.write(`${error.stack}
|
|
36933
|
+
`);
|
|
36934
|
+
}
|
|
36935
|
+
cleanup();
|
|
36936
|
+
process.exit(1);
|
|
36937
|
+
});
|
|
36938
|
+
}
|
|
36695
36939
|
sanitize(text) {
|
|
36696
36940
|
return text.replace(/ghp_[a-zA-Z0-9]{36}/g, "ghp_***").replace(/github_pat_[a-zA-Z0-9_]{82}/g, "github_pat_***").replace(/gho_[a-zA-Z0-9]{36}/g, "gho_***").replace(/ghu_[a-zA-Z0-9]{36}/g, "ghu_***").replace(/ghs_[a-zA-Z0-9]{36}/g, "ghs_***").replace(/ghr_[a-zA-Z0-9]{36}/g, "ghr_***").replace(/Bearer [a-zA-Z0-9_-]+/g, "Bearer ***").replace(/token=[a-zA-Z0-9_-]+/g, "token=***");
|
|
36697
36941
|
}
|
|
@@ -36736,7 +36980,11 @@ var SYMBOLS2 = {
|
|
|
36736
36980
|
line: "│",
|
|
36737
36981
|
selected: "●",
|
|
36738
36982
|
unselected: "○",
|
|
36739
|
-
pointer: ">"
|
|
36983
|
+
pointer: ">",
|
|
36984
|
+
pass: "✓",
|
|
36985
|
+
warn: "⚠",
|
|
36986
|
+
fail: "✗",
|
|
36987
|
+
infoStatus: "ℹ"
|
|
36740
36988
|
},
|
|
36741
36989
|
ascii: {
|
|
36742
36990
|
prompt: "?",
|
|
@@ -36747,10 +36995,13 @@ var SYMBOLS2 = {
|
|
|
36747
36995
|
line: "|",
|
|
36748
36996
|
selected: ">",
|
|
36749
36997
|
unselected: " ",
|
|
36750
|
-
pointer: ">"
|
|
36998
|
+
pointer: ">",
|
|
36999
|
+
pass: "[PASS]",
|
|
37000
|
+
warn: "[WARN]",
|
|
37001
|
+
fail: "[FAIL]",
|
|
37002
|
+
infoStatus: "[INFO]"
|
|
36751
37003
|
}
|
|
36752
37004
|
};
|
|
36753
|
-
|
|
36754
37005
|
class OutputManager2 {
|
|
36755
37006
|
config = {
|
|
36756
37007
|
verbose: false,
|
|
@@ -36760,6 +37011,7 @@ class OutputManager2 {
|
|
|
36760
37011
|
jsonBuffer = [];
|
|
36761
37012
|
unicodeSupported;
|
|
36762
37013
|
flushPromise = null;
|
|
37014
|
+
flushQueued = false;
|
|
36763
37015
|
constructor() {
|
|
36764
37016
|
this.unicodeSupported = supportsUnicode();
|
|
36765
37017
|
}
|
|
@@ -36865,8 +37117,12 @@ class OutputManager2 {
|
|
|
36865
37117
|
...entry,
|
|
36866
37118
|
timestamp: new Date().toISOString()
|
|
36867
37119
|
});
|
|
36868
|
-
if (this.jsonBuffer.length >= 1000 && !this.flushPromise) {
|
|
36869
|
-
|
|
37120
|
+
if (this.jsonBuffer.length >= 1000 && !this.flushPromise && !this.flushQueued) {
|
|
37121
|
+
this.flushQueued = true;
|
|
37122
|
+
queueMicrotask(() => {
|
|
37123
|
+
this.flushQueued = false;
|
|
37124
|
+
this.flushJson();
|
|
37125
|
+
});
|
|
36870
37126
|
}
|
|
36871
37127
|
}
|
|
36872
37128
|
addJsonResult(data) {
|
|
@@ -36896,6 +37152,7 @@ class OutputManager2 {
|
|
|
36896
37152
|
this.config = { verbose: false, json: false, quiet: false };
|
|
36897
37153
|
this.jsonBuffer = [];
|
|
36898
37154
|
this.flushPromise = null;
|
|
37155
|
+
this.flushQueued = false;
|
|
36899
37156
|
this.unicodeSupported = supportsUnicode();
|
|
36900
37157
|
}
|
|
36901
37158
|
}
|