claudekit-cli 3.36.0-dev.1 → 3.36.0-dev.2

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 +226 -98
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -54366,7 +54366,7 @@ var package_default;
54366
54366
  var init_package = __esm(() => {
54367
54367
  package_default = {
54368
54368
  name: "claudekit-cli",
54369
- version: "3.36.0-dev.1",
54369
+ version: "3.36.0-dev.2",
54370
54370
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
54371
54371
  type: "module",
54372
54372
  repository: {
@@ -65598,6 +65598,121 @@ var init_skill_migration_merger = __esm(() => {
65598
65598
  import_fs_extra31 = __toESM(require_lib3(), 1);
65599
65599
  });
65600
65600
 
65601
+ // src/services/standalone-skill-cleanup.ts
65602
+ var exports_standalone_skill_cleanup = {};
65603
+ __export(exports_standalone_skill_cleanup, {
65604
+ cleanupOverlappingStandaloneSkills: () => cleanupOverlappingStandaloneSkills
65605
+ });
65606
+ import { readFile as readFile48, readdir as readdir32 } from "node:fs/promises";
65607
+ import { join as join101 } from "node:path";
65608
+ async function listSkillDirs(dir) {
65609
+ if (!await import_fs_extra32.pathExists(dir))
65610
+ return new Set;
65611
+ try {
65612
+ const entries = await readdir32(dir, { withFileTypes: true });
65613
+ const dirs = entries.filter((e2) => e2.isDirectory());
65614
+ const results = await Promise.all(dirs.map(async (e2) => {
65615
+ const exists = await import_fs_extra32.pathExists(join101(dir, e2.name, "SKILL.md"));
65616
+ return exists ? e2.name : null;
65617
+ }));
65618
+ return new Set(results.filter(Boolean));
65619
+ } catch {
65620
+ return new Set;
65621
+ }
65622
+ }
65623
+ async function getSkillOwnershipMap(claudeDir2) {
65624
+ const ownershipMap = new Map;
65625
+ const metadataPath = join101(claudeDir2, "metadata.json");
65626
+ if (!await import_fs_extra32.pathExists(metadataPath))
65627
+ return ownershipMap;
65628
+ let trackedFiles;
65629
+ try {
65630
+ const content = await readFile48(metadataPath, "utf-8");
65631
+ const metadata = JSON.parse(content);
65632
+ trackedFiles = extractTrackedSkillFiles2(metadata);
65633
+ } catch {
65634
+ logger.debug("standalone-skill-cleanup: could not read metadata");
65635
+ return ownershipMap;
65636
+ }
65637
+ for (const file of trackedFiles) {
65638
+ const skillDirName = extractSkillDirName(file.path);
65639
+ if (!skillDirName)
65640
+ continue;
65641
+ const existing = ownershipMap.get(skillDirName);
65642
+ if (file.ownership === "user" || file.ownership === "ck-modified") {
65643
+ ownershipMap.set(skillDirName, "user");
65644
+ } else if (!existing) {
65645
+ ownershipMap.set(skillDirName, "ck");
65646
+ }
65647
+ }
65648
+ return ownershipMap;
65649
+ }
65650
+ function extractTrackedSkillFiles2(metadata) {
65651
+ const files = [];
65652
+ if (metadata.kits && typeof metadata.kits === "object") {
65653
+ for (const kit of Object.values(metadata.kits)) {
65654
+ if (kit.files) {
65655
+ files.push(...kit.files.filter((f3) => f3.path?.startsWith("skills/")));
65656
+ }
65657
+ }
65658
+ }
65659
+ if (Array.isArray(metadata.files)) {
65660
+ files.push(...metadata.files.filter((f3) => f3.path?.startsWith("skills/")));
65661
+ }
65662
+ return files;
65663
+ }
65664
+ function extractSkillDirName(filePath) {
65665
+ const normalized = filePath.replace(/\\/g, "/");
65666
+ const parts = normalized.split("/").filter(Boolean);
65667
+ if (parts.length < 2 || parts[0] !== "skills")
65668
+ return null;
65669
+ return parts[1];
65670
+ }
65671
+ async function cleanupOverlappingStandaloneSkills(claudeDir2, pluginSkillsDir) {
65672
+ const standaloneSkillsDir = join101(claudeDir2, "skills");
65673
+ const result = {
65674
+ removed: [],
65675
+ preserved: [],
65676
+ pluginSkillsDir
65677
+ };
65678
+ const [pluginSkills, standaloneSkills] = await Promise.all([
65679
+ listSkillDirs(pluginSkillsDir),
65680
+ listSkillDirs(standaloneSkillsDir)
65681
+ ]);
65682
+ if (pluginSkills.size === 0 || standaloneSkills.size === 0) {
65683
+ logger.debug(`standalone-skill-cleanup: nothing to clean (plugin=${pluginSkills.size}, standalone=${standaloneSkills.size})`);
65684
+ return result;
65685
+ }
65686
+ const overlaps = [...standaloneSkills].filter((name2) => pluginSkills.has(name2));
65687
+ if (overlaps.length === 0)
65688
+ return result;
65689
+ const ownershipMap = await getSkillOwnershipMap(claudeDir2);
65690
+ for (const skillName of overlaps) {
65691
+ const ownership = ownershipMap.get(skillName);
65692
+ const skillPath = join101(standaloneSkillsDir, skillName);
65693
+ if (ownership === "user" || ownership === undefined) {
65694
+ result.preserved.push(skillName);
65695
+ const reason = ownership === "user" ? "user-owned/modified" : "untracked";
65696
+ logger.debug(`standalone-skill-cleanup: preserved ${skillName} (${reason})`);
65697
+ continue;
65698
+ }
65699
+ try {
65700
+ await import_fs_extra32.remove(skillPath);
65701
+ result.removed.push(skillName);
65702
+ logger.debug(`standalone-skill-cleanup: removed standalone ${skillName} (plugin has it)`);
65703
+ } catch (error) {
65704
+ result.preserved.push(skillName);
65705
+ logger.debug(`standalone-skill-cleanup: could not remove ${skillName}: ${error}`);
65706
+ }
65707
+ }
65708
+ return result;
65709
+ }
65710
+ var import_fs_extra32;
65711
+ var init_standalone_skill_cleanup = __esm(() => {
65712
+ init_logger();
65713
+ import_fs_extra32 = __toESM(require_lib3(), 1);
65714
+ });
65715
+
65601
65716
  // src/domains/help/commands/common-options.ts
65602
65717
  var filterOptionsGroup, folderOptionsGroup;
65603
65718
  var init_common_options = __esm(() => {
@@ -89428,21 +89543,21 @@ Please use only one download method.`);
89428
89543
  }
89429
89544
  // src/commands/init/phases/post-install-handler.ts
89430
89545
  init_projects_registry();
89431
- import { join as join101 } from "node:path";
89546
+ import { join as join102 } from "node:path";
89432
89547
  init_cc_version_checker();
89433
89548
  init_logger();
89434
89549
  init_path_resolver();
89435
- var import_fs_extra32 = __toESM(require_lib3(), 1);
89550
+ var import_fs_extra33 = __toESM(require_lib3(), 1);
89436
89551
  async function handlePostInstall(ctx) {
89437
89552
  if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir) {
89438
89553
  return ctx;
89439
89554
  }
89440
89555
  if (ctx.options.global) {
89441
- const claudeMdSource = join101(ctx.extractDir, "CLAUDE.md");
89442
- const claudeMdDest = join101(ctx.resolvedDir, "CLAUDE.md");
89443
- if (await import_fs_extra32.pathExists(claudeMdSource)) {
89444
- if (ctx.options.fresh || !await import_fs_extra32.pathExists(claudeMdDest)) {
89445
- await import_fs_extra32.copy(claudeMdSource, claudeMdDest);
89556
+ const claudeMdSource = join102(ctx.extractDir, "CLAUDE.md");
89557
+ const claudeMdDest = join102(ctx.resolvedDir, "CLAUDE.md");
89558
+ if (await import_fs_extra33.pathExists(claudeMdSource)) {
89559
+ if (ctx.options.fresh || !await import_fs_extra33.pathExists(claudeMdDest)) {
89560
+ await import_fs_extra33.copy(claudeMdSource, claudeMdDest);
89446
89561
  logger.success(ctx.options.fresh ? "Replaced CLAUDE.md in global directory (fresh install)" : "Copied CLAUDE.md to global directory");
89447
89562
  } else {
89448
89563
  logger.debug("CLAUDE.md already exists in global directory (preserved)");
@@ -89532,6 +89647,19 @@ async function handlePostInstall(ctx) {
89532
89647
  logger.debug(`Deferred skill deletion failed: ${error}`);
89533
89648
  }
89534
89649
  }
89650
+ if (pluginVerified) {
89651
+ try {
89652
+ const { cleanupOverlappingStandaloneSkills: cleanupOverlappingStandaloneSkills2 } = await Promise.resolve().then(() => (init_standalone_skill_cleanup(), exports_standalone_skill_cleanup));
89653
+ const globalClaudeDir = PathResolver.getGlobalKitDir();
89654
+ const pluginSkillsDir = join102(PathResolver.getClaudeKitDir(), "marketplace", "plugins", "ck", "skills");
89655
+ const overlap = await cleanupOverlappingStandaloneSkills2(globalClaudeDir, pluginSkillsDir);
89656
+ if (overlap.removed.length > 0) {
89657
+ logger.info(`Cleaned up ${overlap.removed.length} standalone skill(s) now provided by /ck:* plugin`);
89658
+ }
89659
+ } catch (error) {
89660
+ logger.info(`Standalone skill cleanup failed: ${error}`);
89661
+ }
89662
+ }
89535
89663
  if (!ctx.isNonInteractive) {
89536
89664
  const { isGeminiInstalled: isGeminiInstalled2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
89537
89665
  const { checkExistingGeminiConfig: checkExistingGeminiConfig2, findMcpConfigPath: findMcpConfigPath2, processGeminiMcpLinking: processGeminiMcpLinking2 } = await Promise.resolve().then(() => (init_gemini_mcp_linker(), exports_gemini_mcp_linker));
@@ -89558,7 +89686,7 @@ async function handlePostInstall(ctx) {
89558
89686
  }
89559
89687
  if (!ctx.options.skipSetup) {
89560
89688
  await promptSetupWizardIfNeeded({
89561
- envPath: join101(ctx.claudeDir, ".env"),
89689
+ envPath: join102(ctx.claudeDir, ".env"),
89562
89690
  claudeDir: ctx.claudeDir,
89563
89691
  isGlobal: ctx.options.global,
89564
89692
  isNonInteractive: ctx.isNonInteractive,
@@ -89594,7 +89722,7 @@ function extractSkillDirFromDeletionPath(path14) {
89594
89722
  init_config_manager();
89595
89723
  init_github_client();
89596
89724
  import { mkdir as mkdir30 } from "node:fs/promises";
89597
- import { join as join103, resolve as resolve21 } from "node:path";
89725
+ import { join as join104, resolve as resolve21 } from "node:path";
89598
89726
 
89599
89727
  // src/domains/github/kit-access-checker.ts
89600
89728
  init_logger();
@@ -89727,9 +89855,9 @@ init_metadata_migration();
89727
89855
  init_manifest_reader();
89728
89856
  init_logger();
89729
89857
  init_safe_spinner();
89730
- var import_fs_extra33 = __toESM(require_lib3(), 1);
89858
+ var import_fs_extra34 = __toESM(require_lib3(), 1);
89731
89859
  import { existsSync as existsSync50, readdirSync as readdirSync4, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
89732
- import { dirname as dirname22, join as join102, resolve as resolve20 } from "node:path";
89860
+ import { dirname as dirname22, join as join103, resolve as resolve20 } from "node:path";
89733
89861
  var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
89734
89862
  async function analyzeFreshInstallation(claudeDir2) {
89735
89863
  const metadata = await readManifest(claudeDir2);
@@ -89799,7 +89927,7 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
89799
89927
  const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
89800
89928
  const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
89801
89929
  for (const file of filesToRemove) {
89802
- const fullPath = join102(claudeDir2, file.path);
89930
+ const fullPath = join103(claudeDir2, file.path);
89803
89931
  try {
89804
89932
  if (existsSync50(fullPath)) {
89805
89933
  unlinkSync4(fullPath);
@@ -89824,13 +89952,13 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
89824
89952
  };
89825
89953
  }
89826
89954
  async function updateMetadataAfterFresh(claudeDir2, removedFiles) {
89827
- const metadataPath = join102(claudeDir2, "metadata.json");
89828
- if (!await import_fs_extra33.pathExists(metadataPath)) {
89955
+ const metadataPath = join103(claudeDir2, "metadata.json");
89956
+ if (!await import_fs_extra34.pathExists(metadataPath)) {
89829
89957
  return;
89830
89958
  }
89831
89959
  let content;
89832
89960
  try {
89833
- content = await import_fs_extra33.readFile(metadataPath, "utf-8");
89961
+ content = await import_fs_extra34.readFile(metadataPath, "utf-8");
89834
89962
  } catch (readError) {
89835
89963
  logger.warning(`Failed to read metadata.json: ${readError instanceof Error ? readError.message : String(readError)}`);
89836
89964
  return;
@@ -89856,7 +89984,7 @@ async function updateMetadataAfterFresh(claudeDir2, removedFiles) {
89856
89984
  metadata.files = metadata.files.filter((f3) => !removedSet.has(f3.path));
89857
89985
  }
89858
89986
  try {
89859
- await import_fs_extra33.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
89987
+ await import_fs_extra34.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
89860
89988
  logger.debug(`Updated metadata.json, removed ${removedFiles.length} file entries`);
89861
89989
  } catch (writeError) {
89862
89990
  logger.warning(`Failed to write metadata.json: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -89867,16 +89995,16 @@ async function removeSubdirectoriesFallback(claudeDir2) {
89867
89995
  const removedFiles = [];
89868
89996
  let removedDirCount = 0;
89869
89997
  for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
89870
- const subdirPath = join102(claudeDir2, subdir);
89871
- if (await import_fs_extra33.pathExists(subdirPath)) {
89998
+ const subdirPath = join103(claudeDir2, subdir);
89999
+ if (await import_fs_extra34.pathExists(subdirPath)) {
89872
90000
  rmSync3(subdirPath, { recursive: true, force: true });
89873
90001
  removedDirCount++;
89874
90002
  removedFiles.push(`${subdir}/ (entire directory)`);
89875
90003
  logger.debug(`Removed subdirectory: ${subdir}/`);
89876
90004
  }
89877
90005
  }
89878
- const metadataPath = join102(claudeDir2, "metadata.json");
89879
- if (await import_fs_extra33.pathExists(metadataPath)) {
90006
+ const metadataPath = join103(claudeDir2, "metadata.json");
90007
+ if (await import_fs_extra34.pathExists(metadataPath)) {
89880
90008
  unlinkSync4(metadataPath);
89881
90009
  removedFiles.push("metadata.json");
89882
90010
  }
@@ -89889,7 +90017,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
89889
90017
  };
89890
90018
  }
89891
90019
  async function handleFreshInstallation(claudeDir2, prompts) {
89892
- if (!await import_fs_extra33.pathExists(claudeDir2)) {
90020
+ if (!await import_fs_extra34.pathExists(claudeDir2)) {
89893
90021
  logger.info(".claude directory does not exist, proceeding with fresh installation");
89894
90022
  return true;
89895
90023
  }
@@ -89925,7 +90053,7 @@ init_manifest_reader();
89925
90053
  init_logger();
89926
90054
  init_path_resolver();
89927
90055
  init_types3();
89928
- var import_fs_extra34 = __toESM(require_lib3(), 1);
90056
+ var import_fs_extra35 = __toESM(require_lib3(), 1);
89929
90057
 
89930
90058
  // src/commands/init/types.ts
89931
90059
  function isSyncContext(ctx) {
@@ -90116,7 +90244,7 @@ async function handleSelection(ctx) {
90116
90244
  return { ...ctx, cancelled: true };
90117
90245
  }
90118
90246
  }
90119
- if (!await import_fs_extra34.pathExists(resolvedDir)) {
90247
+ if (!await import_fs_extra35.pathExists(resolvedDir)) {
90120
90248
  if (ctx.options.global) {
90121
90249
  await mkdir30(resolvedDir, { recursive: true });
90122
90250
  logger.info(`Created global directory: ${resolvedDir}`);
@@ -90128,7 +90256,7 @@ async function handleSelection(ctx) {
90128
90256
  }
90129
90257
  if (!ctx.options.fresh) {
90130
90258
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
90131
- const claudeDir2 = prefix ? join103(resolvedDir, prefix) : resolvedDir;
90259
+ const claudeDir2 = prefix ? join104(resolvedDir, prefix) : resolvedDir;
90132
90260
  try {
90133
90261
  const existingMetadata = await readManifest(claudeDir2);
90134
90262
  if (existingMetadata?.kits) {
@@ -90160,7 +90288,7 @@ async function handleSelection(ctx) {
90160
90288
  }
90161
90289
  if (ctx.options.fresh) {
90162
90290
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
90163
- const claudeDir2 = prefix ? join103(resolvedDir, prefix) : resolvedDir;
90291
+ const claudeDir2 = prefix ? join104(resolvedDir, prefix) : resolvedDir;
90164
90292
  const canProceed = await handleFreshInstallation(claudeDir2, ctx.prompts);
90165
90293
  if (!canProceed) {
90166
90294
  return { ...ctx, cancelled: true };
@@ -90179,7 +90307,7 @@ async function handleSelection(ctx) {
90179
90307
  logger.info("Fetching available versions...");
90180
90308
  let currentVersion = null;
90181
90309
  try {
90182
- const metadataPath = ctx.options.global ? join103(PathResolver.getGlobalKitDir(), "metadata.json") : join103(resolvedDir, ".claude", "metadata.json");
90310
+ const metadataPath = ctx.options.global ? join104(PathResolver.getGlobalKitDir(), "metadata.json") : join104(resolvedDir, ".claude", "metadata.json");
90183
90311
  const metadata = await readClaudeKitMetadata(metadataPath);
90184
90312
  currentVersion = metadata?.version || null;
90185
90313
  if (currentVersion) {
@@ -90253,27 +90381,27 @@ async function handleSelection(ctx) {
90253
90381
  };
90254
90382
  }
90255
90383
  // src/commands/init/phases/sync-handler.ts
90256
- import { copyFile as copyFile8, mkdir as mkdir31, open as open4, readFile as readFile49, rename as rename7, stat as stat17, unlink as unlink11, writeFile as writeFile30 } from "node:fs/promises";
90257
- import { dirname as dirname23, join as join104, resolve as resolve22 } from "node:path";
90384
+ import { copyFile as copyFile8, mkdir as mkdir31, open as open4, readFile as readFile50, rename as rename7, stat as stat17, unlink as unlink11, writeFile as writeFile30 } from "node:fs/promises";
90385
+ import { dirname as dirname23, join as join105, resolve as resolve22 } from "node:path";
90258
90386
  init_cc_version_checker();
90259
90387
  init_manifest_reader();
90260
90388
  init_logger();
90261
90389
  init_path_resolver();
90262
- var import_fs_extra35 = __toESM(require_lib3(), 1);
90390
+ var import_fs_extra36 = __toESM(require_lib3(), 1);
90263
90391
  var import_picocolors23 = __toESM(require_picocolors(), 1);
90264
90392
  async function handleSync(ctx) {
90265
90393
  if (!ctx.options.sync) {
90266
90394
  return ctx;
90267
90395
  }
90268
90396
  const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve22(ctx.options.dir || ".");
90269
- const claudeDir2 = ctx.options.global ? resolvedDir : join104(resolvedDir, ".claude");
90270
- if (!await import_fs_extra35.pathExists(claudeDir2)) {
90397
+ const claudeDir2 = ctx.options.global ? resolvedDir : join105(resolvedDir, ".claude");
90398
+ if (!await import_fs_extra36.pathExists(claudeDir2)) {
90271
90399
  logger.error("Cannot sync: no .claude directory found");
90272
90400
  ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
90273
90401
  return { ...ctx, cancelled: true };
90274
90402
  }
90275
- const metadataPath = join104(claudeDir2, "metadata.json");
90276
- if (!await import_fs_extra35.pathExists(metadataPath)) {
90403
+ const metadataPath = join105(claudeDir2, "metadata.json");
90404
+ if (!await import_fs_extra36.pathExists(metadataPath)) {
90277
90405
  logger.error("Cannot sync: no metadata.json found");
90278
90406
  ctx.prompts.note(`Your installation may be from an older version.
90279
90407
  Run 'ck init' to update.`, "Legacy Installation");
@@ -90381,7 +90509,7 @@ function isProcessAlive(pid) {
90381
90509
  }
90382
90510
  async function readLockPayload(lockPath) {
90383
90511
  try {
90384
- const raw2 = await readFile49(lockPath, "utf-8");
90512
+ const raw2 = await readFile50(lockPath, "utf-8");
90385
90513
  const parsed = JSON.parse(raw2);
90386
90514
  if (typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0) {
90387
90515
  return {
@@ -90394,7 +90522,7 @@ async function readLockPayload(lockPath) {
90394
90522
  }
90395
90523
  async function acquireSyncLock(global3) {
90396
90524
  const cacheDir = PathResolver.getCacheDir(global3);
90397
- const lockPath = join104(cacheDir, ".sync-lock");
90525
+ const lockPath = join105(cacheDir, ".sync-lock");
90398
90526
  const startTime = Date.now();
90399
90527
  const lockTimeout = getLockTimeout();
90400
90528
  await mkdir31(dirname23(lockPath), { recursive: true });
@@ -90454,12 +90582,12 @@ async function executeSyncMerge(ctx) {
90454
90582
  const releaseLock = await acquireSyncLock(ctx.options.global);
90455
90583
  try {
90456
90584
  const trackedFiles = ctx.syncTrackedFiles;
90457
- const upstreamDir = ctx.options.global ? join104(ctx.extractDir, ".claude") : ctx.extractDir;
90585
+ const upstreamDir = ctx.options.global ? join105(ctx.extractDir, ".claude") : ctx.extractDir;
90458
90586
  let deletions = [];
90459
90587
  try {
90460
- const sourceMetadataPath = join104(upstreamDir, "metadata.json");
90461
- if (await import_fs_extra35.pathExists(sourceMetadataPath)) {
90462
- const content = await readFile49(sourceMetadataPath, "utf-8");
90588
+ const sourceMetadataPath = join105(upstreamDir, "metadata.json");
90589
+ if (await import_fs_extra36.pathExists(sourceMetadataPath)) {
90590
+ const content = await readFile50(sourceMetadataPath, "utf-8");
90463
90591
  const sourceMetadata = JSON.parse(content);
90464
90592
  deletions = sourceMetadata.deletions || [];
90465
90593
  }
@@ -90757,7 +90885,7 @@ async function createBackup(claudeDir2, files, backupDir) {
90757
90885
  for (const file of files) {
90758
90886
  try {
90759
90887
  const sourcePath = await validateSyncPath(claudeDir2, file.path);
90760
- if (await import_fs_extra35.pathExists(sourcePath)) {
90888
+ if (await import_fs_extra36.pathExists(sourcePath)) {
90761
90889
  const targetPath = await validateSyncPath(backupDir, file.path);
90762
90890
  const targetDir = dirname23(targetPath);
90763
90891
  await mkdir31(targetDir, { recursive: true });
@@ -90792,7 +90920,7 @@ function extractSkillDirFromDeletionPath2(path14) {
90792
90920
  }
90793
90921
  // src/commands/init/phases/transform-handler.ts
90794
90922
  init_config_manager();
90795
- import { join as join108 } from "node:path";
90923
+ import { join as join109 } from "node:path";
90796
90924
 
90797
90925
  // src/services/transformers/folder-path-transformer.ts
90798
90926
  init_logger();
@@ -90801,40 +90929,40 @@ init_types3();
90801
90929
  // src/services/transformers/folder-transform/folder-renamer.ts
90802
90930
  init_logger();
90803
90931
  init_types3();
90804
- var import_fs_extra36 = __toESM(require_lib3(), 1);
90932
+ var import_fs_extra37 = __toESM(require_lib3(), 1);
90805
90933
  import { rename as rename8, rm as rm13 } from "node:fs/promises";
90806
- import { join as join105, relative as relative18 } from "node:path";
90934
+ import { join as join106, relative as relative18 } from "node:path";
90807
90935
  async function collectDirsToRename(extractDir, folders) {
90808
90936
  const dirsToRename = [];
90809
90937
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
90810
- const docsPath = join105(extractDir, DEFAULT_FOLDERS.docs);
90811
- if (await import_fs_extra36.pathExists(docsPath)) {
90938
+ const docsPath = join106(extractDir, DEFAULT_FOLDERS.docs);
90939
+ if (await import_fs_extra37.pathExists(docsPath)) {
90812
90940
  dirsToRename.push({
90813
90941
  from: docsPath,
90814
- to: join105(extractDir, folders.docs)
90942
+ to: join106(extractDir, folders.docs)
90815
90943
  });
90816
90944
  }
90817
- const claudeDocsPath = join105(extractDir, ".claude", DEFAULT_FOLDERS.docs);
90818
- if (await import_fs_extra36.pathExists(claudeDocsPath)) {
90945
+ const claudeDocsPath = join106(extractDir, ".claude", DEFAULT_FOLDERS.docs);
90946
+ if (await import_fs_extra37.pathExists(claudeDocsPath)) {
90819
90947
  dirsToRename.push({
90820
90948
  from: claudeDocsPath,
90821
- to: join105(extractDir, ".claude", folders.docs)
90949
+ to: join106(extractDir, ".claude", folders.docs)
90822
90950
  });
90823
90951
  }
90824
90952
  }
90825
90953
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
90826
- const plansPath = join105(extractDir, DEFAULT_FOLDERS.plans);
90827
- if (await import_fs_extra36.pathExists(plansPath)) {
90954
+ const plansPath = join106(extractDir, DEFAULT_FOLDERS.plans);
90955
+ if (await import_fs_extra37.pathExists(plansPath)) {
90828
90956
  dirsToRename.push({
90829
90957
  from: plansPath,
90830
- to: join105(extractDir, folders.plans)
90958
+ to: join106(extractDir, folders.plans)
90831
90959
  });
90832
90960
  }
90833
- const claudePlansPath = join105(extractDir, ".claude", DEFAULT_FOLDERS.plans);
90834
- if (await import_fs_extra36.pathExists(claudePlansPath)) {
90961
+ const claudePlansPath = join106(extractDir, ".claude", DEFAULT_FOLDERS.plans);
90962
+ if (await import_fs_extra37.pathExists(claudePlansPath)) {
90835
90963
  dirsToRename.push({
90836
90964
  from: claudePlansPath,
90837
- to: join105(extractDir, ".claude", folders.plans)
90965
+ to: join106(extractDir, ".claude", folders.plans)
90838
90966
  });
90839
90967
  }
90840
90968
  }
@@ -90846,7 +90974,7 @@ async function moveAcrossDevices(src, dest) {
90846
90974
  } catch (e2) {
90847
90975
  if (e2.code === "EXDEV") {
90848
90976
  logger.debug(`Cross-device move detected, using copy+delete: ${src} -> ${dest}`);
90849
- await import_fs_extra36.copy(src, dest, { overwrite: true });
90977
+ await import_fs_extra37.copy(src, dest, { overwrite: true });
90850
90978
  await rm13(src, { recursive: true, force: true });
90851
90979
  } else {
90852
90980
  throw e2;
@@ -90874,8 +91002,8 @@ async function renameFolders(dirsToRename, extractDir, options2) {
90874
91002
  // src/services/transformers/folder-transform/path-replacer.ts
90875
91003
  init_logger();
90876
91004
  init_types3();
90877
- import { readFile as readFile50, readdir as readdir32, writeFile as writeFile31 } from "node:fs/promises";
90878
- import { join as join106, relative as relative19 } from "node:path";
91005
+ import { readFile as readFile51, readdir as readdir33, writeFile as writeFile31 } from "node:fs/promises";
91006
+ import { join as join107, relative as relative19 } from "node:path";
90879
91007
  var TRANSFORMABLE_FILE_PATTERNS = [
90880
91008
  ".md",
90881
91009
  ".txt",
@@ -90926,9 +91054,9 @@ function compileReplacements(replacements) {
90926
91054
  async function transformFileContents(dir, compiledReplacements, options2) {
90927
91055
  let filesChanged = 0;
90928
91056
  let replacementsCount = 0;
90929
- const entries = await readdir32(dir, { withFileTypes: true });
91057
+ const entries = await readdir33(dir, { withFileTypes: true });
90930
91058
  for (const entry of entries) {
90931
- const fullPath = join106(dir, entry.name);
91059
+ const fullPath = join107(dir, entry.name);
90932
91060
  if (entry.isDirectory()) {
90933
91061
  if (entry.name === "node_modules" || entry.name === ".git") {
90934
91062
  continue;
@@ -90941,7 +91069,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
90941
91069
  if (!shouldTransform)
90942
91070
  continue;
90943
91071
  try {
90944
- const content = await readFile50(fullPath, "utf-8");
91072
+ const content = await readFile51(fullPath, "utf-8");
90945
91073
  let newContent = content;
90946
91074
  let changeCount = 0;
90947
91075
  for (const { regex: regex2, replacement } of compiledReplacements) {
@@ -91063,9 +91191,9 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
91063
91191
 
91064
91192
  // src/services/transformers/global-path-transformer.ts
91065
91193
  init_logger();
91066
- import { readFile as readFile51, readdir as readdir33, writeFile as writeFile32 } from "node:fs/promises";
91194
+ import { readFile as readFile52, readdir as readdir34, writeFile as writeFile32 } from "node:fs/promises";
91067
91195
  import { platform as platform13 } from "node:os";
91068
- import { extname as extname6, join as join107 } from "node:path";
91196
+ import { extname as extname6, join as join108 } from "node:path";
91069
91197
  var IS_WINDOWS3 = platform13() === "win32";
91070
91198
  var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
91071
91199
  function getHomeDirPrefix() {
@@ -91173,9 +91301,9 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
91173
91301
  let filesSkipped = 0;
91174
91302
  const skippedFiles = [];
91175
91303
  async function processDirectory2(dir) {
91176
- const entries = await readdir33(dir, { withFileTypes: true });
91304
+ const entries = await readdir34(dir, { withFileTypes: true });
91177
91305
  for (const entry of entries) {
91178
- const fullPath = join107(dir, entry.name);
91306
+ const fullPath = join108(dir, entry.name);
91179
91307
  if (entry.isDirectory()) {
91180
91308
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
91181
91309
  continue;
@@ -91183,7 +91311,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
91183
91311
  await processDirectory2(fullPath);
91184
91312
  } else if (entry.isFile() && shouldTransformFile3(entry.name)) {
91185
91313
  try {
91186
- const content = await readFile51(fullPath, "utf-8");
91314
+ const content = await readFile52(fullPath, "utf-8");
91187
91315
  const { transformed, changes } = transformContent(content);
91188
91316
  if (changes > 0) {
91189
91317
  await writeFile32(fullPath, transformed, "utf-8");
@@ -91251,7 +91379,7 @@ async function handleTransforms(ctx) {
91251
91379
  logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
91252
91380
  }
91253
91381
  }
91254
- const claudeDir2 = ctx.options.global ? ctx.resolvedDir : join108(ctx.resolvedDir, ".claude");
91382
+ const claudeDir2 = ctx.options.global ? ctx.resolvedDir : join109(ctx.resolvedDir, ".claude");
91255
91383
  return {
91256
91384
  ...ctx,
91257
91385
  foldersConfig,
@@ -91445,7 +91573,7 @@ init_checksum_utils();
91445
91573
  init_config_discovery();
91446
91574
  var import_picocolors25 = __toESM(require_picocolors(), 1);
91447
91575
  import { existsSync as existsSync51 } from "node:fs";
91448
- import { readFile as readFile52, rm as rm14, unlink as unlink12 } from "node:fs/promises";
91576
+ import { readFile as readFile53, rm as rm14, unlink as unlink12 } from "node:fs/promises";
91449
91577
  import { resolve as resolve23 } from "node:path";
91450
91578
 
91451
91579
  // src/commands/portable/conflict-resolver.ts
@@ -92018,7 +92146,7 @@ async function migrateCommand(options2) {
92018
92146
  for (const action of conflictActions) {
92019
92147
  if (!action.diff && action.targetPath && existsSync51(action.targetPath)) {
92020
92148
  try {
92021
- const targetContent = await readFile52(action.targetPath, "utf-8");
92149
+ const targetContent = await readFile53(action.targetPath, "utf-8");
92022
92150
  const sourceItem = agents2.find((a3) => a3.name === action.item) || commands.find((c2) => c2.name === action.item) || (configItem?.name === action.item ? configItem : null) || ruleItems.find((r2) => r2.name === action.item);
92023
92151
  if (sourceItem) {
92024
92152
  const providerConfig = providers[action.provider];
@@ -92225,7 +92353,7 @@ async function computeTargetStates(selectedProviders, global3) {
92225
92353
  exists: true
92226
92354
  };
92227
92355
  try {
92228
- const content = await readFile52(entry.path, "utf-8");
92356
+ const content = await readFile53(entry.path, "utf-8");
92229
92357
  state.currentChecksum = computeContentChecksum(content);
92230
92358
  } catch (error) {
92231
92359
  logger.debug(`[migrate] Failed to read target for checksum: ${entry.path} (${String(error)})`);
@@ -92288,7 +92416,7 @@ import { resolve as resolve24 } from "node:path";
92288
92416
  init_logger();
92289
92417
  init_path_resolver();
92290
92418
  init_types3();
92291
- var import_fs_extra37 = __toESM(require_lib3(), 1);
92419
+ var import_fs_extra38 = __toESM(require_lib3(), 1);
92292
92420
  async function directorySetup(validOptions, prompts) {
92293
92421
  const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
92294
92422
  const config = await ConfigManager.get();
@@ -92387,8 +92515,8 @@ async function directorySetup(validOptions, prompts) {
92387
92515
  return null;
92388
92516
  }
92389
92517
  }
92390
- if (await import_fs_extra37.pathExists(resolvedDir)) {
92391
- const files = await import_fs_extra37.readdir(resolvedDir);
92518
+ if (await import_fs_extra38.pathExists(resolvedDir)) {
92519
+ const files = await import_fs_extra38.readdir(resolvedDir);
92392
92520
  const isEmpty = files.length === 0;
92393
92521
  if (!isEmpty) {
92394
92522
  if (isNonInteractive2) {
@@ -92426,7 +92554,7 @@ async function handleDirectorySetup(ctx) {
92426
92554
  // src/commands/new/phases/project-creation.ts
92427
92555
  init_config_manager();
92428
92556
  init_github_client();
92429
- import { join as join109 } from "node:path";
92557
+ import { join as join110 } from "node:path";
92430
92558
  init_logger();
92431
92559
  init_output_manager();
92432
92560
  init_types3();
@@ -92552,7 +92680,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
92552
92680
  output.section("Installing");
92553
92681
  logger.verbose("Installation target", { directory: resolvedDir });
92554
92682
  const merger = new FileMerger;
92555
- const claudeDir2 = join109(resolvedDir, ".claude");
92683
+ const claudeDir2 = join110(resolvedDir, ".claude");
92556
92684
  merger.setMultiKitContext(claudeDir2, kit);
92557
92685
  if (validOptions.exclude && validOptions.exclude.length > 0) {
92558
92686
  merger.addIgnorePatterns(validOptions.exclude);
@@ -92599,7 +92727,7 @@ async function handleProjectCreation(ctx) {
92599
92727
  }
92600
92728
  // src/commands/new/phases/post-setup.ts
92601
92729
  init_projects_registry();
92602
- import { join as join110 } from "node:path";
92730
+ import { join as join111 } from "node:path";
92603
92731
  init_package_installer();
92604
92732
  init_logger();
92605
92733
  init_path_resolver();
@@ -92631,9 +92759,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
92631
92759
  withSudo: validOptions.withSudo
92632
92760
  });
92633
92761
  }
92634
- const claudeDir2 = join110(resolvedDir, ".claude");
92762
+ const claudeDir2 = join111(resolvedDir, ".claude");
92635
92763
  await promptSetupWizardIfNeeded({
92636
- envPath: join110(claudeDir2, ".env"),
92764
+ envPath: join111(claudeDir2, ".env"),
92637
92765
  claudeDir: claudeDir2,
92638
92766
  isGlobal: false,
92639
92767
  isNonInteractive: isNonInteractive2,
@@ -93600,7 +93728,7 @@ var import_picocolors32 = __toESM(require_picocolors(), 1);
93600
93728
  // src/commands/uninstall/installation-detector.ts
93601
93729
  init_claudekit_scanner();
93602
93730
  init_path_resolver();
93603
- var import_fs_extra38 = __toESM(require_lib3(), 1);
93731
+ var import_fs_extra39 = __toESM(require_lib3(), 1);
93604
93732
  function hasClaudeKitComponents(components) {
93605
93733
  return components.agents > 0 || components.commands > 0 || components.rules > 0 || components.skills > 0;
93606
93734
  }
@@ -93615,7 +93743,7 @@ async function detectInstallations() {
93615
93743
  installations.push({
93616
93744
  type: "local",
93617
93745
  path: setup.project.path,
93618
- exists: await import_fs_extra38.pathExists(setup.project.path),
93746
+ exists: await import_fs_extra39.pathExists(setup.project.path),
93619
93747
  hasMetadata,
93620
93748
  components: setup.project.components
93621
93749
  });
@@ -93628,7 +93756,7 @@ async function detectInstallations() {
93628
93756
  installations.push({
93629
93757
  type: "global",
93630
93758
  path: setup.global.path,
93631
- exists: await import_fs_extra38.pathExists(setup.global.path),
93759
+ exists: await import_fs_extra39.pathExists(setup.global.path),
93632
93760
  hasMetadata,
93633
93761
  components: setup.global.components
93634
93762
  });
@@ -93639,16 +93767,16 @@ async function detectInstallations() {
93639
93767
 
93640
93768
  // src/commands/uninstall/removal-handler.ts
93641
93769
  import { readdirSync as readdirSync6, rmSync as rmSync5 } from "node:fs";
93642
- import { join as join112, resolve as resolve26, sep as sep5 } from "node:path";
93770
+ import { join as join113, resolve as resolve26, sep as sep5 } from "node:path";
93643
93771
  init_logger();
93644
93772
  init_safe_prompts();
93645
93773
  init_safe_spinner();
93646
- var import_fs_extra39 = __toESM(require_lib3(), 1);
93774
+ var import_fs_extra40 = __toESM(require_lib3(), 1);
93647
93775
 
93648
93776
  // src/commands/uninstall/analysis-handler.ts
93649
93777
  init_metadata_migration();
93650
93778
  import { readdirSync as readdirSync5, rmSync as rmSync4 } from "node:fs";
93651
- import { dirname as dirname24, join as join111 } from "node:path";
93779
+ import { dirname as dirname24, join as join112 } from "node:path";
93652
93780
  init_logger();
93653
93781
  init_safe_prompts();
93654
93782
  var import_picocolors31 = __toESM(require_picocolors(), 1);
@@ -93696,7 +93824,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
93696
93824
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
93697
93825
  const kitFiles = metadata.kits[kit].files || [];
93698
93826
  for (const trackedFile of kitFiles) {
93699
- const filePath = join111(installation.path, trackedFile.path);
93827
+ const filePath = join112(installation.path, trackedFile.path);
93700
93828
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
93701
93829
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
93702
93830
  continue;
@@ -93726,7 +93854,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
93726
93854
  return result;
93727
93855
  }
93728
93856
  for (const trackedFile of allTrackedFiles) {
93729
- const filePath = join111(installation.path, trackedFile.path);
93857
+ const filePath = join112(installation.path, trackedFile.path);
93730
93858
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
93731
93859
  if (!ownershipResult.exists)
93732
93860
  continue;
@@ -93771,7 +93899,7 @@ function displayDryRunPreview(analysis, installationType) {
93771
93899
  // src/commands/uninstall/removal-handler.ts
93772
93900
  async function isDirectory(filePath) {
93773
93901
  try {
93774
- const stats = await import_fs_extra39.lstat(filePath);
93902
+ const stats = await import_fs_extra40.lstat(filePath);
93775
93903
  return stats.isDirectory();
93776
93904
  } catch {
93777
93905
  logger.debug(`Failed to check if path is directory: ${filePath}`);
@@ -93786,9 +93914,9 @@ async function isPathSafeToRemove(filePath, baseDir) {
93786
93914
  logger.debug(`Path outside installation directory: ${filePath}`);
93787
93915
  return false;
93788
93916
  }
93789
- const stats = await import_fs_extra39.lstat(filePath);
93917
+ const stats = await import_fs_extra40.lstat(filePath);
93790
93918
  if (stats.isSymbolicLink()) {
93791
- const realPath = await import_fs_extra39.realpath(filePath);
93919
+ const realPath = await import_fs_extra40.realpath(filePath);
93792
93920
  const resolvedReal = resolve26(realPath);
93793
93921
  if (!resolvedReal.startsWith(resolvedBase + sep5) && resolvedReal !== resolvedBase) {
93794
93922
  logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
@@ -93823,15 +93951,15 @@ async function removeInstallations(installations, options2) {
93823
93951
  let removedCount = 0;
93824
93952
  let cleanedDirs = 0;
93825
93953
  for (const item of analysis.toDelete) {
93826
- const filePath = join112(installation.path, item.path);
93827
- if (!await import_fs_extra39.pathExists(filePath))
93954
+ const filePath = join113(installation.path, item.path);
93955
+ if (!await import_fs_extra40.pathExists(filePath))
93828
93956
  continue;
93829
93957
  if (!await isPathSafeToRemove(filePath, installation.path)) {
93830
93958
  logger.debug(`Skipping unsafe path: ${item.path}`);
93831
93959
  continue;
93832
93960
  }
93833
93961
  const isDir = await isDirectory(filePath);
93834
- await import_fs_extra39.remove(filePath);
93962
+ await import_fs_extra40.remove(filePath);
93835
93963
  removedCount++;
93836
93964
  logger.debug(`Removed ${isDir ? "directory" : "file"}: ${item.path}`);
93837
93965
  if (!isDir) {
@@ -94222,7 +94350,7 @@ init_logger();
94222
94350
  init_path_resolver();
94223
94351
  init_types3();
94224
94352
  import { existsSync as existsSync53, readFileSync as readFileSync10 } from "node:fs";
94225
- import { join as join113 } from "node:path";
94353
+ import { join as join114 } from "node:path";
94226
94354
  var packageVersion = package_default.version;
94227
94355
  function formatInstalledKits(metadata) {
94228
94356
  if (!metadata.kits || Object.keys(metadata.kits).length === 0) {
@@ -94254,9 +94382,9 @@ async function displayVersion() {
94254
94382
  let localKitVersion = null;
94255
94383
  let isGlobalOnlyKit = false;
94256
94384
  const globalKitDir = PathResolver.getGlobalKitDir();
94257
- const globalMetadataPath = join113(globalKitDir, "metadata.json");
94385
+ const globalMetadataPath = join114(globalKitDir, "metadata.json");
94258
94386
  const prefix = PathResolver.getPathPrefix(false);
94259
- const localMetadataPath = prefix ? join113(process.cwd(), prefix, "metadata.json") : join113(process.cwd(), "metadata.json");
94387
+ const localMetadataPath = prefix ? join114(process.cwd(), prefix, "metadata.json") : join114(process.cwd(), "metadata.json");
94260
94388
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
94261
94389
  if (!isLocalSameAsGlobal && existsSync53(localMetadataPath)) {
94262
94390
  try {
@@ -94649,7 +94777,7 @@ var output2 = new OutputManager2;
94649
94777
 
94650
94778
  // src/shared/temp-cleanup.ts
94651
94779
  init_logger();
94652
- var import_fs_extra40 = __toESM(require_lib3(), 1);
94780
+ var import_fs_extra41 = __toESM(require_lib3(), 1);
94653
94781
  import { rmSync as rmSync6 } from "node:fs";
94654
94782
  var tempDirs2 = new Set;
94655
94783
  async function cleanup() {
@@ -94658,7 +94786,7 @@ async function cleanup() {
94658
94786
  logger.debug(`Cleaning up ${tempDirs2.size} temporary director(ies)...`);
94659
94787
  for (const dir of tempDirs2) {
94660
94788
  try {
94661
- await import_fs_extra40.remove(dir);
94789
+ await import_fs_extra41.remove(dir);
94662
94790
  logger.debug(`Cleaned up temp directory: ${dir}`);
94663
94791
  } catch (error) {
94664
94792
  logger.debug(`Failed to clean temp directory ${dir}: ${error}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.36.0-dev.1",
3
+ "version": "3.36.0-dev.2",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {