@claude-collective/cli 0.13.4 → 0.21.0

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 (228) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/config/skills-matrix.yaml +180 -113
  3. package/config/stacks.yaml +6 -6
  4. package/dist/{chunk-K3NB6DSG.js → chunk-2LSGX6R4.js} +54 -114
  5. package/dist/chunk-2LSGX6R4.js.map +1 -0
  6. package/dist/chunk-2OKUEELH.js +32 -0
  7. package/dist/chunk-2OKUEELH.js.map +1 -0
  8. package/dist/{chunk-V46GGCCI.js → chunk-374JNMR6.js} +14 -96
  9. package/dist/chunk-374JNMR6.js.map +1 -0
  10. package/dist/chunk-3EHUF54X.js +133 -0
  11. package/dist/chunk-3EHUF54X.js.map +1 -0
  12. package/dist/{chunk-7Q44DMSP.js → chunk-3XR4PALU.js} +92 -145
  13. package/dist/chunk-3XR4PALU.js.map +1 -0
  14. package/dist/{chunk-IAUAQJQ2.js → chunk-5K2ZLUO5.js} +5 -5
  15. package/dist/{chunk-IAUAQJQ2.js.map → chunk-5K2ZLUO5.js.map} +1 -1
  16. package/dist/{chunk-ACNBKXXJ.js → chunk-5KXUDHAB.js} +8 -36
  17. package/dist/chunk-5KXUDHAB.js.map +1 -0
  18. package/dist/chunk-7SLV7CMF.js +615 -0
  19. package/dist/chunk-7SLV7CMF.js.map +1 -0
  20. package/dist/{chunk-CDX4W4DM.js → chunk-A46TPNBJ.js} +61 -32
  21. package/dist/chunk-A46TPNBJ.js.map +1 -0
  22. package/dist/{chunk-TKFPKEV3.js → chunk-AL74GBW4.js} +1 -1
  23. package/dist/chunk-AL74GBW4.js.map +1 -0
  24. package/dist/chunk-BQX23RBV.js +191 -0
  25. package/dist/chunk-BQX23RBV.js.map +1 -0
  26. package/dist/{chunk-IMDW5ZUP.js → chunk-CA4LH4LI.js} +5 -5
  27. package/dist/chunk-CA4LH4LI.js.map +1 -0
  28. package/dist/{chunk-D237EVNB.js → chunk-CBLPAMZO.js} +5 -8
  29. package/dist/chunk-CBLPAMZO.js.map +1 -0
  30. package/dist/{chunk-B7CCVP6Q.js → chunk-CKPQHGXR.js} +52 -274
  31. package/dist/chunk-CKPQHGXR.js.map +1 -0
  32. package/dist/{chunk-SVYPSDWY.js → chunk-CXOFOJCN.js} +6 -10
  33. package/dist/chunk-CXOFOJCN.js.map +1 -0
  34. package/dist/{chunk-UQTEPWU7.js → chunk-EHGD7HIE.js} +2 -6
  35. package/dist/chunk-EHGD7HIE.js.map +1 -0
  36. package/dist/{chunk-76DWXGQE.js → chunk-FJFEKPXF.js} +1 -1
  37. package/dist/chunk-FJFEKPXF.js.map +1 -0
  38. package/dist/{chunk-E3FJH4TF.js → chunk-HEOHU5EZ.js} +2 -13
  39. package/dist/chunk-HEOHU5EZ.js.map +1 -0
  40. package/dist/{chunk-JIPWV2FX.js → chunk-HGCBZUH5.js} +6 -27
  41. package/dist/chunk-HGCBZUH5.js.map +1 -0
  42. package/dist/{chunk-ED4E6Q2T.js → chunk-HPGFY5ZN.js} +4 -4
  43. package/dist/chunk-HPGFY5ZN.js.map +1 -0
  44. package/dist/chunk-INJ2EFRW.js +127 -0
  45. package/dist/chunk-INJ2EFRW.js.map +1 -0
  46. package/dist/{chunk-KAAEN2PO.js → chunk-IOBFMF6X.js} +6 -2
  47. package/dist/{chunk-KAAEN2PO.js.map → chunk-IOBFMF6X.js.map} +1 -1
  48. package/dist/{chunk-K7EVM5LY.js → chunk-KH3HA7J7.js} +8 -33
  49. package/dist/chunk-KH3HA7J7.js.map +1 -0
  50. package/dist/{chunk-4K4ZXQRM.js → chunk-N6JNE326.js} +38 -94
  51. package/dist/chunk-N6JNE326.js.map +1 -0
  52. package/dist/chunk-NAGU7TVZ.js +36 -0
  53. package/dist/chunk-NAGU7TVZ.js.map +1 -0
  54. package/dist/{chunk-Z7G4B5HJ.js → chunk-OQYYMQJR.js} +68 -142
  55. package/dist/chunk-OQYYMQJR.js.map +1 -0
  56. package/dist/{chunk-RFTSZDHV.js → chunk-PLZOUVDD.js} +159 -53
  57. package/dist/chunk-PLZOUVDD.js.map +1 -0
  58. package/dist/chunk-Q3J43SF3.js +21 -0
  59. package/dist/chunk-Q3J43SF3.js.map +1 -0
  60. package/dist/{chunk-3U3R4NCG.js → chunk-T25OEQFI.js} +6 -2
  61. package/dist/chunk-T25OEQFI.js.map +1 -0
  62. package/dist/chunk-UMORK7OK.js +29 -0
  63. package/dist/chunk-UMORK7OK.js.map +1 -0
  64. package/dist/{chunk-ZFPSUQOU.js → chunk-VFHWU7JU.js} +12 -121
  65. package/dist/chunk-VFHWU7JU.js.map +1 -0
  66. package/dist/{chunk-GDH553MV.js → chunk-VS4GVTZE.js} +3 -3
  67. package/dist/chunk-VS4GVTZE.js.map +1 -0
  68. package/dist/chunk-WFEFICFM.js +67 -0
  69. package/dist/chunk-WFEFICFM.js.map +1 -0
  70. package/dist/{chunk-P26A2K5N.js → chunk-WG6KIAPK.js} +6 -16
  71. package/dist/chunk-WG6KIAPK.js.map +1 -0
  72. package/dist/{chunk-X6QONICW.js → chunk-ZEI3ZUDU.js} +3 -7
  73. package/dist/chunk-ZEI3ZUDU.js.map +1 -0
  74. package/dist/chunk-ZNIDWLL5.js +68 -0
  75. package/dist/chunk-ZNIDWLL5.js.map +1 -0
  76. package/dist/chunk-ZSVMS677.js +45 -0
  77. package/dist/chunk-ZSVMS677.js.map +1 -0
  78. package/dist/cli/defaults/agent-mappings.yaml +13 -13
  79. package/dist/commands/build/marketplace.js +8 -14
  80. package/dist/commands/build/marketplace.js.map +1 -1
  81. package/dist/commands/build/plugins.js +10 -21
  82. package/dist/commands/build/plugins.js.map +1 -1
  83. package/dist/commands/build/stack.js +13 -18
  84. package/dist/commands/build/stack.js.map +1 -1
  85. package/dist/commands/compile.js +25 -40
  86. package/dist/commands/compile.js.map +1 -1
  87. package/dist/commands/config/get.js +7 -7
  88. package/dist/commands/config/get.js.map +1 -1
  89. package/dist/commands/config/index.js +6 -6
  90. package/dist/commands/config/index.js.map +1 -1
  91. package/dist/commands/config/path.js +5 -7
  92. package/dist/commands/config/path.js.map +1 -1
  93. package/dist/commands/config/set-project.js +8 -9
  94. package/dist/commands/config/set-project.js.map +1 -1
  95. package/dist/commands/config/show.js +5 -5
  96. package/dist/commands/config/unset-project.js +8 -9
  97. package/dist/commands/config/unset-project.js.map +1 -1
  98. package/dist/commands/diff.js +17 -40
  99. package/dist/commands/diff.js.map +1 -1
  100. package/dist/commands/doctor.js +14 -25
  101. package/dist/commands/doctor.js.map +1 -1
  102. package/dist/commands/edit.js +41 -54
  103. package/dist/commands/edit.js.map +1 -1
  104. package/dist/commands/eject.js +24 -44
  105. package/dist/commands/eject.js.map +1 -1
  106. package/dist/commands/import/skill.js +19 -39
  107. package/dist/commands/import/skill.js.map +1 -1
  108. package/dist/commands/info.js +10 -15
  109. package/dist/commands/info.js.map +1 -1
  110. package/dist/commands/init.js +452 -451
  111. package/dist/commands/init.js.map +1 -1
  112. package/dist/commands/list.js +85 -9
  113. package/dist/commands/list.js.map +1 -1
  114. package/dist/commands/new/agent.js +9 -10
  115. package/dist/commands/new/agent.js.map +1 -1
  116. package/dist/commands/new/skill.js +12 -16
  117. package/dist/commands/new/skill.js.map +1 -1
  118. package/dist/commands/outdated.js +12 -89
  119. package/dist/commands/outdated.js.map +1 -1
  120. package/dist/commands/search.js +12 -18
  121. package/dist/commands/search.js.map +1 -1
  122. package/dist/commands/uninstall.js +12 -21
  123. package/dist/commands/uninstall.js.map +1 -1
  124. package/dist/commands/update.js +26 -146
  125. package/dist/commands/update.js.map +1 -1
  126. package/dist/commands/validate.js +407 -15
  127. package/dist/commands/validate.js.map +1 -1
  128. package/dist/commands/version/bump.js +7 -23
  129. package/dist/commands/version/bump.js.map +1 -1
  130. package/dist/commands/version/index.js +6 -21
  131. package/dist/commands/version/index.js.map +1 -1
  132. package/dist/commands/version/set.js +6 -23
  133. package/dist/commands/version/set.js.map +1 -1
  134. package/dist/commands/version/show.js +6 -21
  135. package/dist/commands/version/show.js.map +1 -1
  136. package/dist/components/common/message.js +2 -6
  137. package/dist/components/common/message.js.map +1 -1
  138. package/dist/components/common/spinner.js.map +1 -1
  139. package/dist/components/skill-search/skill-search.js +1 -1
  140. package/dist/components/wizard/category-grid.js +1 -1
  141. package/dist/components/wizard/category-grid.test.js +20 -92
  142. package/dist/components/wizard/category-grid.test.js.map +1 -1
  143. package/dist/components/wizard/menu-item.js +9 -0
  144. package/dist/components/wizard/section-progress.js +1 -1
  145. package/dist/components/wizard/section-progress.test.js +13 -103
  146. package/dist/components/wizard/section-progress.test.js.map +1 -1
  147. package/dist/components/wizard/step-approach.js +5 -4
  148. package/dist/components/wizard/step-build.js +3 -4
  149. package/dist/components/wizard/step-build.test.js +81 -186
  150. package/dist/components/wizard/step-build.test.js.map +1 -1
  151. package/dist/components/wizard/step-confirm.js +1 -2
  152. package/dist/components/wizard/step-refine.js +1 -2
  153. package/dist/components/wizard/step-refine.test.js +6 -14
  154. package/dist/components/wizard/step-refine.test.js.map +1 -1
  155. package/dist/components/wizard/step-stack.js +5 -3
  156. package/dist/components/wizard/view-title.js +9 -0
  157. package/dist/components/wizard/wizard-layout.js +16 -0
  158. package/dist/components/wizard/wizard-layout.js.map +1 -0
  159. package/dist/components/wizard/wizard-tabs.js +1 -1
  160. package/dist/components/wizard/wizard.js +12 -13
  161. package/dist/config/skills-matrix.yaml +180 -113
  162. package/dist/config/stacks.yaml +6 -6
  163. package/dist/hooks/init.js +5 -7
  164. package/dist/hooks/init.js.map +1 -1
  165. package/dist/src/agents/developer/web-developer/examples.md +1 -6
  166. package/dist/src/agents/meta/documentor/workflow.md +1 -5
  167. package/dist/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
  168. package/dist/src/agents/tester/web-tester/output-format.md +1 -3
  169. package/dist/stores/wizard-store.js +2 -2
  170. package/dist/stores/wizard-store.test.js +60 -23
  171. package/dist/stores/wizard-store.test.js.map +1 -1
  172. package/package.json +1 -1
  173. package/src/agents/developer/web-developer/examples.md +1 -6
  174. package/src/agents/meta/documentor/workflow.md +1 -5
  175. package/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
  176. package/src/agents/tester/web-tester/output-format.md +1 -3
  177. package/dist/chunk-3U3R4NCG.js.map +0 -1
  178. package/dist/chunk-4K4ZXQRM.js.map +0 -1
  179. package/dist/chunk-76DWXGQE.js.map +0 -1
  180. package/dist/chunk-7Q44DMSP.js.map +0 -1
  181. package/dist/chunk-ACNBKXXJ.js.map +0 -1
  182. package/dist/chunk-B7CCVP6Q.js.map +0 -1
  183. package/dist/chunk-BDLUZVKU.js +0 -54
  184. package/dist/chunk-BDLUZVKU.js.map +0 -1
  185. package/dist/chunk-CDX4W4DM.js.map +0 -1
  186. package/dist/chunk-D237EVNB.js.map +0 -1
  187. package/dist/chunk-DRXPNNPB.js +0 -393
  188. package/dist/chunk-DRXPNNPB.js.map +0 -1
  189. package/dist/chunk-E3FJH4TF.js.map +0 -1
  190. package/dist/chunk-ED4E6Q2T.js.map +0 -1
  191. package/dist/chunk-GDH553MV.js.map +0 -1
  192. package/dist/chunk-HLJX2FTL.js +0 -95
  193. package/dist/chunk-HLJX2FTL.js.map +0 -1
  194. package/dist/chunk-I2DSLOXZ.js +0 -75
  195. package/dist/chunk-I2DSLOXZ.js.map +0 -1
  196. package/dist/chunk-I4TPKIYX.js +0 -493
  197. package/dist/chunk-I4TPKIYX.js.map +0 -1
  198. package/dist/chunk-IBE7JIAG.js +0 -129
  199. package/dist/chunk-IBE7JIAG.js.map +0 -1
  200. package/dist/chunk-IMDW5ZUP.js.map +0 -1
  201. package/dist/chunk-JIPWV2FX.js.map +0 -1
  202. package/dist/chunk-K3NB6DSG.js.map +0 -1
  203. package/dist/chunk-K7EVM5LY.js.map +0 -1
  204. package/dist/chunk-NDY25DTL.js +0 -453
  205. package/dist/chunk-NDY25DTL.js.map +0 -1
  206. package/dist/chunk-P26A2K5N.js.map +0 -1
  207. package/dist/chunk-RFTSZDHV.js.map +0 -1
  208. package/dist/chunk-SVYPSDWY.js.map +0 -1
  209. package/dist/chunk-TKFPKEV3.js.map +0 -1
  210. package/dist/chunk-UQTEPWU7.js.map +0 -1
  211. package/dist/chunk-V46GGCCI.js.map +0 -1
  212. package/dist/chunk-X6QONICW.js.map +0 -1
  213. package/dist/chunk-Y2LW7R3Y.js +0 -23
  214. package/dist/chunk-Y2LW7R3Y.js.map +0 -1
  215. package/dist/chunk-Z7G4B5HJ.js.map +0 -1
  216. package/dist/chunk-ZENYS6KW.js +0 -90
  217. package/dist/chunk-ZENYS6KW.js.map +0 -1
  218. package/dist/chunk-ZFPSUQOU.js.map +0 -1
  219. package/dist/commands/config/set.js +0 -61
  220. package/dist/commands/config/set.js.map +0 -1
  221. package/dist/commands/config/unset.js +0 -57
  222. package/dist/commands/config/unset.js.map +0 -1
  223. package/dist/commands/test-imports.js +0 -92
  224. package/dist/commands/test-imports.js.map +0 -1
  225. package/dist/components/wizard/step-stack-options.js +0 -11
  226. package/dist/components/wizard/wizard-footer.js +0 -9
  227. /package/dist/components/wizard/{step-stack-options.js.map → menu-item.js.map} +0 -0
  228. /package/dist/components/wizard/{wizard-footer.js.map → view-title.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/uninstall.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp } from \"ink\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command\";\nimport { Confirm } from \"../components/common/confirm\";\nimport { directoryExists, fileExists, remove } from \"../utils/fs\";\nimport { claudePluginUninstall, isClaudeCLIAvailable } from \"../utils/exec\";\nimport { getCollectivePluginDir } from \"../lib/plugin-finder\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\n\nconst PLUGIN_NAME = \"claude-collective\";\n\ninterface UninstallTarget {\n hasPlugin: boolean;\n hasLocalSkills: boolean;\n hasLocalAgents: boolean;\n hasLocalConfig: boolean;\n hasClaudeDir: boolean;\n hasClaudeSrcDir: boolean;\n pluginDir: string;\n skillsDir: string;\n agentsDir: string;\n configPath: string;\n claudeDir: string;\n claudeSrcDir: string;\n}\n\nasync function detectInstallation(\n projectDir: string,\n): Promise<UninstallTarget> {\n const pluginDir = getCollectivePluginDir(projectDir);\n const skillsDir = path.join(projectDir, CLAUDE_DIR, \"skills\");\n const agentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n const configPath = path.join(projectDir, CLAUDE_DIR, \"config.yaml\");\n const claudeDir = path.join(projectDir, CLAUDE_DIR);\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n const [\n hasPlugin,\n hasLocalSkills,\n hasLocalAgents,\n hasLocalConfig,\n hasClaudeDir,\n hasClaudeSrcDir,\n ] = await Promise.all([\n directoryExists(pluginDir),\n directoryExists(skillsDir),\n directoryExists(agentsDir),\n fileExists(configPath),\n directoryExists(claudeDir),\n directoryExists(claudeSrcDir),\n ]);\n\n return {\n hasPlugin,\n hasLocalSkills,\n hasLocalAgents,\n hasLocalConfig,\n hasClaudeDir,\n hasClaudeSrcDir,\n pluginDir,\n skillsDir,\n agentsDir,\n configPath,\n claudeDir,\n claudeSrcDir,\n };\n}\n\ninterface UninstallConfirmProps {\n target: UninstallTarget;\n uninstallPlugin: boolean;\n uninstallLocal: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nconst UninstallConfirm: React.FC<UninstallConfirmProps> = ({\n target,\n uninstallPlugin,\n uninstallLocal,\n onConfirm,\n onCancel,\n}) => {\n const { exit } = useApp();\n const hasPluginToRemove = uninstallPlugin && target.hasPlugin;\n const hasLocalToRemove =\n uninstallLocal && (target.hasClaudeDir || target.hasClaudeSrcDir);\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>The following will be removed:</Text>\n <Text> </Text>\n\n {hasPluginToRemove && (\n <Box flexDirection=\"column\">\n <Text color=\"red\"> Plugin:</Text>\n <Text dimColor> {target.pluginDir}</Text>\n </Box>\n )}\n\n {hasLocalToRemove && (\n <Box flexDirection=\"column\">\n <Text color=\"red\"> Local directories:</Text>\n {target.hasClaudeDir && <Text dimColor> {target.claudeDir}/</Text>}\n {target.hasClaudeSrcDir && (\n <Text dimColor> {target.claudeSrcDir}/</Text>\n )}\n </Box>\n )}\n\n <Text> </Text>\n <Confirm\n message=\"Are you sure you want to uninstall?\"\n onConfirm={() => {\n onConfirm();\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n defaultValue={false}\n />\n </Box>\n );\n};\n\nexport default class Uninstall extends BaseCommand {\n static summary = \"Remove Claude Collective from this project\";\n\n static description =\n \"Uninstall the Claude Collective plugin and/or local directories (.claude/ and .claude-src/). By default, removes everything.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --plugin\",\n \"<%= config.bin %> <%= command.id %> --local\",\n \"<%= config.bin %> <%= command.id %> --dry-run\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n plugin: Flags.boolean({\n description: \"Only uninstall the plugin (not local files)\",\n default: false,\n }),\n local: Flags.boolean({\n description: \"Only remove local files (not the plugin)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Uninstall);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(\"Claude Collective Uninstall\");\n this.log(\"\");\n\n if (flags[\"dry-run\"]) {\n this.log(\"[dry-run] Preview mode - no files will be removed\");\n this.log(\"\");\n }\n\n // Detect what's installed\n const target = await detectInstallation(projectDir);\n\n // Determine what to uninstall based on flags\n const uninstallPlugin = !flags.local;\n const uninstallLocal = !flags.plugin;\n\n // Check if there's anything to uninstall\n const hasPluginToRemove = uninstallPlugin && target.hasPlugin;\n const hasLocalToRemove =\n uninstallLocal && (target.hasClaudeDir || target.hasClaudeSrcDir);\n\n if (!hasPluginToRemove && !hasLocalToRemove) {\n this.warn(\"Nothing to uninstall.\");\n this.log(\"\");\n\n if (flags.plugin && !target.hasPlugin) {\n this.log(\"No plugin installation found.\");\n }\n if (flags.local && !target.hasClaudeDir && !target.hasClaudeSrcDir) {\n this.log(\"No local installation found.\");\n }\n if (!flags.plugin && !flags.local) {\n this.log(\"Claude Collective is not installed in this project.\");\n }\n\n this.log(\"\");\n this.log(\"No changes made.\");\n return;\n }\n\n // Show what will be removed and get confirmation (unless --yes or --dry-run)\n if (!flags.yes && !flags[\"dry-run\"]) {\n const confirmed = await new Promise<boolean>((resolve) => {\n const { waitUntilExit } = render(\n <UninstallConfirm\n target={target}\n uninstallPlugin={uninstallPlugin}\n uninstallLocal={uninstallLocal}\n onConfirm={() => resolve(true)}\n onCancel={() => resolve(false)}\n />,\n );\n\n waitUntilExit().catch(() => resolve(false));\n });\n\n if (!confirmed) {\n this.log(\"\");\n this.log(\"Uninstall cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n } else {\n // In dry-run or --yes mode, just show what will be removed\n this.log(\"The following will be removed:\");\n this.log(\"\");\n\n if (hasPluginToRemove) {\n this.log(\" Plugin:\");\n this.log(` ${target.pluginDir}`);\n }\n\n if (hasLocalToRemove) {\n this.log(\" Local directories:\");\n if (target.hasClaudeDir) {\n this.log(` ${target.claudeDir}/`);\n }\n if (target.hasClaudeSrcDir) {\n this.log(` ${target.claudeSrcDir}/`);\n }\n }\n\n this.log(\"\");\n }\n\n // Dry run - show what would happen\n if (flags[\"dry-run\"]) {\n if (hasPluginToRemove) {\n this.log(`[dry-run] Would uninstall plugin \"${PLUGIN_NAME}\"`);\n this.log(`[dry-run] Would remove ${target.pluginDir}`);\n }\n if (hasLocalToRemove) {\n if (target.hasClaudeDir) {\n this.log(`[dry-run] Would remove ${target.claudeDir}/`);\n }\n if (target.hasClaudeSrcDir) {\n this.log(`[dry-run] Would remove ${target.claudeSrcDir}/`);\n }\n }\n this.log(\"\");\n this.log(\"[dry-run] Preview complete - no files were removed\");\n this.log(\"\");\n return;\n }\n\n // Uninstall plugin\n if (hasPluginToRemove) {\n this.log(\"Uninstalling plugin...\");\n\n try {\n // Try to use claude CLI to uninstall (handles settings.json)\n const cliAvailable = await isClaudeCLIAvailable();\n if (cliAvailable) {\n await claudePluginUninstall(PLUGIN_NAME, \"project\", projectDir);\n }\n\n // Remove plugin directory\n await remove(target.pluginDir);\n\n this.logSuccess(\"Plugin uninstalled\");\n } catch (error) {\n this.log(\"Plugin uninstall failed\");\n this.error(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n { exit: EXIT_CODES.ERROR },\n );\n }\n }\n\n // Remove local directories\n if (hasLocalToRemove) {\n this.log(\"Removing local directories...\");\n\n try {\n const removed: string[] = [];\n\n if (target.hasClaudeDir) {\n await remove(target.claudeDir);\n removed.push(CLAUDE_DIR);\n }\n\n if (target.hasClaudeSrcDir) {\n await remove(target.claudeSrcDir);\n removed.push(CLAUDE_SRC_DIR);\n }\n\n this.logSuccess(\n `Removed ${removed.length} ${removed.length === 1 ? \"directory\" : \"directories\"}: ${removed.join(\", \")}`,\n );\n } catch (error) {\n this.log(\"Failed to remove local directories\");\n this.error(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n { exit: EXIT_CODES.ERROR },\n );\n }\n }\n\n this.log(\"\");\n this.log(\"Claude Collective has been uninstalled.\");\n\n this.log(\"\");\n this.logSuccess(\"Uninstall complete!\");\n this.log(\"\");\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/uninstall.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp } from \"ink\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command\";\nimport { Confirm } from \"../components/common/confirm\";\nimport { directoryExists, fileExists, remove } from \"../utils/fs\";\nimport { claudePluginUninstall, isClaudeCLIAvailable } from \"../utils/exec\";\nimport { getCollectivePluginDir } from \"../lib/plugin-finder\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\n\nconst PLUGIN_NAME = \"claude-collective\";\n\ninterface UninstallTarget {\n hasPlugin: boolean;\n hasLocalSkills: boolean;\n hasLocalAgents: boolean;\n hasLocalConfig: boolean;\n hasClaudeDir: boolean;\n hasClaudeSrcDir: boolean;\n pluginDir: string;\n skillsDir: string;\n agentsDir: string;\n configPath: string;\n claudeDir: string;\n claudeSrcDir: string;\n}\n\nasync function detectInstallation(projectDir: string): Promise<UninstallTarget> {\n const pluginDir = getCollectivePluginDir(projectDir);\n const skillsDir = path.join(projectDir, CLAUDE_DIR, \"skills\");\n const agentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n const configPath = path.join(projectDir, CLAUDE_DIR, \"config.yaml\");\n const claudeDir = path.join(projectDir, CLAUDE_DIR);\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n const [hasPlugin, hasLocalSkills, hasLocalAgents, hasLocalConfig, hasClaudeDir, hasClaudeSrcDir] =\n await Promise.all([\n directoryExists(pluginDir),\n directoryExists(skillsDir),\n directoryExists(agentsDir),\n fileExists(configPath),\n directoryExists(claudeDir),\n directoryExists(claudeSrcDir),\n ]);\n\n return {\n hasPlugin,\n hasLocalSkills,\n hasLocalAgents,\n hasLocalConfig,\n hasClaudeDir,\n hasClaudeSrcDir,\n pluginDir,\n skillsDir,\n agentsDir,\n configPath,\n claudeDir,\n claudeSrcDir,\n };\n}\n\ninterface UninstallConfirmProps {\n target: UninstallTarget;\n uninstallPlugin: boolean;\n uninstallLocal: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nconst UninstallConfirm: React.FC<UninstallConfirmProps> = ({\n target,\n uninstallPlugin,\n uninstallLocal,\n onConfirm,\n onCancel,\n}) => {\n const { exit } = useApp();\n const hasPluginToRemove = uninstallPlugin && target.hasPlugin;\n const hasLocalToRemove = uninstallLocal && (target.hasClaudeDir || target.hasClaudeSrcDir);\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>The following will be removed:</Text>\n <Text> </Text>\n\n {hasPluginToRemove && (\n <Box flexDirection=\"column\">\n <Text color=\"red\"> Plugin:</Text>\n <Text dimColor> {target.pluginDir}</Text>\n </Box>\n )}\n\n {hasLocalToRemove && (\n <Box flexDirection=\"column\">\n <Text color=\"red\"> Local directories:</Text>\n {target.hasClaudeDir && <Text dimColor> {target.claudeDir}/</Text>}\n {target.hasClaudeSrcDir && <Text dimColor> {target.claudeSrcDir}/</Text>}\n </Box>\n )}\n\n <Text> </Text>\n <Confirm\n message=\"Are you sure you want to uninstall?\"\n onConfirm={() => {\n onConfirm();\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n defaultValue={false}\n />\n </Box>\n );\n};\n\nexport default class Uninstall extends BaseCommand {\n static summary = \"Remove Claude Collective from this project\";\n\n static description =\n \"Uninstall the Claude Collective plugin and/or local directories (.claude/ and .claude-src/). By default, removes everything.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --plugin\",\n \"<%= config.bin %> <%= command.id %> --local\",\n \"<%= config.bin %> <%= command.id %> --dry-run\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n plugin: Flags.boolean({\n description: \"Only uninstall the plugin (not local files)\",\n default: false,\n }),\n local: Flags.boolean({\n description: \"Only remove local files (not the plugin)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Uninstall);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(\"Claude Collective Uninstall\");\n this.log(\"\");\n\n if (flags[\"dry-run\"]) {\n this.log(\"[dry-run] Preview mode - no files will be removed\");\n this.log(\"\");\n }\n\n // Detect what's installed\n const target = await detectInstallation(projectDir);\n\n // Determine what to uninstall based on flags\n const uninstallPlugin = !flags.local;\n const uninstallLocal = !flags.plugin;\n\n // Check if there's anything to uninstall\n const hasPluginToRemove = uninstallPlugin && target.hasPlugin;\n const hasLocalToRemove = uninstallLocal && (target.hasClaudeDir || target.hasClaudeSrcDir);\n\n if (!hasPluginToRemove && !hasLocalToRemove) {\n this.warn(\"Nothing to uninstall.\");\n this.log(\"\");\n\n if (flags.plugin && !target.hasPlugin) {\n this.log(\"No plugin installation found.\");\n }\n if (flags.local && !target.hasClaudeDir && !target.hasClaudeSrcDir) {\n this.log(\"No local installation found.\");\n }\n if (!flags.plugin && !flags.local) {\n this.log(\"Claude Collective is not installed in this project.\");\n }\n\n this.log(\"\");\n this.log(\"No changes made.\");\n return;\n }\n\n // Show what will be removed and get confirmation (unless --yes or --dry-run)\n if (!flags.yes && !flags[\"dry-run\"]) {\n const confirmed = await new Promise<boolean>((resolve) => {\n const { waitUntilExit } = render(\n <UninstallConfirm\n target={target}\n uninstallPlugin={uninstallPlugin}\n uninstallLocal={uninstallLocal}\n onConfirm={() => resolve(true)}\n onCancel={() => resolve(false)}\n />,\n );\n\n waitUntilExit().catch(() => resolve(false));\n });\n\n if (!confirmed) {\n this.log(\"\");\n this.log(\"Uninstall cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n } else {\n // In dry-run or --yes mode, just show what will be removed\n this.log(\"The following will be removed:\");\n this.log(\"\");\n\n if (hasPluginToRemove) {\n this.log(\" Plugin:\");\n this.log(` ${target.pluginDir}`);\n }\n\n if (hasLocalToRemove) {\n this.log(\" Local directories:\");\n if (target.hasClaudeDir) {\n this.log(` ${target.claudeDir}/`);\n }\n if (target.hasClaudeSrcDir) {\n this.log(` ${target.claudeSrcDir}/`);\n }\n }\n\n this.log(\"\");\n }\n\n // Dry run - show what would happen\n if (flags[\"dry-run\"]) {\n if (hasPluginToRemove) {\n this.log(`[dry-run] Would uninstall plugin \"${PLUGIN_NAME}\"`);\n this.log(`[dry-run] Would remove ${target.pluginDir}`);\n }\n if (hasLocalToRemove) {\n if (target.hasClaudeDir) {\n this.log(`[dry-run] Would remove ${target.claudeDir}/`);\n }\n if (target.hasClaudeSrcDir) {\n this.log(`[dry-run] Would remove ${target.claudeSrcDir}/`);\n }\n }\n this.log(\"\");\n this.log(\"[dry-run] Preview complete - no files were removed\");\n this.log(\"\");\n return;\n }\n\n // Uninstall plugin\n if (hasPluginToRemove) {\n this.log(\"Uninstalling plugin...\");\n\n try {\n // Try to use claude CLI to uninstall (handles settings.json)\n const cliAvailable = await isClaudeCLIAvailable();\n if (cliAvailable) {\n await claudePluginUninstall(PLUGIN_NAME, \"project\", projectDir);\n }\n\n // Remove plugin directory\n await remove(target.pluginDir);\n\n this.logSuccess(\"Plugin uninstalled\");\n } catch (error) {\n this.log(\"Plugin uninstall failed\");\n this.error(error instanceof Error ? error.message : \"Unknown error occurred\", {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n // Remove local directories\n if (hasLocalToRemove) {\n this.log(\"Removing local directories...\");\n\n try {\n const removed: string[] = [];\n\n if (target.hasClaudeDir) {\n await remove(target.claudeDir);\n removed.push(CLAUDE_DIR);\n }\n\n if (target.hasClaudeSrcDir) {\n await remove(target.claudeSrcDir);\n removed.push(CLAUDE_SRC_DIR);\n }\n\n this.logSuccess(\n `Removed ${removed.length} ${removed.length === 1 ? \"directory\" : \"directories\"}: ${removed.join(\", \")}`,\n );\n } catch (error) {\n this.log(\"Failed to remove local directories\");\n this.error(error instanceof Error ? error.message : \"Unknown error occurred\", {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n this.log(\"\");\n this.log(\"Claude Collective has been uninstalled.\");\n\n this.log(\"\");\n this.logSuccess(\"Uninstall complete!\");\n this.log(\"\");\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA,SAAS,aAAa;AACtB,SAAS,QAAQ,KAAK,MAAM,cAAc;AAC1C,OAAO,UAAU;AAiFX,cAMI,YANJ;AAxEN,IAAM,cAAc;AAiBpB,eAAe,mBAAmB,YAA8C;AAC9E,QAAM,YAAY,uBAAuB,UAAU;AACnD,QAAM,YAAY,KAAK,KAAK,YAAY,YAAY,QAAQ;AAC5D,QAAM,YAAY,KAAK,KAAK,YAAY,YAAY,QAAQ;AAC5D,QAAM,aAAa,KAAK,KAAK,YAAY,YAAY,aAAa;AAClE,QAAM,YAAY,KAAK,KAAK,YAAY,UAAU;AAClD,QAAM,eAAe,KAAK,KAAK,YAAY,cAAc;AAEzD,QAAM,CAAC,WAAW,gBAAgB,gBAAgB,gBAAgB,cAAc,eAAe,IAC7F,MAAM,QAAQ,IAAI;AAAA,IAChB,gBAAgB,SAAS;AAAA,IACzB,gBAAgB,SAAS;AAAA,IACzB,gBAAgB,SAAS;AAAA,IACzB,WAAW,UAAU;AAAA,IACrB,gBAAgB,SAAS;AAAA,IACzB,gBAAgB,YAAY;AAAA,EAC9B,CAAC;AAEH,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAUA,IAAM,mBAAoD,CAAC;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,KAAK,IAAI,OAAO;AACxB,QAAM,oBAAoB,mBAAmB,OAAO;AACpD,QAAM,mBAAmB,mBAAmB,OAAO,gBAAgB,OAAO;AAE1E,SACE,qBAAC,OAAI,eAAc,UACjB;AAAA,wBAAC,QAAK,MAAI,MAAC,4CAA8B;AAAA,IACzC,oBAAC,QAAK,eAAC;AAAA,IAEN,qBACC,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,QAAK,OAAM,OAAM,sBAAQ;AAAA,MAC1B,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAE,OAAO;AAAA,SAAU;AAAA,OACpC;AAAA,IAGD,oBACC,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,QAAK,OAAM,OAAM,iCAAmB;AAAA,MACpC,OAAO,gBAAgB,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAE,OAAO;AAAA,QAAU;AAAA,SAAC;AAAA,MAC1D,OAAO,mBAAmB,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAE,OAAO;AAAA,QAAa;AAAA,SAAC;AAAA,OACnE;AAAA,IAGF,oBAAC,QAAK,eAAC;AAAA,IACP;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,WAAW,MAAM;AACf,oBAAU;AACV,eAAK;AAAA,QACP;AAAA,QACA,UAAU,MAAM;AACd,mBAAS;AACT,eAAK;AAAA,QACP;AAAA,QACA,cAAc;AAAA;AAAA,IAChB;AAAA,KACF;AAEJ;AAEA,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EACjD,OAAO,UAAU;AAAA,EAEjB,OAAO,cACL;AAAA,EAEF,OAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,GAAG,YAAY;AAAA,IACf,KAAK,MAAM,QAAQ;AAAA,MACjB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,QAAQ;AAAA,MACpB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,OAAO,MAAM,QAAQ;AAAA,MACnB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,UAAS;AAC5C,UAAM,aAAa,QAAQ,IAAI;AAE/B,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,6BAA6B;AACtC,SAAK,IAAI,EAAE;AAEX,QAAI,MAAM,SAAS,GAAG;AACpB,WAAK,IAAI,mDAAmD;AAC5D,WAAK,IAAI,EAAE;AAAA,IACb;AAGA,UAAM,SAAS,MAAM,mBAAmB,UAAU;AAGlD,UAAM,kBAAkB,CAAC,MAAM;AAC/B,UAAM,iBAAiB,CAAC,MAAM;AAG9B,UAAM,oBAAoB,mBAAmB,OAAO;AACpD,UAAM,mBAAmB,mBAAmB,OAAO,gBAAgB,OAAO;AAE1E,QAAI,CAAC,qBAAqB,CAAC,kBAAkB;AAC3C,WAAK,KAAK,uBAAuB;AACjC,WAAK,IAAI,EAAE;AAEX,UAAI,MAAM,UAAU,CAAC,OAAO,WAAW;AACrC,aAAK,IAAI,+BAA+B;AAAA,MAC1C;AACA,UAAI,MAAM,SAAS,CAAC,OAAO,gBAAgB,CAAC,OAAO,iBAAiB;AAClE,aAAK,IAAI,8BAA8B;AAAA,MACzC;AACA,UAAI,CAAC,MAAM,UAAU,CAAC,MAAM,OAAO;AACjC,aAAK,IAAI,qDAAqD;AAAA,MAChE;AAEA,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,kBAAkB;AAC3B;AAAA,IACF;AAGA,QAAI,CAAC,MAAM,OAAO,CAAC,MAAM,SAAS,GAAG;AACnC,YAAM,YAAY,MAAM,IAAI,QAAiB,CAAC,YAAY;AACxD,cAAM,EAAE,cAAc,IAAI;AAAA,UACxB;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA,WAAW,MAAM,QAAQ,IAAI;AAAA,cAC7B,UAAU,MAAM,QAAQ,KAAK;AAAA;AAAA,UAC/B;AAAA,QACF;AAEA,sBAAc,EAAE,MAAM,MAAM,QAAQ,KAAK,CAAC;AAAA,MAC5C,CAAC;AAED,UAAI,CAAC,WAAW;AACd,aAAK,IAAI,EAAE;AACX,aAAK,IAAI,qBAAqB;AAC9B,aAAK,KAAK,WAAW,SAAS;AAAA,MAChC;AAAA,IACF,OAAO;AAEL,WAAK,IAAI,gCAAgC;AACzC,WAAK,IAAI,EAAE;AAEX,UAAI,mBAAmB;AACrB,aAAK,IAAI,WAAW;AACpB,aAAK,IAAI,OAAO,OAAO,SAAS,EAAE;AAAA,MACpC;AAEA,UAAI,kBAAkB;AACpB,aAAK,IAAI,sBAAsB;AAC/B,YAAI,OAAO,cAAc;AACvB,eAAK,IAAI,OAAO,OAAO,SAAS,GAAG;AAAA,QACrC;AACA,YAAI,OAAO,iBAAiB;AAC1B,eAAK,IAAI,OAAO,OAAO,YAAY,GAAG;AAAA,QACxC;AAAA,MACF;AAEA,WAAK,IAAI,EAAE;AAAA,IACb;AAGA,QAAI,MAAM,SAAS,GAAG;AACpB,UAAI,mBAAmB;AACrB,aAAK,IAAI,qCAAqC,WAAW,GAAG;AAC5D,aAAK,IAAI,0BAA0B,OAAO,SAAS,EAAE;AAAA,MACvD;AACA,UAAI,kBAAkB;AACpB,YAAI,OAAO,cAAc;AACvB,eAAK,IAAI,0BAA0B,OAAO,SAAS,GAAG;AAAA,QACxD;AACA,YAAI,OAAO,iBAAiB;AAC1B,eAAK,IAAI,0BAA0B,OAAO,YAAY,GAAG;AAAA,QAC3D;AAAA,MACF;AACA,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,oDAAoD;AAC7D,WAAK,IAAI,EAAE;AACX;AAAA,IACF;AAGA,QAAI,mBAAmB;AACrB,WAAK,IAAI,wBAAwB;AAEjC,UAAI;AAEF,cAAM,eAAe,MAAM,qBAAqB;AAChD,YAAI,cAAc;AAChB,gBAAM,sBAAsB,aAAa,WAAW,UAAU;AAAA,QAChE;AAGA,cAAM,OAAO,OAAO,SAAS;AAE7B,aAAK,WAAW,oBAAoB;AAAA,MACtC,SAAS,OAAO;AACd,aAAK,IAAI,yBAAyB;AAClC,aAAK,MAAM,iBAAiB,QAAQ,MAAM,UAAU,0BAA0B;AAAA,UAC5E,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,kBAAkB;AACpB,WAAK,IAAI,+BAA+B;AAExC,UAAI;AACF,cAAM,UAAoB,CAAC;AAE3B,YAAI,OAAO,cAAc;AACvB,gBAAM,OAAO,OAAO,SAAS;AAC7B,kBAAQ,KAAK,UAAU;AAAA,QACzB;AAEA,YAAI,OAAO,iBAAiB;AAC1B,gBAAM,OAAO,OAAO,YAAY;AAChC,kBAAQ,KAAK,cAAc;AAAA,QAC7B;AAEA,aAAK;AAAA,UACH,WAAW,QAAQ,MAAM,IAAI,QAAQ,WAAW,IAAI,cAAc,aAAa,KAAK,QAAQ,KAAK,IAAI,CAAC;AAAA,QACxG;AAAA,MACF,SAAS,OAAO;AACd,aAAK,IAAI,oCAAoC;AAC7C,aAAK,MAAM,iBAAiB,QAAQ,MAAM,UAAU,0BAA0B;AAAA,UAC5E,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,yCAAyC;AAElD,SAAK,IAAI,EAAE;AACX,SAAK,WAAW,qBAAqB;AACrC,SAAK,IAAI,EAAE;AAAA,EACb;AACF;","names":[]}
@@ -4,38 +4,37 @@ import {
4
4
  } from "../chunk-RTE64SJA.js";
5
5
  import {
6
6
  recompileAgents
7
- } from "../chunk-4K4ZXQRM.js";
8
- import "../chunk-DRXPNNPB.js";
9
- import "../chunk-GDH553MV.js";
10
- import "../chunk-I4TPKIYX.js";
7
+ } from "../chunk-N6JNE326.js";
8
+ import "../chunk-7SLV7CMF.js";
9
+ import "../chunk-VS4GVTZE.js";
11
10
  import {
12
11
  getCollectivePluginDir
13
- } from "../chunk-ED4E6Q2T.js";
14
- import "../chunk-ZFPSUQOU.js";
12
+ } from "../chunk-HPGFY5ZN.js";
13
+ import "../chunk-VFHWU7JU.js";
15
14
  import {
16
- hashFile
17
- } from "../chunk-KAAEN2PO.js";
15
+ compareSkills,
16
+ injectForkedFromMetadata
17
+ } from "../chunk-INJ2EFRW.js";
18
+ import "../chunk-IOBFMF6X.js";
18
19
  import {
19
20
  loadSkillsMatrixFromSource
20
- } from "../chunk-RFTSZDHV.js";
21
- import "../chunk-B7CCVP6Q.js";
22
- import "../chunk-IMDW5ZUP.js";
21
+ } from "../chunk-PLZOUVDD.js";
22
+ import "../chunk-CKPQHGXR.js";
23
+ import "../chunk-CA4LH4LI.js";
24
+ import "../chunk-BQX23RBV.js";
23
25
  import {
24
26
  BaseCommand,
25
27
  EXIT_CODES
26
28
  } from "../chunk-EHS3TWWP.js";
27
- import "../chunk-V46GGCCI.js";
28
- import "../chunk-3U3R4NCG.js";
29
+ import "../chunk-374JNMR6.js";
30
+ import "../chunk-T25OEQFI.js";
29
31
  import {
30
32
  copy,
31
- fileExists,
32
- listDirectories,
33
- readFile,
34
- writeFile
35
- } from "../chunk-TKFPKEV3.js";
33
+ fileExists
34
+ } from "../chunk-AL74GBW4.js";
36
35
  import {
37
36
  LOCAL_SKILLS_PATH
38
- } from "../chunk-76DWXGQE.js";
37
+ } from "../chunk-FJFEKPXF.js";
39
38
  import {
40
39
  init_esm_shims
41
40
  } from "../chunk-DHET7RCE.js";
@@ -46,109 +45,7 @@ import { render } from "ink";
46
45
  import { Flags, Args } from "@oclif/core";
47
46
  import { printTable } from "@oclif/table";
48
47
  import path from "path";
49
- import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
50
48
  import { jsx } from "react/jsx-runtime";
51
- async function readForkedFromMetadata(skillDir) {
52
- const metadataPath = path.join(skillDir, "metadata.yaml");
53
- if (!await fileExists(metadataPath)) {
54
- return null;
55
- }
56
- const content = await readFile(metadataPath);
57
- const metadata = parseYaml(content);
58
- return metadata.forked_from ?? null;
59
- }
60
- async function getLocalSkillsWithMetadata(projectDir) {
61
- const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);
62
- const result = /* @__PURE__ */ new Map();
63
- if (!await fileExists(localSkillsPath)) {
64
- return result;
65
- }
66
- const skillDirs = await listDirectories(localSkillsPath);
67
- for (const dirName of skillDirs) {
68
- const skillDir = path.join(localSkillsPath, dirName);
69
- const forkedFrom = await readForkedFromMetadata(skillDir);
70
- const skillId = forkedFrom?.skill_id ?? dirName;
71
- result.set(skillId, { dirName, forkedFrom });
72
- }
73
- return result;
74
- }
75
- async function computeSourceHash(sourcePath, skillPath) {
76
- const skillMdPath = path.join(sourcePath, "src", skillPath, "SKILL.md");
77
- if (!await fileExists(skillMdPath)) {
78
- return null;
79
- }
80
- return hashFile(skillMdPath);
81
- }
82
- function getCurrentDate() {
83
- return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
84
- }
85
- async function compareSkills(projectDir, sourcePath, sourceSkills) {
86
- const results = [];
87
- const localSkills = await getLocalSkillsWithMetadata(projectDir);
88
- for (const [skillId, { dirName, forkedFrom }] of localSkills) {
89
- if (!forkedFrom) {
90
- results.push({
91
- id: skillId,
92
- localHash: null,
93
- sourceHash: null,
94
- status: "local-only",
95
- dirName
96
- });
97
- continue;
98
- }
99
- const localHash = forkedFrom.content_hash;
100
- const sourceSkill = sourceSkills[forkedFrom.skill_id];
101
- if (!sourceSkill) {
102
- results.push({
103
- id: forkedFrom.skill_id,
104
- localHash,
105
- sourceHash: null,
106
- status: "local-only",
107
- dirName
108
- });
109
- continue;
110
- }
111
- const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);
112
- if (sourceHash === null) {
113
- results.push({
114
- id: forkedFrom.skill_id,
115
- localHash,
116
- sourceHash: null,
117
- status: "local-only",
118
- dirName
119
- });
120
- continue;
121
- }
122
- const status = localHash === sourceHash ? "current" : "outdated";
123
- results.push({
124
- id: forkedFrom.skill_id,
125
- localHash,
126
- sourceHash,
127
- status,
128
- dirName,
129
- sourcePath: sourceSkill.path
130
- });
131
- }
132
- results.sort((a, b) => a.id.localeCompare(b.id));
133
- return results;
134
- }
135
- async function updateForkedFromMetadata(skillDir, skillId, contentHash) {
136
- const metadataPath = path.join(skillDir, "metadata.yaml");
137
- const rawContent = await readFile(metadataPath);
138
- const lines = rawContent.split("\n");
139
- let yamlContent = rawContent;
140
- if (lines[0]?.startsWith("# yaml-language-server:")) {
141
- yamlContent = lines.slice(1).join("\n");
142
- }
143
- const metadata = parseYaml(yamlContent);
144
- metadata.forked_from = {
145
- skill_id: skillId,
146
- content_hash: contentHash,
147
- date: getCurrentDate()
148
- };
149
- const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });
150
- await writeFile(metadataPath, newYamlContent);
151
- }
152
49
  async function updateSkill(skill, projectDir, sourceResult) {
153
50
  if (!skill.sourcePath || !skill.sourceHash) {
154
51
  return { success: false, newHash: null, error: "No source path available" };
@@ -158,7 +55,7 @@ async function updateSkill(skill, projectDir, sourceResult) {
158
55
  const srcPath = path.join(sourceResult.sourcePath, "src", skill.sourcePath);
159
56
  try {
160
57
  await copy(srcPath, destPath);
161
- await updateForkedFromMetadata(destPath, skill.id, skill.sourceHash);
58
+ await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);
162
59
  return { success: true, newHash: skill.sourceHash };
163
60
  } catch (error) {
164
61
  return {
@@ -176,9 +73,7 @@ function findSkillByPartialMatch(skillName, results) {
176
73
  return nameWithoutAuthor === skillName.toLowerCase();
177
74
  });
178
75
  if (partial) return partial;
179
- const byDir = results.find(
180
- (r) => r.dirName.toLowerCase() === skillName.toLowerCase()
181
- );
76
+ const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());
182
77
  if (byDir) return byDir;
183
78
  return null;
184
79
  }
@@ -190,10 +85,7 @@ function findSimilarSkills(skillName, results) {
190
85
  return name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(" ")[0]);
191
86
  }).map((r) => r.id).slice(0, 3);
192
87
  }
193
- var UpdateConfirm = ({
194
- onConfirm,
195
- onCancel
196
- }) => {
88
+ var UpdateConfirm = ({ onConfirm, onCancel }) => {
197
89
  return /* @__PURE__ */ jsx(
198
90
  Confirm,
199
91
  {
@@ -251,18 +143,12 @@ var Update = class _Update extends BaseCommand {
251
143
  `Loaded from ${sourceResult.isLocal ? "local" : "remote"}: ${sourceResult.sourcePath}`
252
144
  );
253
145
  const sourceSkills = {};
254
- for (const [skillId, skill] of Object.entries(
255
- sourceResult.matrix.skills
256
- )) {
146
+ for (const [skillId, skill] of Object.entries(sourceResult.matrix.skills)) {
257
147
  if (!skill.local) {
258
148
  sourceSkills[skillId] = { path: skill.path };
259
149
  }
260
150
  }
261
- const allResults = await compareSkills(
262
- projectDir,
263
- sourceResult.sourcePath,
264
- sourceSkills
265
- );
151
+ const allResults = await compareSkills(projectDir, sourceResult.sourcePath, sourceSkills);
266
152
  let outdatedSkills = allResults.filter((r) => r.status === "outdated");
267
153
  if (args.skill) {
268
154
  const foundSkill = findSkillByPartialMatch(args.skill, allResults);
@@ -278,9 +164,7 @@ var Update = class _Update extends BaseCommand {
278
164
  }
279
165
  this.log("");
280
166
  }
281
- this.log(
282
- `Run \`cc search ${args.skill}\` to search available skills.`
283
- );
167
+ this.log(`Run \`cc search ${args.skill}\` to search available skills.`);
284
168
  this.log("");
285
169
  this.error("Skill not found", { exit: EXIT_CODES.ERROR });
286
170
  }
@@ -295,9 +179,7 @@ var Update = class _Update extends BaseCommand {
295
179
  }
296
180
  if (foundSkill.status === "local-only") {
297
181
  this.log("");
298
- this.log(
299
- `Skill "${foundSkill.id}" is a local-only skill (not forked from source).`
300
- );
182
+ this.log(`Skill "${foundSkill.id}" is a local-only skill (not forked from source).`);
301
183
  this.log("Cannot update local-only skills.");
302
184
  this.log("");
303
185
  return;
@@ -404,9 +286,7 @@ var Update = class _Update extends BaseCommand {
404
286
  this.log("");
405
287
  if (failed.length === 0) {
406
288
  const agentMsg = recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : "";
407
- this.logSuccess(
408
- `Update complete! ${updated.length} skill(s) updated${agentMsg}.`
409
- );
289
+ this.logSuccess(`Update complete! ${updated.length} skill(s) updated${agentMsg}.`);
410
290
  } else {
411
291
  this.warn(
412
292
  `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { render } from \"ink\";\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport {\n loadSkillsMatrixFromSource,\n type SourceLoadResult,\n} from \"../lib/source-loader.js\";\nimport { hashFile } from \"../lib/versioning.js\";\nimport { recompileAgents } from \"../lib/agent-recompiler.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n fileExists,\n readFile,\n writeFile,\n listDirectories,\n copy,\n} from \"../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { getCollectivePluginDir } from \"../lib/plugin-finder.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\n/**\n * ForkedFrom metadata stored in local skill's metadata.yaml\n */\ninterface ForkedFromMetadata {\n skill_id: string;\n content_hash: string;\n date: string;\n}\n\n/**\n * Local skill metadata structure\n */\ninterface LocalSkillMetadata {\n forked_from?: ForkedFromMetadata;\n [key: string]: unknown;\n}\n\n/**\n * Result of comparing a local skill to its source\n */\ninterface SkillComparisonResult {\n id: string;\n localHash: string | null;\n sourceHash: string | null;\n status: \"current\" | \"outdated\" | \"local-only\";\n dirName: string;\n sourcePath?: string;\n}\n\n/**\n * Read forked_from metadata from a local skill's metadata.yaml\n */\nasync function readForkedFromMetadata(\n skillDir: string,\n): Promise<ForkedFromMetadata | null> {\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const metadata = parseYaml(content) as LocalSkillMetadata;\n\n return metadata.forked_from ?? null;\n}\n\n/**\n * Get local skills with their forked_from metadata\n */\nasync function getLocalSkillsWithMetadata(\n projectDir: string,\n): Promise<\n Map<string, { dirName: string; forkedFrom: ForkedFromMetadata | null }>\n> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const result = new Map<\n string,\n { dirName: string; forkedFrom: ForkedFromMetadata | null }\n >();\n\n if (!(await fileExists(localSkillsPath))) {\n return result;\n }\n\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const dirName of skillDirs) {\n const skillDir = path.join(localSkillsPath, dirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n // Use the skill_id from forked_from if available, otherwise use directory name\n const skillId = forkedFrom?.skill_id ?? dirName;\n\n result.set(skillId, { dirName, forkedFrom });\n }\n\n return result;\n}\n\n/**\n * Compute source hash for a skill's SKILL.md file\n */\nasync function computeSourceHash(\n sourcePath: string,\n skillPath: string,\n): Promise<string | null> {\n const skillMdPath = path.join(sourcePath, \"src\", skillPath, \"SKILL.md\");\n\n if (!(await fileExists(skillMdPath))) {\n return null;\n }\n\n return hashFile(skillMdPath);\n}\n\n/**\n * Get the current date in ISO format (YYYY-MM-DD)\n */\nfunction getCurrentDate(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\n/**\n * Compare local skills against source and determine status\n */\nasync function compareSkills(\n projectDir: string,\n sourcePath: string,\n sourceSkills: Record<string, { path: string }>,\n): Promise<SkillComparisonResult[]> {\n const results: SkillComparisonResult[] = [];\n const localSkills = await getLocalSkillsWithMetadata(projectDir);\n\n for (const [skillId, { dirName, forkedFrom }] of localSkills) {\n if (!forkedFrom) {\n // Local-only skill (no forked_from metadata)\n results.push({\n id: skillId,\n localHash: null,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const localHash = forkedFrom.content_hash;\n const sourceSkill = sourceSkills[forkedFrom.skill_id];\n\n if (!sourceSkill) {\n // Skill was forked from a source that no longer exists\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);\n\n if (sourceHash === null) {\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const status = localHash === sourceHash ? \"current\" : \"outdated\";\n\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash,\n status,\n dirName,\n sourcePath: sourceSkill.path,\n });\n }\n\n // Sort results by skill ID\n results.sort((a, b) => a.id.localeCompare(b.id));\n\n return results;\n}\n\n/**\n * Update forked_from metadata in a skill's metadata.yaml\n */\nasync function updateForkedFromMetadata(\n skillDir: string,\n skillId: string,\n contentHash: string,\n): Promise<void> {\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n const rawContent = await readFile(metadataPath);\n\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const metadata = parseYaml(yamlContent) as LocalSkillMetadata;\n\n metadata.forked_from = {\n skill_id: skillId,\n content_hash: contentHash,\n date: getCurrentDate(),\n };\n\n const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataPath, newYamlContent);\n}\n\n/**\n * Update a single skill from source\n */\nasync function updateSkill(\n skill: SkillComparisonResult,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<{ success: boolean; newHash: string | null; error?: string }> {\n if (!skill.sourcePath || !skill.sourceHash) {\n return { success: false, newHash: null, error: \"No source path available\" };\n }\n\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n // Copy skill files from source to local\n await copy(srcPath, destPath);\n\n // Update forked_from metadata\n await updateForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n\n return { success: true, newHash: skill.sourceHash };\n } catch (error) {\n return {\n success: false,\n newHash: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Find a skill by partial name match\n */\nfunction findSkillByPartialMatch(\n skillName: string,\n results: SkillComparisonResult[],\n): SkillComparisonResult | null {\n // Exact match first\n const exact = results.find((r) => r.id === skillName);\n if (exact) return exact;\n\n // Partial match (skill name without author)\n const partial = results.find((r) => {\n const nameWithoutAuthor = r.id.replace(/\\s*\\(@\\w+\\)$/, \"\").toLowerCase();\n return nameWithoutAuthor === skillName.toLowerCase();\n });\n if (partial) return partial;\n\n // Directory name match\n const byDir = results.find(\n (r) => r.dirName.toLowerCase() === skillName.toLowerCase(),\n );\n if (byDir) return byDir;\n\n return null;\n}\n\n/**\n * Find similar skill names for suggestions\n */\nfunction findSimilarSkills(\n skillName: string,\n results: SkillComparisonResult[],\n): string[] {\n const lowered = skillName.toLowerCase();\n return results\n .filter((r) => {\n const name = r.id.toLowerCase();\n const dir = r.dirName.toLowerCase();\n return (\n name.includes(lowered) ||\n dir.includes(lowered) ||\n lowered.includes(name.split(\" \")[0])\n );\n })\n .map((r) => r.id)\n .slice(0, 3);\n}\n\n/**\n * Confirmation component for update operation\n */\ninterface UpdateConfirmProps {\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({\n onConfirm,\n onCancel,\n}) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n // Check if local skills directory exists\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n this.warn(\"No local skills found. Run `cc init` or `cc edit` first.\");\n return;\n }\n\n this.log(\"Loading skills...\");\n\n const sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n // Build source skills map for lookup\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(\n sourceResult.matrix.skills,\n )) {\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Compare local skills against source\n const allResults = await compareSkills(\n projectDir,\n sourceResult.sourcePath,\n sourceSkills,\n );\n\n // Filter to just outdated skills\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n // Handle specific skill argument\n if (args.skill) {\n const foundSkill = findSkillByPartialMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n const similar = findSimilarSkills(args.skill, allResults);\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(\n `Run \\`cc search ${args.skill}\\` to search available skills.`,\n );\n this.log(\"\");\n this.error(\"Skill not found\", { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(\n `Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`,\n );\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n // Only update this specific skill\n outdatedSkills = [foundSkill];\n }\n\n // Check if there are any outdated skills\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(\"All skills are up to date.\");\n this.log(\"\");\n return;\n }\n\n // Show what will be updated\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n // Confirm unless --yes flag\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(\"No changes made.\");\n return;\n }\n }\n\n this.log(\"\");\n\n // Update each skill\n const updated: string[] = [];\n const failed: string[] = [];\n\n for (const skill of outdatedSkills) {\n this.log(`Updating ${skill.id}...`);\n\n const result = await updateSkill(skill, projectDir, sourceResult);\n\n if (result.success) {\n this.log(` Updated ${skill.id}`);\n updated.push(skill.id);\n } else {\n this.log(` Failed to update ${skill.id}: ${result.error}`);\n failed.push(skill.id);\n }\n }\n\n // Recompile agents if needed\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updated.length > 0) {\n this.log(\"\");\n this.log(\"Recompiling agents...\");\n\n try {\n const pluginDir = getCollectivePluginDir(projectDir);\n const recompileResult = await recompileAgents({\n pluginDir,\n sourcePath: sourceResult.sourcePath,\n projectDir,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(\"No agents to recompile\");\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(\n `Could not recompile agents: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Final summary\n this.log(\"\");\n if (failed.length === 0) {\n const agentMsg =\n recompiledAgents.length > 0\n ? `, ${recompiledAgents.length} agent(s) recompiled`\n : \"\";\n this.logSuccess(\n `Update complete! ${updated.length} skill(s) updated${agentMsg}.`,\n );\n } else {\n this.warn(\n `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`,\n );\n }\n this.log(\"\");\n\n if (failed.length > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React from \"react\";\nimport { render } from \"ink\";\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/source-loader.js\";\nimport { recompileAgents } from \"../lib/agent-recompiler.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n compareSkills,\n injectForkedFromMetadata,\n type SkillComparisonResult,\n} from \"../lib/skill-metadata.js\";\nimport { fileExists, copy } from \"../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { getCollectivePluginDir } from \"../lib/plugin-finder.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\n/**\n * Update a single skill from source\n */\nasync function updateSkill(\n skill: SkillComparisonResult,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<{ success: boolean; newHash: string | null; error?: string }> {\n if (!skill.sourcePath || !skill.sourceHash) {\n return { success: false, newHash: null, error: \"No source path available\" };\n }\n\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n // Copy skill files from source to local\n await copy(srcPath, destPath);\n\n // Update forked_from metadata\n await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n\n return { success: true, newHash: skill.sourceHash };\n } catch (error) {\n return {\n success: false,\n newHash: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Find a skill by partial name match\n */\nfunction findSkillByPartialMatch(\n skillName: string,\n results: SkillComparisonResult[],\n): SkillComparisonResult | null {\n // Exact match first\n const exact = results.find((r) => r.id === skillName);\n if (exact) return exact;\n\n // Partial match (skill name without author)\n const partial = results.find((r) => {\n const nameWithoutAuthor = r.id.replace(/\\s*\\(@\\w+\\)$/, \"\").toLowerCase();\n return nameWithoutAuthor === skillName.toLowerCase();\n });\n if (partial) return partial;\n\n // Directory name match\n const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());\n if (byDir) return byDir;\n\n return null;\n}\n\n/**\n * Find similar skill names for suggestions\n */\nfunction findSimilarSkills(skillName: string, results: SkillComparisonResult[]): string[] {\n const lowered = skillName.toLowerCase();\n return results\n .filter((r) => {\n const name = r.id.toLowerCase();\n const dir = r.dirName.toLowerCase();\n return (\n name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(\" \")[0])\n );\n })\n .map((r) => r.id)\n .slice(0, 3);\n}\n\n/**\n * Confirmation component for update operation\n */\ninterface UpdateConfirmProps {\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({ onConfirm, onCancel }) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n // Check if local skills directory exists\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n this.warn(\"No local skills found. Run `cc init` or `cc edit` first.\");\n return;\n }\n\n this.log(\"Loading skills...\");\n\n const sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n // Build source skills map for lookup\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(sourceResult.matrix.skills)) {\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Compare local skills against source\n const allResults = await compareSkills(projectDir, sourceResult.sourcePath, sourceSkills);\n\n // Filter to just outdated skills\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n // Handle specific skill argument\n if (args.skill) {\n const foundSkill = findSkillByPartialMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n const similar = findSimilarSkills(args.skill, allResults);\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(`Run \\`cc search ${args.skill}\\` to search available skills.`);\n this.log(\"\");\n this.error(\"Skill not found\", { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`);\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n // Only update this specific skill\n outdatedSkills = [foundSkill];\n }\n\n // Check if there are any outdated skills\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(\"All skills are up to date.\");\n this.log(\"\");\n return;\n }\n\n // Show what will be updated\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n // Confirm unless --yes flag\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(\"No changes made.\");\n return;\n }\n }\n\n this.log(\"\");\n\n // Update each skill\n const updated: string[] = [];\n const failed: string[] = [];\n\n for (const skill of outdatedSkills) {\n this.log(`Updating ${skill.id}...`);\n\n const result = await updateSkill(skill, projectDir, sourceResult);\n\n if (result.success) {\n this.log(` Updated ${skill.id}`);\n updated.push(skill.id);\n } else {\n this.log(` Failed to update ${skill.id}: ${result.error}`);\n failed.push(skill.id);\n }\n }\n\n // Recompile agents if needed\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updated.length > 0) {\n this.log(\"\");\n this.log(\"Recompiling agents...\");\n\n try {\n const pluginDir = getCollectivePluginDir(projectDir);\n const recompileResult = await recompileAgents({\n pluginDir,\n sourcePath: sourceResult.sourcePath,\n projectDir,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(\"No agents to recompile\");\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(\n `Could not recompile agents: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Final summary\n this.log(\"\");\n if (failed.length === 0) {\n const agentMsg =\n recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : \"\";\n this.logSuccess(`Update complete! ${updated.length} skill(s) updated${agentMsg}.`);\n } else {\n this.warn(\n `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`,\n );\n }\n this.log(\"\");\n\n if (failed.length > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}