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.
Files changed (2) hide show
  1. package/dist/index.js +194 -194
  2. 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.0",
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 join12, relative as relative3 } from "node:path";
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 import_fs_extra3 = __toESM(require_lib(), 1);
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
- if (!metadata || !metadata.files || metadata.files.length === 0) {
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 = metadata.files.find((f3) => f3.path === relativePath);
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 = join12(destDir, relativePath);
30232
- if (await import_fs_extra3.pathExists(destPath)) {
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 = join12(destDir, relativePath);
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 import_fs_extra3.pathExists(destPath);
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 import_fs_extra3.copy(file, destPath, { overwrite: true });
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 import_fs_extra3.readFile(sourceFile, "utf-8");
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 import_fs_extra3.pathExists(destFile);
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 import_fs_extra3.writeFile(destFile, formattedContent, "utf-8");
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 import_fs_extra3.copy(sourceFile, destFile, { overwrite: true });
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 import_fs_extra3.writeFile(destFile, formattedContent, "utf-8");
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 import_fs_extra3.readdir(dir, { encoding: "utf8" });
30530
+ const entries = await import_fs_extra4.readdir(dir, { encoding: "utf8" });
30380
30531
  for (const entry of entries) {
30381
- const fullPath = join12(dir, entry);
30532
+ const fullPath = join13(dir, entry);
30382
30533
  const relativePath = relative3(baseDir, fullPath);
30383
30534
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
30384
- const stats = await import_fs_extra3.lstat(fullPath);
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 join13 } from "node:path";
30443
- var import_fs_extra4 = __toESM(require_lib(), 1);
30593
+ import { join as join14 } from "node:path";
30594
+ var import_fs_extra5 = __toESM(require_lib(), 1);
30444
30595
  var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
30445
30596
  async function handleFreshInstallation(claudeDir, prompts) {
30446
- if (!await import_fs_extra4.pathExists(claudeDir)) {
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 = join13(claudeDir, subdir);
30462
- if (await import_fs_extra4.pathExists(subdirPath)) {
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 join15 } from "node:path";
30628
+ import { join as join16 } from "node:path";
30478
30629
 
30479
30630
  // src/domains/config/config-generator.ts
30480
- var import_fs_extra5 = __toESM(require_lib(), 1);
30481
- import { join as join14 } from "node:path";
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 = join14(targetDir, ".env");
30494
- await import_fs_extra5.writeFile(envPath, `${lines.join(`
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 import_fs_extra6 = __toESM(require_lib(), 1);
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 import_fs_extra6.readFile(path9, "utf-8");
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 = join15(PathResolver.getGlobalKitDir(), ".env");
30568
- if (!await import_fs_extra6.pathExists(globalEnvPath))
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 = join15(PathResolver.getGlobalKitDir(), ".env");
30584
- if (await import_fs_extra6.pathExists(globalEnvPath)) {
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 ${join15(targetDir, ".env")}`);
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
- installedFiles: this.getInstalledFiles(),
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
- if (!metadata || !metadata.files || metadata.files.length === 0) {
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
- if (!metadata?.files || metadata.files.length === 0) {
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 metadata.files || []) {
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.0",
35043
+ version: "3.11.1",
35044
35044
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
35045
35045
  type: "module",
35046
35046
  repository: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.11.0",
3
+ "version": "3.11.1",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {