claudekit-cli 3.11.0 → 3.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +194 -194
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15466,7 +15466,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
15466
15466
|
// package.json
|
|
15467
15467
|
var package_default = {
|
|
15468
15468
|
name: "claudekit-cli",
|
|
15469
|
-
version: "3.11.
|
|
15469
|
+
version: "3.11.1",
|
|
15470
15470
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
15471
15471
|
type: "module",
|
|
15472
15472
|
repository: {
|
|
@@ -28410,7 +28410,7 @@ Solutions:
|
|
|
28410
28410
|
}
|
|
28411
28411
|
|
|
28412
28412
|
// src/domains/installation/file-merger.ts
|
|
28413
|
-
import { dirname as dirname5, join as
|
|
28413
|
+
import { dirname as dirname5, join as join13, relative as relative3 } from "node:path";
|
|
28414
28414
|
|
|
28415
28415
|
// src/domains/config/settings-merger.ts
|
|
28416
28416
|
init_logger();
|
|
@@ -28619,7 +28619,7 @@ class SettingsMerger {
|
|
|
28619
28619
|
init_logger();
|
|
28620
28620
|
init_types2();
|
|
28621
28621
|
init_dist2();
|
|
28622
|
-
var
|
|
28622
|
+
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
28623
28623
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
28624
28624
|
|
|
28625
28625
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
@@ -30065,6 +30065,156 @@ import { createReadStream } from "node:fs";
|
|
|
30065
30065
|
import { stat } from "node:fs/promises";
|
|
30066
30066
|
import { relative as relative2 } from "node:path";
|
|
30067
30067
|
|
|
30068
|
+
// src/domains/migration/metadata-migration.ts
|
|
30069
|
+
init_logger();
|
|
30070
|
+
var import_fs_extra3 = __toESM(require_lib(), 1);
|
|
30071
|
+
import { join as join12 } from "node:path";
|
|
30072
|
+
async function detectMetadataFormat(claudeDir) {
|
|
30073
|
+
const metadataPath = join12(claudeDir, "metadata.json");
|
|
30074
|
+
if (!await import_fs_extra3.pathExists(metadataPath)) {
|
|
30075
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30076
|
+
}
|
|
30077
|
+
try {
|
|
30078
|
+
const content = await import_fs_extra3.readFile(metadataPath, "utf-8");
|
|
30079
|
+
const parsed = JSON.parse(content);
|
|
30080
|
+
if (parsed.kits && Object.keys(parsed.kits).length > 0) {
|
|
30081
|
+
const installedKits = Object.keys(parsed.kits);
|
|
30082
|
+
return {
|
|
30083
|
+
format: "multi-kit",
|
|
30084
|
+
metadata: parsed,
|
|
30085
|
+
detectedKit: installedKits[0] || null
|
|
30086
|
+
};
|
|
30087
|
+
}
|
|
30088
|
+
if (parsed.name || parsed.version || parsed.files) {
|
|
30089
|
+
let detectedKit = null;
|
|
30090
|
+
const nameToCheck = parsed.name || "";
|
|
30091
|
+
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30092
|
+
detectedKit = "engineer";
|
|
30093
|
+
} else if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30094
|
+
detectedKit = "marketing";
|
|
30095
|
+
} else {
|
|
30096
|
+
detectedKit = "engineer";
|
|
30097
|
+
}
|
|
30098
|
+
return { format: "legacy", metadata: parsed, detectedKit };
|
|
30099
|
+
}
|
|
30100
|
+
logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
|
|
30101
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30102
|
+
} catch (error) {
|
|
30103
|
+
logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
|
|
30104
|
+
return { format: "none", metadata: null, detectedKit: null };
|
|
30105
|
+
}
|
|
30106
|
+
}
|
|
30107
|
+
async function migrateToMultiKit(claudeDir) {
|
|
30108
|
+
const detection = await detectMetadataFormat(claudeDir);
|
|
30109
|
+
if (detection.format === "multi-kit") {
|
|
30110
|
+
return {
|
|
30111
|
+
success: true,
|
|
30112
|
+
migrated: false,
|
|
30113
|
+
fromFormat: "multi-kit",
|
|
30114
|
+
toFormat: "multi-kit"
|
|
30115
|
+
};
|
|
30116
|
+
}
|
|
30117
|
+
if (detection.format === "none") {
|
|
30118
|
+
return {
|
|
30119
|
+
success: true,
|
|
30120
|
+
migrated: false,
|
|
30121
|
+
fromFormat: "none",
|
|
30122
|
+
toFormat: "multi-kit"
|
|
30123
|
+
};
|
|
30124
|
+
}
|
|
30125
|
+
const metadataPath = join12(claudeDir, "metadata.json");
|
|
30126
|
+
const legacy = detection.metadata;
|
|
30127
|
+
if (!legacy) {
|
|
30128
|
+
return {
|
|
30129
|
+
success: false,
|
|
30130
|
+
migrated: false,
|
|
30131
|
+
fromFormat: "legacy",
|
|
30132
|
+
toFormat: "multi-kit",
|
|
30133
|
+
error: "Metadata exists but could not be read"
|
|
30134
|
+
};
|
|
30135
|
+
}
|
|
30136
|
+
const legacyKit = detection.detectedKit || "engineer";
|
|
30137
|
+
try {
|
|
30138
|
+
const kitMetadata = {
|
|
30139
|
+
version: legacy.version || "unknown",
|
|
30140
|
+
installedAt: legacy.installedAt || new Date().toISOString(),
|
|
30141
|
+
files: legacy.files || []
|
|
30142
|
+
};
|
|
30143
|
+
const multiKit = {
|
|
30144
|
+
kits: {
|
|
30145
|
+
[legacyKit]: kitMetadata
|
|
30146
|
+
},
|
|
30147
|
+
scope: legacy.scope,
|
|
30148
|
+
name: legacy.name,
|
|
30149
|
+
version: legacy.version,
|
|
30150
|
+
installedAt: legacy.installedAt,
|
|
30151
|
+
installedFiles: legacy.installedFiles,
|
|
30152
|
+
userConfigFiles: legacy.userConfigFiles,
|
|
30153
|
+
files: legacy.files
|
|
30154
|
+
};
|
|
30155
|
+
await import_fs_extra3.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
|
|
30156
|
+
logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
|
|
30157
|
+
return {
|
|
30158
|
+
success: true,
|
|
30159
|
+
migrated: true,
|
|
30160
|
+
fromFormat: "legacy",
|
|
30161
|
+
toFormat: "multi-kit"
|
|
30162
|
+
};
|
|
30163
|
+
} catch (error) {
|
|
30164
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
30165
|
+
logger.error(`Metadata migration failed: ${errorMsg}`);
|
|
30166
|
+
return {
|
|
30167
|
+
success: false,
|
|
30168
|
+
migrated: false,
|
|
30169
|
+
fromFormat: "legacy",
|
|
30170
|
+
toFormat: "multi-kit",
|
|
30171
|
+
error: errorMsg
|
|
30172
|
+
};
|
|
30173
|
+
}
|
|
30174
|
+
}
|
|
30175
|
+
function getKitMetadata(metadata, kit) {
|
|
30176
|
+
if (metadata.kits?.[kit]) {
|
|
30177
|
+
return metadata.kits[kit];
|
|
30178
|
+
}
|
|
30179
|
+
if (!metadata.kits && metadata.version) {
|
|
30180
|
+
return {
|
|
30181
|
+
version: metadata.version,
|
|
30182
|
+
installedAt: metadata.installedAt || "",
|
|
30183
|
+
files: metadata.files
|
|
30184
|
+
};
|
|
30185
|
+
}
|
|
30186
|
+
return null;
|
|
30187
|
+
}
|
|
30188
|
+
function getAllTrackedFiles(metadata) {
|
|
30189
|
+
if (metadata.kits) {
|
|
30190
|
+
const allFiles = [];
|
|
30191
|
+
for (const kit of Object.values(metadata.kits)) {
|
|
30192
|
+
if (kit.files) {
|
|
30193
|
+
allFiles.push(...kit.files);
|
|
30194
|
+
}
|
|
30195
|
+
}
|
|
30196
|
+
return allFiles;
|
|
30197
|
+
}
|
|
30198
|
+
return metadata.files || [];
|
|
30199
|
+
}
|
|
30200
|
+
function getInstalledKits(metadata) {
|
|
30201
|
+
if (metadata.kits) {
|
|
30202
|
+
return Object.keys(metadata.kits);
|
|
30203
|
+
}
|
|
30204
|
+
const nameToCheck = metadata.name || "";
|
|
30205
|
+
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30206
|
+
return ["engineer"];
|
|
30207
|
+
}
|
|
30208
|
+
if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30209
|
+
return ["marketing"];
|
|
30210
|
+
}
|
|
30211
|
+
if (metadata.version) {
|
|
30212
|
+
return ["engineer"];
|
|
30213
|
+
}
|
|
30214
|
+
return [];
|
|
30215
|
+
}
|
|
30216
|
+
|
|
30217
|
+
// src/services/file-operations/ownership-checker.ts
|
|
30068
30218
|
class OwnershipChecker {
|
|
30069
30219
|
static async calculateChecksum(filePath) {
|
|
30070
30220
|
return new Promise((resolve3, reject) => {
|
|
@@ -30086,11 +30236,12 @@ class OwnershipChecker {
|
|
|
30086
30236
|
} catch {
|
|
30087
30237
|
return { path: filePath, ownership: "user", exists: false };
|
|
30088
30238
|
}
|
|
30089
|
-
|
|
30239
|
+
const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
|
|
30240
|
+
if (!metadata || allTrackedFiles.length === 0) {
|
|
30090
30241
|
return { path: filePath, ownership: "user", exists: true };
|
|
30091
30242
|
}
|
|
30092
30243
|
const relativePath = relative2(claudeDir, filePath).replace(/\\/g, "/");
|
|
30093
|
-
const tracked =
|
|
30244
|
+
const tracked = allTrackedFiles.find((f3) => f3.path === relativePath);
|
|
30094
30245
|
if (!tracked) {
|
|
30095
30246
|
return { path: filePath, ownership: "user", exists: true };
|
|
30096
30247
|
}
|
|
@@ -30228,8 +30379,8 @@ class FileMerger {
|
|
|
30228
30379
|
for (const file of files) {
|
|
30229
30380
|
const relativePath = relative3(sourceDir, file);
|
|
30230
30381
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
30231
|
-
const destPath =
|
|
30232
|
-
if (await
|
|
30382
|
+
const destPath = join13(destDir, relativePath);
|
|
30383
|
+
if (await import_fs_extra4.pathExists(destPath)) {
|
|
30233
30384
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
30234
30385
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
30235
30386
|
continue;
|
|
@@ -30250,14 +30401,14 @@ class FileMerger {
|
|
|
30250
30401
|
for (const file of files) {
|
|
30251
30402
|
const relativePath = relative3(sourceDir, file);
|
|
30252
30403
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
30253
|
-
const destPath =
|
|
30404
|
+
const destPath = join13(destDir, relativePath);
|
|
30254
30405
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
30255
30406
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
30256
30407
|
skippedCount++;
|
|
30257
30408
|
continue;
|
|
30258
30409
|
}
|
|
30259
30410
|
if (this.userConfigChecker.ignores(normalizedRelativePath)) {
|
|
30260
|
-
const fileExists = await
|
|
30411
|
+
const fileExists = await import_fs_extra4.pathExists(destPath);
|
|
30261
30412
|
if (fileExists) {
|
|
30262
30413
|
logger.debug(`Preserving user config: ${normalizedRelativePath}`);
|
|
30263
30414
|
skippedCount++;
|
|
@@ -30280,7 +30431,7 @@ class FileMerger {
|
|
|
30280
30431
|
continue;
|
|
30281
30432
|
}
|
|
30282
30433
|
}
|
|
30283
|
-
await
|
|
30434
|
+
await import_fs_extra4.copy(file, destPath, { overwrite: true });
|
|
30284
30435
|
this.trackInstalledFile(normalizedRelativePath);
|
|
30285
30436
|
copiedCount++;
|
|
30286
30437
|
}
|
|
@@ -30292,7 +30443,7 @@ class FileMerger {
|
|
|
30292
30443
|
}
|
|
30293
30444
|
async processSettingsJson(sourceFile, destFile) {
|
|
30294
30445
|
try {
|
|
30295
|
-
const sourceContent = await
|
|
30446
|
+
const sourceContent = await import_fs_extra4.readFile(sourceFile, "utf-8");
|
|
30296
30447
|
const isWindows5 = process.platform === "win32";
|
|
30297
30448
|
let transformedSource = sourceContent;
|
|
30298
30449
|
if (this.isGlobal) {
|
|
@@ -30308,19 +30459,19 @@ class FileMerger {
|
|
|
30308
30459
|
logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
|
|
30309
30460
|
}
|
|
30310
30461
|
}
|
|
30311
|
-
const destExists = await
|
|
30462
|
+
const destExists = await import_fs_extra4.pathExists(destFile);
|
|
30312
30463
|
if (destExists && !this.forceOverwriteSettings) {
|
|
30313
30464
|
await this.selectiveMergeSettings(transformedSource, destFile);
|
|
30314
30465
|
} else {
|
|
30315
30466
|
const formattedContent = this.formatJsonContent(transformedSource);
|
|
30316
|
-
await
|
|
30467
|
+
await import_fs_extra4.writeFile(destFile, formattedContent, "utf-8");
|
|
30317
30468
|
if (this.forceOverwriteSettings && destExists) {
|
|
30318
30469
|
logger.debug("Force overwrite enabled, replaced settings.json completely");
|
|
30319
30470
|
}
|
|
30320
30471
|
}
|
|
30321
30472
|
} catch (error) {
|
|
30322
30473
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
30323
|
-
await
|
|
30474
|
+
await import_fs_extra4.copy(sourceFile, destFile, { overwrite: true });
|
|
30324
30475
|
}
|
|
30325
30476
|
}
|
|
30326
30477
|
async selectiveMergeSettings(transformedSourceContent, destFile) {
|
|
@@ -30330,7 +30481,7 @@ class FileMerger {
|
|
|
30330
30481
|
} catch {
|
|
30331
30482
|
logger.warning("Failed to parse source settings.json, falling back to overwrite");
|
|
30332
30483
|
const formattedContent = this.formatJsonContent(transformedSourceContent);
|
|
30333
|
-
await
|
|
30484
|
+
await import_fs_extra4.writeFile(destFile, formattedContent, "utf-8");
|
|
30334
30485
|
return;
|
|
30335
30486
|
}
|
|
30336
30487
|
const destSettings = await SettingsMerger.readSettingsFile(destFile);
|
|
@@ -30376,12 +30527,12 @@ class FileMerger {
|
|
|
30376
30527
|
}
|
|
30377
30528
|
async getFiles(dir, baseDir = dir) {
|
|
30378
30529
|
const files = [];
|
|
30379
|
-
const entries = await
|
|
30530
|
+
const entries = await import_fs_extra4.readdir(dir, { encoding: "utf8" });
|
|
30380
30531
|
for (const entry of entries) {
|
|
30381
|
-
const fullPath =
|
|
30532
|
+
const fullPath = join13(dir, entry);
|
|
30382
30533
|
const relativePath = relative3(baseDir, fullPath);
|
|
30383
30534
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
30384
|
-
const stats = await
|
|
30535
|
+
const stats = await import_fs_extra4.lstat(fullPath);
|
|
30385
30536
|
if (stats.isSymbolicLink()) {
|
|
30386
30537
|
logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
|
|
30387
30538
|
continue;
|
|
@@ -30439,11 +30590,11 @@ class FileMerger {
|
|
|
30439
30590
|
|
|
30440
30591
|
// src/domains/installation/fresh-installer.ts
|
|
30441
30592
|
init_logger();
|
|
30442
|
-
import { join as
|
|
30443
|
-
var
|
|
30593
|
+
import { join as join14 } from "node:path";
|
|
30594
|
+
var import_fs_extra5 = __toESM(require_lib(), 1);
|
|
30444
30595
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
30445
30596
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
30446
|
-
if (!await
|
|
30597
|
+
if (!await import_fs_extra5.pathExists(claudeDir)) {
|
|
30447
30598
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
30448
30599
|
return true;
|
|
30449
30600
|
}
|
|
@@ -30458,8 +30609,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
30458
30609
|
const { rmSync } = await import("node:fs");
|
|
30459
30610
|
let removedCount = 0;
|
|
30460
30611
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
30461
|
-
const subdirPath =
|
|
30462
|
-
if (await
|
|
30612
|
+
const subdirPath = join14(claudeDir, subdir);
|
|
30613
|
+
if (await import_fs_extra5.pathExists(subdirPath)) {
|
|
30463
30614
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
30464
30615
|
removedCount++;
|
|
30465
30616
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
@@ -30474,11 +30625,11 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
30474
30625
|
}
|
|
30475
30626
|
|
|
30476
30627
|
// src/domains/installation/setup-wizard.ts
|
|
30477
|
-
import { join as
|
|
30628
|
+
import { join as join16 } from "node:path";
|
|
30478
30629
|
|
|
30479
30630
|
// src/domains/config/config-generator.ts
|
|
30480
|
-
var
|
|
30481
|
-
import { join as
|
|
30631
|
+
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
30632
|
+
import { join as join15 } from "node:path";
|
|
30482
30633
|
async function generateEnvFile(targetDir, values) {
|
|
30483
30634
|
const lines = [
|
|
30484
30635
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -30490,8 +30641,8 @@ async function generateEnvFile(targetDir, values) {
|
|
|
30490
30641
|
lines.push(`${key}=${value}`);
|
|
30491
30642
|
}
|
|
30492
30643
|
}
|
|
30493
|
-
const envPath =
|
|
30494
|
-
await
|
|
30644
|
+
const envPath = join15(targetDir, ".env");
|
|
30645
|
+
await import_fs_extra6.writeFile(envPath, `${lines.join(`
|
|
30495
30646
|
`)}
|
|
30496
30647
|
`, { mode: 384 });
|
|
30497
30648
|
}
|
|
@@ -30509,7 +30660,7 @@ function validateApiKey(value, pattern) {
|
|
|
30509
30660
|
// src/domains/installation/setup-wizard.ts
|
|
30510
30661
|
init_logger();
|
|
30511
30662
|
init_dist2();
|
|
30512
|
-
var
|
|
30663
|
+
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
30513
30664
|
var ESSENTIAL_CONFIGS = [
|
|
30514
30665
|
{
|
|
30515
30666
|
key: "GEMINI_API_KEY",
|
|
@@ -30538,7 +30689,7 @@ var ESSENTIAL_CONFIGS = [
|
|
|
30538
30689
|
];
|
|
30539
30690
|
async function parseEnvFile(path9) {
|
|
30540
30691
|
try {
|
|
30541
|
-
const content = await
|
|
30692
|
+
const content = await import_fs_extra7.readFile(path9, "utf-8");
|
|
30542
30693
|
const env2 = {};
|
|
30543
30694
|
for (const line of content.split(`
|
|
30544
30695
|
`)) {
|
|
@@ -30564,8 +30715,8 @@ async function parseEnvFile(path9) {
|
|
|
30564
30715
|
}
|
|
30565
30716
|
}
|
|
30566
30717
|
async function checkGlobalConfig() {
|
|
30567
|
-
const globalEnvPath =
|
|
30568
|
-
if (!await
|
|
30718
|
+
const globalEnvPath = join16(PathResolver.getGlobalKitDir(), ".env");
|
|
30719
|
+
if (!await import_fs_extra7.pathExists(globalEnvPath))
|
|
30569
30720
|
return false;
|
|
30570
30721
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
30571
30722
|
return Object.keys(env2).length > 0;
|
|
@@ -30580,8 +30731,8 @@ async function runSetupWizard(options) {
|
|
|
30580
30731
|
let globalEnv = {};
|
|
30581
30732
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
30582
30733
|
if (!isGlobal) {
|
|
30583
|
-
const globalEnvPath =
|
|
30584
|
-
if (await
|
|
30734
|
+
const globalEnvPath = join16(PathResolver.getGlobalKitDir(), ".env");
|
|
30735
|
+
if (await import_fs_extra7.pathExists(globalEnvPath)) {
|
|
30585
30736
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
30586
30737
|
}
|
|
30587
30738
|
}
|
|
@@ -30633,7 +30784,7 @@ async function runSetupWizard(options) {
|
|
|
30633
30784
|
}
|
|
30634
30785
|
}
|
|
30635
30786
|
await generateEnvFile(targetDir, values);
|
|
30636
|
-
f2.success(`Configuration saved to ${
|
|
30787
|
+
f2.success(`Configuration saved to ${join16(targetDir, ".env")}`);
|
|
30637
30788
|
return true;
|
|
30638
30789
|
}
|
|
30639
30790
|
|
|
@@ -30643,157 +30794,6 @@ import { join as join19, relative as relative4 } from "node:path";
|
|
|
30643
30794
|
|
|
30644
30795
|
// src/services/file-operations/manifest-writer.ts
|
|
30645
30796
|
import { join as join17 } from "node:path";
|
|
30646
|
-
|
|
30647
|
-
// src/domains/migration/metadata-migration.ts
|
|
30648
|
-
init_logger();
|
|
30649
|
-
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
30650
|
-
import { join as join16 } from "node:path";
|
|
30651
|
-
async function detectMetadataFormat(claudeDir) {
|
|
30652
|
-
const metadataPath = join16(claudeDir, "metadata.json");
|
|
30653
|
-
if (!await import_fs_extra7.pathExists(metadataPath)) {
|
|
30654
|
-
return { format: "none", metadata: null, detectedKit: null };
|
|
30655
|
-
}
|
|
30656
|
-
try {
|
|
30657
|
-
const content = await import_fs_extra7.readFile(metadataPath, "utf-8");
|
|
30658
|
-
const parsed = JSON.parse(content);
|
|
30659
|
-
if (parsed.kits && Object.keys(parsed.kits).length > 0) {
|
|
30660
|
-
const installedKits = Object.keys(parsed.kits);
|
|
30661
|
-
return {
|
|
30662
|
-
format: "multi-kit",
|
|
30663
|
-
metadata: parsed,
|
|
30664
|
-
detectedKit: installedKits[0] || null
|
|
30665
|
-
};
|
|
30666
|
-
}
|
|
30667
|
-
if (parsed.name || parsed.version || parsed.files) {
|
|
30668
|
-
let detectedKit = null;
|
|
30669
|
-
const nameToCheck = parsed.name || "";
|
|
30670
|
-
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30671
|
-
detectedKit = "engineer";
|
|
30672
|
-
} else if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30673
|
-
detectedKit = "marketing";
|
|
30674
|
-
} else {
|
|
30675
|
-
detectedKit = "engineer";
|
|
30676
|
-
}
|
|
30677
|
-
return { format: "legacy", metadata: parsed, detectedKit };
|
|
30678
|
-
}
|
|
30679
|
-
logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
|
|
30680
|
-
return { format: "none", metadata: null, detectedKit: null };
|
|
30681
|
-
} catch (error) {
|
|
30682
|
-
logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
|
|
30683
|
-
return { format: "none", metadata: null, detectedKit: null };
|
|
30684
|
-
}
|
|
30685
|
-
}
|
|
30686
|
-
async function migrateToMultiKit(claudeDir) {
|
|
30687
|
-
const detection = await detectMetadataFormat(claudeDir);
|
|
30688
|
-
if (detection.format === "multi-kit") {
|
|
30689
|
-
return {
|
|
30690
|
-
success: true,
|
|
30691
|
-
migrated: false,
|
|
30692
|
-
fromFormat: "multi-kit",
|
|
30693
|
-
toFormat: "multi-kit"
|
|
30694
|
-
};
|
|
30695
|
-
}
|
|
30696
|
-
if (detection.format === "none") {
|
|
30697
|
-
return {
|
|
30698
|
-
success: true,
|
|
30699
|
-
migrated: false,
|
|
30700
|
-
fromFormat: "none",
|
|
30701
|
-
toFormat: "multi-kit"
|
|
30702
|
-
};
|
|
30703
|
-
}
|
|
30704
|
-
const metadataPath = join16(claudeDir, "metadata.json");
|
|
30705
|
-
const legacy = detection.metadata;
|
|
30706
|
-
if (!legacy) {
|
|
30707
|
-
return {
|
|
30708
|
-
success: false,
|
|
30709
|
-
migrated: false,
|
|
30710
|
-
fromFormat: "legacy",
|
|
30711
|
-
toFormat: "multi-kit",
|
|
30712
|
-
error: "Metadata exists but could not be read"
|
|
30713
|
-
};
|
|
30714
|
-
}
|
|
30715
|
-
const legacyKit = detection.detectedKit || "engineer";
|
|
30716
|
-
try {
|
|
30717
|
-
const kitMetadata = {
|
|
30718
|
-
version: legacy.version || "unknown",
|
|
30719
|
-
installedAt: legacy.installedAt || new Date().toISOString(),
|
|
30720
|
-
files: legacy.files || []
|
|
30721
|
-
};
|
|
30722
|
-
const multiKit = {
|
|
30723
|
-
kits: {
|
|
30724
|
-
[legacyKit]: kitMetadata
|
|
30725
|
-
},
|
|
30726
|
-
scope: legacy.scope,
|
|
30727
|
-
name: legacy.name,
|
|
30728
|
-
version: legacy.version,
|
|
30729
|
-
installedAt: legacy.installedAt,
|
|
30730
|
-
installedFiles: legacy.installedFiles,
|
|
30731
|
-
userConfigFiles: legacy.userConfigFiles,
|
|
30732
|
-
files: legacy.files
|
|
30733
|
-
};
|
|
30734
|
-
await import_fs_extra7.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
|
|
30735
|
-
logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
|
|
30736
|
-
return {
|
|
30737
|
-
success: true,
|
|
30738
|
-
migrated: true,
|
|
30739
|
-
fromFormat: "legacy",
|
|
30740
|
-
toFormat: "multi-kit"
|
|
30741
|
-
};
|
|
30742
|
-
} catch (error) {
|
|
30743
|
-
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
30744
|
-
logger.error(`Metadata migration failed: ${errorMsg}`);
|
|
30745
|
-
return {
|
|
30746
|
-
success: false,
|
|
30747
|
-
migrated: false,
|
|
30748
|
-
fromFormat: "legacy",
|
|
30749
|
-
toFormat: "multi-kit",
|
|
30750
|
-
error: errorMsg
|
|
30751
|
-
};
|
|
30752
|
-
}
|
|
30753
|
-
}
|
|
30754
|
-
function getKitMetadata(metadata, kit) {
|
|
30755
|
-
if (metadata.kits?.[kit]) {
|
|
30756
|
-
return metadata.kits[kit];
|
|
30757
|
-
}
|
|
30758
|
-
if (!metadata.kits && metadata.version) {
|
|
30759
|
-
return {
|
|
30760
|
-
version: metadata.version,
|
|
30761
|
-
installedAt: metadata.installedAt || "",
|
|
30762
|
-
files: metadata.files
|
|
30763
|
-
};
|
|
30764
|
-
}
|
|
30765
|
-
return null;
|
|
30766
|
-
}
|
|
30767
|
-
function getAllTrackedFiles(metadata) {
|
|
30768
|
-
if (metadata.kits) {
|
|
30769
|
-
const allFiles = [];
|
|
30770
|
-
for (const kit of Object.values(metadata.kits)) {
|
|
30771
|
-
if (kit.files) {
|
|
30772
|
-
allFiles.push(...kit.files);
|
|
30773
|
-
}
|
|
30774
|
-
}
|
|
30775
|
-
return allFiles;
|
|
30776
|
-
}
|
|
30777
|
-
return metadata.files || [];
|
|
30778
|
-
}
|
|
30779
|
-
function getInstalledKits(metadata) {
|
|
30780
|
-
if (metadata.kits) {
|
|
30781
|
-
return Object.keys(metadata.kits);
|
|
30782
|
-
}
|
|
30783
|
-
const nameToCheck = metadata.name || "";
|
|
30784
|
-
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
30785
|
-
return ["engineer"];
|
|
30786
|
-
}
|
|
30787
|
-
if (/\bmarketing\b/i.test(nameToCheck)) {
|
|
30788
|
-
return ["marketing"];
|
|
30789
|
-
}
|
|
30790
|
-
if (metadata.version) {
|
|
30791
|
-
return ["engineer"];
|
|
30792
|
-
}
|
|
30793
|
-
return [];
|
|
30794
|
-
}
|
|
30795
|
-
|
|
30796
|
-
// src/services/file-operations/manifest-writer.ts
|
|
30797
30797
|
init_logger();
|
|
30798
30798
|
init_types2();
|
|
30799
30799
|
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
@@ -31054,16 +31054,14 @@ class ManifestWriter {
|
|
|
31054
31054
|
};
|
|
31055
31055
|
const metadata = {
|
|
31056
31056
|
kits: {
|
|
31057
|
-
...existingMetadata.kits,
|
|
31057
|
+
...existingMetadata.kits || {},
|
|
31058
31058
|
[kit]: kitMetadata
|
|
31059
31059
|
},
|
|
31060
31060
|
scope,
|
|
31061
31061
|
name: kitName,
|
|
31062
31062
|
version,
|
|
31063
31063
|
installedAt,
|
|
31064
|
-
|
|
31065
|
-
userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()],
|
|
31066
|
-
files: trackedFiles.length > 0 ? trackedFiles : undefined
|
|
31064
|
+
userConfigFiles: [...USER_CONFIG_PATTERNS, ...this.getUserConfigFiles()]
|
|
31067
31065
|
};
|
|
31068
31066
|
const validated = MetadataSchema.parse(metadata);
|
|
31069
31067
|
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
@@ -33353,7 +33351,8 @@ class CommandsPrefix {
|
|
|
33353
33351
|
logger.info("Checking ownership before cleanup...");
|
|
33354
33352
|
}
|
|
33355
33353
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
33356
|
-
|
|
33354
|
+
const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
|
|
33355
|
+
if (!metadata || allTrackedFiles.length === 0) {
|
|
33357
33356
|
logger.verbose("No ownership metadata found - skipping cleanup (legacy/fresh install)");
|
|
33358
33357
|
logger.verbose("All existing files will be preserved as user-owned");
|
|
33359
33358
|
return result;
|
|
@@ -34704,7 +34703,8 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
34704
34703
|
}
|
|
34705
34704
|
return result;
|
|
34706
34705
|
}
|
|
34707
|
-
|
|
34706
|
+
const allTrackedFiles = metadata ? getAllTrackedFiles(metadata) : [];
|
|
34707
|
+
if (!metadata || allTrackedFiles.length === 0) {
|
|
34708
34708
|
for (const item of uninstallManifest.filesToRemove) {
|
|
34709
34709
|
if (!uninstallManifest.filesToPreserve.includes(item)) {
|
|
34710
34710
|
result.toDelete.push({ path: item, reason: "legacy installation" });
|
|
@@ -34712,7 +34712,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
34712
34712
|
}
|
|
34713
34713
|
return result;
|
|
34714
34714
|
}
|
|
34715
|
-
for (const trackedFile of
|
|
34715
|
+
for (const trackedFile of allTrackedFiles) {
|
|
34716
34716
|
const filePath = join34(installation.path, trackedFile.path);
|
|
34717
34717
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
34718
34718
|
if (!ownershipResult.exists)
|
|
@@ -35040,7 +35040,7 @@ var import_compare_versions2 = __toESM(require_umd(), 1);
|
|
|
35040
35040
|
// package.json
|
|
35041
35041
|
var package_default2 = {
|
|
35042
35042
|
name: "claudekit-cli",
|
|
35043
|
-
version: "3.11.
|
|
35043
|
+
version: "3.11.1",
|
|
35044
35044
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
35045
35045
|
type: "module",
|
|
35046
35046
|
repository: {
|