claudekit-cli 4.0.0-dev.2 → 4.0.0-dev.3

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/README.md CHANGED
@@ -324,6 +324,7 @@ Remove ClaudeKit installations from your system:
324
324
  ck uninstall # Interactive mode - prompts for scope and confirmation
325
325
  ck uninstall --local # Uninstall only local installation (current project)
326
326
  ck uninstall --global # Uninstall only global installation (~/.claude/)
327
+ ck uninstall -g --kit marketing # Remove only global Marketing kit
327
328
  ck uninstall -l -y # Local only, skip confirmation
328
329
  ck uninstall -g -y # Global only, skip confirmation
329
330
  ck uninstall --yes # Non-interactive - skip confirmation (for scripts)
@@ -334,7 +335,11 @@ ck uninstall --yes # Non-interactive - skip confirmation (for scripts)
334
335
  - **Local only**: Remove from current project (`.claude/`)
335
336
  - **Global only**: Remove from user directory (`~/.claude/`)
336
337
  - **Both**: Remove all ClaudeKit installations
338
+ - When multiple kits are installed in the selected scope, interactive uninstall prompts for:
339
+ - **Marketing kit only** or **Engineer kit only**: Remove one kit and preserve the other
340
+ - **All ClaudeKit kits**: Remove the full selected installation scope
337
341
  - Use `--local` or `--global` flags to skip the prompt
342
+ - Use `--kit engineer` or `--kit marketing` to skip the kit prompt
338
343
 
339
344
  **What it does:**
340
345
  - Detects local `.claude` directory in current project
package/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.0.0-dev.2",
3
- "generatedAt": "2026-05-07T18:05:52.152Z",
2
+ "version": "4.0.0-dev.3",
3
+ "generatedAt": "2026-05-09T03:16:37.030Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
@@ -1922,6 +1922,10 @@
1922
1922
  "description": "Remove ClaudeKit installations (ownership-aware)",
1923
1923
  "usage": "ck uninstall [options]",
1924
1924
  "examples": [
1925
+ {
1926
+ "command": "ck uninstall --global --kit marketing",
1927
+ "description": "Remove only the global Marketing kit and preserve Engineer"
1928
+ },
1925
1929
  {
1926
1930
  "command": "ck uninstall --local --yes",
1927
1931
  "description": "Remove local installation without confirmation"
package/dist/index.js CHANGED
@@ -62359,7 +62359,7 @@ var package_default;
62359
62359
  var init_package = __esm(() => {
62360
62360
  package_default = {
62361
62361
  name: "claudekit-cli",
62362
- version: "4.0.0-dev.2",
62362
+ version: "4.0.0-dev.3",
62363
62363
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
62364
62364
  type: "module",
62365
62365
  repository: {
@@ -78178,6 +78178,10 @@ var init_uninstall_command_help = __esm(() => {
78178
78178
  description: "Remove ClaudeKit installations (ownership-aware)",
78179
78179
  usage: "ck uninstall [options]",
78180
78180
  examples: [
78181
+ {
78182
+ command: "ck uninstall --global --kit marketing",
78183
+ description: "Remove only the global Marketing kit and preserve Engineer"
78184
+ },
78181
78185
  {
78182
78186
  command: "ck uninstall --local --yes",
78183
78187
  description: "Remove local installation without confirmation"
@@ -105192,6 +105196,21 @@ function isSyncContext(ctx) {
105192
105196
  }
105193
105197
 
105194
105198
  // src/commands/init/phases/selection-handler.ts
105199
+ function buildKitScopedUninstallCommands(kits, resolvedDir, isGlobal) {
105200
+ const scopeFlag = isGlobal || PathResolver.isLocalSameAsGlobal(resolvedDir) ? "--global" : "--local";
105201
+ return kits.map((kit) => `ck uninstall ${scopeFlag} --kit ${kit}`);
105202
+ }
105203
+ function buildRerunInitCommand(kitType, resolvedDir, isGlobal) {
105204
+ const args = ["ck init"];
105205
+ const targetsGlobal = isGlobal || PathResolver.isLocalSameAsGlobal(resolvedDir);
105206
+ if (targetsGlobal) {
105207
+ args.push("--global");
105208
+ } else {
105209
+ args.push(`--dir ${JSON.stringify(resolvedDir)}`);
105210
+ }
105211
+ args.push(`--kit ${kitType}`);
105212
+ return args.join(" ");
105213
+ }
105195
105214
  async function handleSelection(ctx) {
105196
105215
  if (ctx.cancelled)
105197
105216
  return ctx;
@@ -105407,6 +105426,11 @@ async function handleSelection(ctx) {
105407
105426
  try {
105408
105427
  const confirmAdd = await ctx.prompts.confirm(`${existingKitsDisplay} already installed. Add ${kit.name} alongside?`);
105409
105428
  if (!confirmAdd) {
105429
+ logger.info("To remove one installed kit first, run:");
105430
+ for (const command of buildKitScopedUninstallCommands(otherKits, resolvedDir, ctx.options.global)) {
105431
+ logger.info(` ${command}`);
105432
+ }
105433
+ logger.info(`Then rerun: ${buildRerunInitCommand(kitType, resolvedDir, ctx.options.global)}`);
105410
105434
  logger.warning("Multi-kit installation cancelled by user");
105411
105435
  return { ...ctx, cancelled: true };
105412
105436
  }
@@ -111280,6 +111304,9 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
111280
111304
  remainingKits: []
111281
111305
  };
111282
111306
  const metadata = await ManifestWriter.readManifest(installation.path);
111307
+ if (kit && (!metadata || !getInstalledKits(metadata).includes(kit))) {
111308
+ return result;
111309
+ }
111283
111310
  const uninstallManifest = await ManifestWriter.getUninstallManifest(installation.path, kit);
111284
111311
  result.remainingKits = uninstallManifest.remainingKits;
111285
111312
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
@@ -111590,6 +111617,56 @@ async function promptScope(installations) {
111590
111617
  }
111591
111618
  return selected;
111592
111619
  }
111620
+ async function getInstallationKits(installation) {
111621
+ const metadata = await ManifestWriter.readManifest(installation.path);
111622
+ return metadata ? getInstalledKits(metadata) : [];
111623
+ }
111624
+ async function getInstalledKitSet(installations) {
111625
+ const installedKitSet = new Set;
111626
+ for (const installation of installations) {
111627
+ for (const kit of await getInstallationKits(installation)) {
111628
+ installedKitSet.add(kit);
111629
+ }
111630
+ }
111631
+ return installedKitSet;
111632
+ }
111633
+ async function filterInstallationsByKit(installations, kit) {
111634
+ const filtered = [];
111635
+ for (const installation of installations) {
111636
+ const installedKits = await getInstallationKits(installation);
111637
+ if (installedKits.includes(kit)) {
111638
+ filtered.push(installation);
111639
+ }
111640
+ }
111641
+ return filtered;
111642
+ }
111643
+ async function promptKitSelection(installedKitSet) {
111644
+ if (installedKitSet.size < 2) {
111645
+ return "all";
111646
+ }
111647
+ const kitOrder = ["marketing", "engineer"];
111648
+ const kitOptions = kitOrder.filter((kit) => installedKitSet.has(kit)).map((kit) => ({
111649
+ value: kit,
111650
+ label: `${kit[0].toUpperCase()}${kit.slice(1)} kit only`,
111651
+ hint: "Preserve other installed kit(s) and customizations"
111652
+ }));
111653
+ const options2 = [
111654
+ ...kitOptions,
111655
+ {
111656
+ value: "all",
111657
+ label: "All ClaudeKit kits",
111658
+ hint: "Remove the full selected installation scope"
111659
+ }
111660
+ ];
111661
+ const selected = await ie({
111662
+ message: "Multiple kits are installed. What do you want to uninstall?",
111663
+ options: options2
111664
+ });
111665
+ if (lD(selected)) {
111666
+ return null;
111667
+ }
111668
+ return selected;
111669
+ }
111593
111670
  async function confirmUninstall(scope, kitLabel = "") {
111594
111671
  const scopeText = scope === "all" ? "all ClaudeKit installations" : scope === "local" ? "local ClaudeKit installation" : "global ClaudeKit installation";
111595
111672
  const confirmed = await se({
@@ -111648,7 +111725,7 @@ async function uninstallCommand(options2) {
111648
111725
  }
111649
111726
  scope = promptedScope;
111650
111727
  }
111651
- const installations = allInstallations.filter((i) => {
111728
+ let installations = allInstallations.filter((i) => {
111652
111729
  if (scope === "all")
111653
111730
  return true;
111654
111731
  return i.type === scope;
@@ -111658,16 +111735,41 @@ async function uninstallCommand(options2) {
111658
111735
  logger.info(`No ${scopeLabel} ClaudeKit installation found.`);
111659
111736
  return;
111660
111737
  }
111738
+ let kitToRemove = validOptions.kit;
111739
+ if (!kitToRemove) {
111740
+ const installedKitSet = await getInstalledKitSet(installations);
111741
+ if (validOptions.yes) {
111742
+ if (installedKitSet.size > 1) {
111743
+ logger.info("Removing all installed kits (--yes flag bypasses kit prompt; use --kit to scope).");
111744
+ }
111745
+ } else {
111746
+ const selectedKit = await promptKitSelection(installedKitSet);
111747
+ if (!selectedKit) {
111748
+ logger.info("Uninstall cancelled.");
111749
+ return;
111750
+ }
111751
+ if (selectedKit !== "all") {
111752
+ kitToRemove = selectedKit;
111753
+ }
111754
+ }
111755
+ }
111756
+ if (kitToRemove) {
111757
+ installations = await filterInstallationsByKit(installations, kitToRemove);
111758
+ if (installations.length === 0) {
111759
+ logger.info(`Kit "${kitToRemove}" is not installed in selected scope.`);
111760
+ return;
111761
+ }
111762
+ }
111661
111763
  displayInstallations(installations, scope);
111662
- if (validOptions.kit) {
111663
- log.info(import_picocolors39.default.cyan(`Kit-scoped uninstall: ${validOptions.kit} kit only`));
111764
+ if (kitToRemove) {
111765
+ log.info(import_picocolors39.default.cyan(`Kit-scoped uninstall: ${kitToRemove} kit only`));
111664
111766
  }
111665
111767
  if (validOptions.dryRun) {
111666
111768
  log.info(import_picocolors39.default.yellow("DRY RUN MODE - No files will be deleted"));
111667
111769
  await removeInstallations(installations, {
111668
111770
  dryRun: true,
111669
111771
  forceOverwrite: validOptions.forceOverwrite,
111670
- kit: validOptions.kit
111772
+ kit: kitToRemove
111671
111773
  });
111672
111774
  prompts.outro("Dry-run complete. No changes were made.");
111673
111775
  return;
@@ -111677,7 +111779,7 @@ async function uninstallCommand(options2) {
111677
111779
  ${import_picocolors39.default.yellow("User modifications will be permanently deleted!")}`);
111678
111780
  }
111679
111781
  if (!validOptions.yes) {
111680
- const kitLabel = validOptions.kit ? ` (${validOptions.kit} kit only)` : "";
111782
+ const kitLabel = kitToRemove ? ` (${kitToRemove} kit only)` : "";
111681
111783
  const confirmed = await confirmUninstall(scope, kitLabel);
111682
111784
  if (!confirmed) {
111683
111785
  logger.info("Uninstall cancelled.");
@@ -111687,10 +111789,10 @@ ${import_picocolors39.default.yellow("User modifications will be permanently del
111687
111789
  const results = await removeInstallations(installations, {
111688
111790
  dryRun: false,
111689
111791
  forceOverwrite: validOptions.forceOverwrite,
111690
- kit: validOptions.kit
111792
+ kit: kitToRemove
111691
111793
  });
111692
111794
  const hasProtectedFiles = results.some((result) => result.protectedTrackedPaths.length > 0);
111693
- const kitMsg = validOptions.kit ? ` (${validOptions.kit} kit)` : "";
111795
+ const kitMsg = kitToRemove ? ` (${kitToRemove} kit)` : "";
111694
111796
  if (hasProtectedFiles) {
111695
111797
  prompts.outro(`ClaudeKit${kitMsg} uninstall completed with preserved customizations. Use --force-overwrite for full removal.`);
111696
111798
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "4.0.0-dev.2",
3
+ "version": "4.0.0-dev.3",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {