claudekit-cli 4.0.0-dev.1 → 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.1",
3
- "generatedAt": "2026-05-07T15:21:16.194Z",
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
@@ -55509,6 +55509,11 @@ var init_skill_schema = __esm(() => {
55509
55509
  maxLength: 512,
55510
55510
  description: "Human-readable description of the skill and when to use it"
55511
55511
  },
55512
+ when_to_use: {
55513
+ type: "string",
55514
+ maxLength: 1024,
55515
+ description: "Additional invocation context appended to description in Claude Code skill listings"
55516
+ },
55512
55517
  "user-invocable": {
55513
55518
  type: "boolean",
55514
55519
  description: "Whether the skill appears in the user slash-command menu. False keeps it available for agent invocation."
@@ -62354,7 +62359,7 @@ var package_default;
62354
62359
  var init_package = __esm(() => {
62355
62360
  package_default = {
62356
62361
  name: "claudekit-cli",
62357
- version: "4.0.0-dev.1",
62362
+ version: "4.0.0-dev.3",
62358
62363
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
62359
62364
  type: "module",
62360
62365
  repository: {
@@ -78173,6 +78178,10 @@ var init_uninstall_command_help = __esm(() => {
78173
78178
  description: "Remove ClaudeKit installations (ownership-aware)",
78174
78179
  usage: "ck uninstall [options]",
78175
78180
  examples: [
78181
+ {
78182
+ command: "ck uninstall --global --kit marketing",
78183
+ description: "Remove only the global Marketing kit and preserve Engineer"
78184
+ },
78176
78185
  {
78177
78186
  command: "ck uninstall --local --yes",
78178
78187
  description: "Remove local installation without confirmation"
@@ -84254,6 +84263,7 @@ async function scanSkills2(skillsDir2) {
84254
84263
  skills.push({
84255
84264
  id: normalizeSkillId(rawName, fallbackId),
84256
84265
  description: typeof data.description === "string" ? data.description : "",
84266
+ whenToUse: typeof data.when_to_use === "string" ? data.when_to_use : "",
84257
84267
  file,
84258
84268
  userInvocable: typeof data["user-invocable"] === "boolean" ? data["user-invocable"] : undefined
84259
84269
  });
@@ -84315,9 +84325,17 @@ function estimateListingChars(skills, maxDescChars) {
84315
84325
  if (skills.length === 0)
84316
84326
  return 0;
84317
84327
  return skills.reduce((sum, skill) => {
84318
- return sum + skill.id.length + LISTING_OVERHEAD_PER_SKILL + Math.min(skill.description.length, maxDescChars);
84328
+ return sum + skill.id.length + LISTING_OVERHEAD_PER_SKILL + Math.min(getListingText(skill).length, maxDescChars);
84319
84329
  }, skills.length - 1);
84320
84330
  }
84331
+ function getListingText(skill) {
84332
+ if (!skill.whenToUse)
84333
+ return skill.description;
84334
+ if (!skill.description)
84335
+ return skill.whenToUse;
84336
+ return `${skill.description}
84337
+ ${skill.whenToUse}`;
84338
+ }
84321
84339
  function requiredBudgetFraction(listingChars, contextTokens = CONTEXT_FLOOR_TOKENS) {
84322
84340
  if (listingChars <= 0)
84323
84341
  return DEFAULT_BUDGET_FRACTION;
@@ -84441,7 +84459,7 @@ function buildSkillOverridesCheck(settingsPath, read) {
84441
84459
  if (!read.settings || !Object.prototype.hasOwnProperty.call(read.settings, "skillOverrides")) {
84442
84460
  return pass("ck-skill-overrides-policy", "Skill Overrides Policy", "No skillOverrides configured");
84443
84461
  }
84444
- return warn("ck-skill-overrides-policy", "Skill Overrides Policy", "Project settings contain skillOverrides", [{ id: "skillOverrides", description: "", file: settingsPath }], "Remove skillOverrides and manage listing pressure with skillListingBudgetFraction, skillListingMaxDescChars, and inventory cleanup.");
84462
+ return warn("ck-skill-overrides-policy", "Skill Overrides Policy", "Project settings contain skillOverrides", [{ id: "skillOverrides", description: "", whenToUse: "", file: settingsPath }], "Remove skillOverrides and manage listing pressure with skillListingBudgetFraction, skillListingMaxDescChars, and inventory cleanup.");
84445
84463
  }
84446
84464
  function buildUserInvocationCheck(activeSkills) {
84447
84465
  const disabled = activeSkills.filter((skill) => skill.userInvocable === false);
@@ -105178,6 +105196,21 @@ function isSyncContext(ctx) {
105178
105196
  }
105179
105197
 
105180
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
+ }
105181
105214
  async function handleSelection(ctx) {
105182
105215
  if (ctx.cancelled)
105183
105216
  return ctx;
@@ -105393,6 +105426,11 @@ async function handleSelection(ctx) {
105393
105426
  try {
105394
105427
  const confirmAdd = await ctx.prompts.confirm(`${existingKitsDisplay} already installed. Add ${kit.name} alongside?`);
105395
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)}`);
105396
105434
  logger.warning("Multi-kit installation cancelled by user");
105397
105435
  return { ...ctx, cancelled: true };
105398
105436
  }
@@ -111266,6 +111304,9 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
111266
111304
  remainingKits: []
111267
111305
  };
111268
111306
  const metadata = await ManifestWriter.readManifest(installation.path);
111307
+ if (kit && (!metadata || !getInstalledKits(metadata).includes(kit))) {
111308
+ return result;
111309
+ }
111269
111310
  const uninstallManifest = await ManifestWriter.getUninstallManifest(installation.path, kit);
111270
111311
  result.remainingKits = uninstallManifest.remainingKits;
111271
111312
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
@@ -111576,6 +111617,56 @@ async function promptScope(installations) {
111576
111617
  }
111577
111618
  return selected;
111578
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
+ }
111579
111670
  async function confirmUninstall(scope, kitLabel = "") {
111580
111671
  const scopeText = scope === "all" ? "all ClaudeKit installations" : scope === "local" ? "local ClaudeKit installation" : "global ClaudeKit installation";
111581
111672
  const confirmed = await se({
@@ -111634,7 +111725,7 @@ async function uninstallCommand(options2) {
111634
111725
  }
111635
111726
  scope = promptedScope;
111636
111727
  }
111637
- const installations = allInstallations.filter((i) => {
111728
+ let installations = allInstallations.filter((i) => {
111638
111729
  if (scope === "all")
111639
111730
  return true;
111640
111731
  return i.type === scope;
@@ -111644,16 +111735,41 @@ async function uninstallCommand(options2) {
111644
111735
  logger.info(`No ${scopeLabel} ClaudeKit installation found.`);
111645
111736
  return;
111646
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
+ }
111647
111763
  displayInstallations(installations, scope);
111648
- if (validOptions.kit) {
111649
- 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`));
111650
111766
  }
111651
111767
  if (validOptions.dryRun) {
111652
111768
  log.info(import_picocolors39.default.yellow("DRY RUN MODE - No files will be deleted"));
111653
111769
  await removeInstallations(installations, {
111654
111770
  dryRun: true,
111655
111771
  forceOverwrite: validOptions.forceOverwrite,
111656
- kit: validOptions.kit
111772
+ kit: kitToRemove
111657
111773
  });
111658
111774
  prompts.outro("Dry-run complete. No changes were made.");
111659
111775
  return;
@@ -111663,7 +111779,7 @@ async function uninstallCommand(options2) {
111663
111779
  ${import_picocolors39.default.yellow("User modifications will be permanently deleted!")}`);
111664
111780
  }
111665
111781
  if (!validOptions.yes) {
111666
- const kitLabel = validOptions.kit ? ` (${validOptions.kit} kit only)` : "";
111782
+ const kitLabel = kitToRemove ? ` (${kitToRemove} kit only)` : "";
111667
111783
  const confirmed = await confirmUninstall(scope, kitLabel);
111668
111784
  if (!confirmed) {
111669
111785
  logger.info("Uninstall cancelled.");
@@ -111673,10 +111789,10 @@ ${import_picocolors39.default.yellow("User modifications will be permanently del
111673
111789
  const results = await removeInstallations(installations, {
111674
111790
  dryRun: false,
111675
111791
  forceOverwrite: validOptions.forceOverwrite,
111676
- kit: validOptions.kit
111792
+ kit: kitToRemove
111677
111793
  });
111678
111794
  const hasProtectedFiles = results.some((result) => result.protectedTrackedPaths.length > 0);
111679
- const kitMsg = validOptions.kit ? ` (${validOptions.kit} kit)` : "";
111795
+ const kitMsg = kitToRemove ? ` (${kitToRemove} kit)` : "";
111680
111796
  if (hasProtectedFiles) {
111681
111797
  prompts.outro(`ClaudeKit${kitMsg} uninstall completed with preserved customizations. Use --force-overwrite for full removal.`);
111682
111798
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "4.0.0-dev.1",
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": {