@claude-collective/cli 0.21.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/CHANGELOG.md +174 -0
  2. package/README.md +41 -27
  3. package/config/skills-matrix.yaml +38 -37
  4. package/config/stacks.yaml +8 -14
  5. package/dist/{chunk-ZNIDWLL5.js → chunk-3X5D7RM5.js} +4 -3
  6. package/dist/chunk-3X5D7RM5.js.map +1 -0
  7. package/dist/chunk-4S4FCAA2.js +100 -0
  8. package/dist/chunk-4S4FCAA2.js.map +1 -0
  9. package/dist/chunk-4WGN6SUE.js +197 -0
  10. package/dist/chunk-4WGN6SUE.js.map +1 -0
  11. package/dist/{chunk-DHET7RCE.js → chunk-AWKZ5BDL.js} +9 -2
  12. package/dist/{chunk-DHET7RCE.js.map → chunk-AWKZ5BDL.js.map} +1 -1
  13. package/dist/{chunk-6Q3Y7KVB.js → chunk-DBRUQQUF.js} +8 -2
  14. package/dist/chunk-DBRUQQUF.js.map +1 -0
  15. package/dist/{chunk-OQYYMQJR.js → chunk-ETCVEV3S.js} +8 -11
  16. package/dist/chunk-ETCVEV3S.js.map +1 -0
  17. package/dist/{chunk-ZSVMS677.js → chunk-F4RD5FYM.js} +2 -2
  18. package/dist/chunk-F4RD5FYM.js.map +1 -0
  19. package/dist/{chunk-5KXUDHAB.js → chunk-GGFOD5PK.js} +6 -9
  20. package/dist/chunk-GGFOD5PK.js.map +1 -0
  21. package/dist/{chunk-UMORK7OK.js → chunk-H7SSBSPR.js} +2 -2
  22. package/dist/chunk-H7SSBSPR.js.map +1 -0
  23. package/dist/chunk-HWD32NP7.js +19 -0
  24. package/dist/chunk-HWD32NP7.js.map +1 -0
  25. package/dist/{chunk-HGCBZUH5.js → chunk-IAYAE6MG.js} +9 -10
  26. package/dist/chunk-IAYAE6MG.js.map +1 -0
  27. package/dist/{chunk-RTE64SJA.js → chunk-IXBCRT3F.js} +2 -2
  28. package/dist/chunk-IXBCRT3F.js.map +1 -0
  29. package/dist/{chunk-WFEFICFM.js → chunk-KWYO3M5Q.js} +5 -5
  30. package/dist/chunk-KWYO3M5Q.js.map +1 -0
  31. package/dist/{chunk-HEOHU5EZ.js → chunk-MCTSHLAF.js} +22 -11
  32. package/dist/chunk-MCTSHLAF.js.map +1 -0
  33. package/dist/chunk-MH66WDFV.js +251 -0
  34. package/dist/chunk-MH66WDFV.js.map +1 -0
  35. package/dist/{chunk-2LSGX6R4.js → chunk-MTPM7BX5.js} +83 -25
  36. package/dist/chunk-MTPM7BX5.js.map +1 -0
  37. package/dist/chunk-NQJ47R4N.js +1092 -0
  38. package/dist/chunk-NQJ47R4N.js.map +1 -0
  39. package/dist/chunk-NRC7XYCI.js +211 -0
  40. package/dist/chunk-NRC7XYCI.js.map +1 -0
  41. package/dist/{chunk-FJFEKPXF.js → chunk-O6ZTD7ZI.js} +14 -3
  42. package/dist/chunk-O6ZTD7ZI.js.map +1 -0
  43. package/dist/chunk-OBXAY23Y.js +56 -0
  44. package/dist/chunk-OBXAY23Y.js.map +1 -0
  45. package/dist/{chunk-XY3XDVMI.js → chunk-QR2EBWL2.js} +3 -3
  46. package/dist/{chunk-66UDJBF6.js → chunk-REJGRCVQ.js} +2 -2
  47. package/dist/{chunk-CBLPAMZO.js → chunk-TMED5DQ2.js} +68 -42
  48. package/dist/chunk-TMED5DQ2.js.map +1 -0
  49. package/dist/{chunk-Q3J43SF3.js → chunk-U7HFKR74.js} +2 -2
  50. package/dist/chunk-U7HFKR74.js.map +1 -0
  51. package/dist/{chunk-3EHUF54X.js → chunk-UEMRJI2K.js} +17 -4
  52. package/dist/chunk-UEMRJI2K.js.map +1 -0
  53. package/dist/{chunk-Z2CWURZ6.js → chunk-UNN7523L.js} +2 -2
  54. package/dist/chunk-V2ZIH7HV.js +29 -0
  55. package/dist/chunk-V2ZIH7HV.js.map +1 -0
  56. package/dist/{chunk-ZEI3ZUDU.js → chunk-VVYNZZUX.js} +7 -15
  57. package/dist/chunk-VVYNZZUX.js.map +1 -0
  58. package/dist/chunk-WXS4S3MA.js +220 -0
  59. package/dist/chunk-WXS4S3MA.js.map +1 -0
  60. package/dist/{chunk-A46TPNBJ.js → chunk-XENOESJZ.js} +7 -16
  61. package/dist/chunk-XENOESJZ.js.map +1 -0
  62. package/dist/chunk-YDBSSAJ6.js +4207 -0
  63. package/dist/chunk-YDBSSAJ6.js.map +1 -0
  64. package/dist/chunk-ZDREFYD2.js +696 -0
  65. package/dist/chunk-ZDREFYD2.js.map +1 -0
  66. package/dist/chunk-ZW2PELOH.js +197 -0
  67. package/dist/chunk-ZW2PELOH.js.map +1 -0
  68. package/dist/cli/defaults/agent-mappings.yaml +0 -1
  69. package/dist/commands/build/marketplace.js +15 -13
  70. package/dist/commands/build/marketplace.js.map +1 -1
  71. package/dist/commands/build/plugins.js +13 -229
  72. package/dist/commands/build/plugins.js.map +1 -1
  73. package/dist/commands/build/stack.js +11 -18
  74. package/dist/commands/build/stack.js.map +1 -1
  75. package/dist/commands/compile.js +36 -58
  76. package/dist/commands/compile.js.map +1 -1
  77. package/dist/commands/config/get.js +8 -8
  78. package/dist/commands/config/get.js.map +1 -1
  79. package/dist/commands/config/index.js +7 -7
  80. package/dist/commands/config/index.js.map +1 -1
  81. package/dist/commands/config/path.js +6 -6
  82. package/dist/commands/config/path.js.map +1 -1
  83. package/dist/commands/config/set-project.js +8 -8
  84. package/dist/commands/config/set-project.js.map +1 -1
  85. package/dist/commands/config/show.js +7 -7
  86. package/dist/commands/config/unset-project.js +8 -8
  87. package/dist/commands/config/unset-project.js.map +1 -1
  88. package/dist/commands/diff.js +10 -16
  89. package/dist/commands/diff.js.map +1 -1
  90. package/dist/commands/doctor.js +18 -51
  91. package/dist/commands/doctor.js.map +1 -1
  92. package/dist/commands/edit.js +87 -57
  93. package/dist/commands/edit.js.map +1 -1
  94. package/dist/commands/eject.js +17 -49
  95. package/dist/commands/eject.js.map +1 -1
  96. package/dist/commands/import/skill.js +26 -26
  97. package/dist/commands/import/skill.js.map +1 -1
  98. package/dist/commands/info.js +15 -17
  99. package/dist/commands/info.js.map +1 -1
  100. package/dist/commands/init.js +45 -722
  101. package/dist/commands/init.js.map +1 -1
  102. package/dist/commands/list.js +8 -87
  103. package/dist/commands/list.js.map +1 -1
  104. package/dist/commands/new/agent.js +8 -12
  105. package/dist/commands/new/agent.js.map +1 -1
  106. package/dist/commands/new/skill.js +6 -6
  107. package/dist/commands/new/skill.js.map +1 -1
  108. package/dist/commands/outdated.js +15 -19
  109. package/dist/commands/outdated.js.map +1 -1
  110. package/dist/commands/search.js +21 -34
  111. package/dist/commands/search.js.map +1 -1
  112. package/dist/commands/uninstall.js +15 -14
  113. package/dist/commands/uninstall.js.map +1 -1
  114. package/dist/commands/update.js +13 -24
  115. package/dist/commands/update.js.map +1 -1
  116. package/dist/commands/validate.js +44 -487
  117. package/dist/commands/validate.js.map +1 -1
  118. package/dist/commands/version/bump.js +11 -11
  119. package/dist/commands/version/bump.js.map +1 -1
  120. package/dist/commands/version/index.js +9 -10
  121. package/dist/commands/version/index.js.map +1 -1
  122. package/dist/commands/version/set.js +10 -8
  123. package/dist/commands/version/set.js.map +1 -1
  124. package/dist/commands/version/show.js +9 -10
  125. package/dist/commands/version/show.js.map +1 -1
  126. package/dist/components/common/confirm.js +2 -2
  127. package/dist/components/common/confirm.test.js +203 -0
  128. package/dist/components/common/confirm.test.js.map +1 -0
  129. package/dist/components/common/message.js +1 -1
  130. package/dist/components/common/spinner.js +1 -1
  131. package/dist/components/common/spinner.js.map +1 -1
  132. package/dist/components/skill-search/skill-search.js +3 -3
  133. package/dist/components/wizard/category-grid.js +2 -2
  134. package/dist/components/wizard/category-grid.test.js +132 -78
  135. package/dist/components/wizard/category-grid.test.js.map +1 -1
  136. package/dist/components/wizard/menu-item.js +2 -2
  137. package/dist/components/wizard/search-modal.js +9 -0
  138. package/dist/components/wizard/search-modal.js.map +1 -0
  139. package/dist/components/wizard/search-modal.test.js +216 -0
  140. package/dist/components/wizard/search-modal.test.js.map +1 -0
  141. package/dist/components/wizard/section-progress.js +2 -2
  142. package/dist/components/wizard/section-progress.test.js +4 -4
  143. package/dist/components/wizard/section-progress.test.js.map +1 -1
  144. package/dist/components/wizard/source-grid.js +10 -0
  145. package/dist/components/wizard/source-grid.js.map +1 -0
  146. package/dist/components/wizard/source-grid.test.js +500 -0
  147. package/dist/components/wizard/source-grid.test.js.map +1 -0
  148. package/dist/components/wizard/step-approach.js +7 -6
  149. package/dist/components/wizard/step-approach.test.js +115 -0
  150. package/dist/components/wizard/step-approach.test.js.map +1 -0
  151. package/dist/components/wizard/step-build.js +9 -4
  152. package/dist/components/wizard/step-build.test.js +103 -122
  153. package/dist/components/wizard/step-build.test.js.map +1 -1
  154. package/dist/components/wizard/step-confirm.js +3 -2
  155. package/dist/components/wizard/step-confirm.test.js +364 -0
  156. package/dist/components/wizard/step-confirm.test.js.map +1 -0
  157. package/dist/components/wizard/step-refine.js +2 -2
  158. package/dist/components/wizard/step-refine.test.js +19 -13
  159. package/dist/components/wizard/step-refine.test.js.map +1 -1
  160. package/dist/components/wizard/step-settings.js +14 -0
  161. package/dist/components/wizard/step-settings.js.map +1 -0
  162. package/dist/components/wizard/step-settings.test.js +240 -0
  163. package/dist/components/wizard/step-settings.test.js.map +1 -0
  164. package/dist/components/wizard/step-sources.js +17 -0
  165. package/dist/components/wizard/step-sources.js.map +1 -0
  166. package/dist/components/wizard/step-sources.test.js +290 -0
  167. package/dist/components/wizard/step-sources.test.js.map +1 -0
  168. package/dist/components/wizard/step-stack.js +7 -6
  169. package/dist/components/wizard/step-stack.test.js +344 -0
  170. package/dist/components/wizard/step-stack.test.js.map +1 -0
  171. package/dist/components/wizard/view-title.js +2 -2
  172. package/dist/components/wizard/wizard-layout.js +6 -5
  173. package/dist/components/wizard/wizard-tabs.js +2 -2
  174. package/dist/components/wizard/wizard-tabs.test.js +292 -0
  175. package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
  176. package/dist/components/wizard/wizard.js +22 -14
  177. package/dist/config/skills-matrix.yaml +38 -37
  178. package/dist/config/stacks.yaml +8 -14
  179. package/dist/hooks/init.js +5 -5
  180. package/dist/hooks/init.js.map +1 -1
  181. package/dist/index.js +1 -1
  182. package/dist/index.js.map +1 -1
  183. package/dist/{magic-string.es-RGXYGAW3.js → magic-string.es-PAH2SOTR.js} +2 -2
  184. package/dist/source-manager-DSYZEVGZ.js +16 -0
  185. package/dist/source-manager-DSYZEVGZ.js.map +1 -0
  186. package/dist/src/agents/developer/api-developer/agent.yaml +1 -1
  187. package/dist/src/agents/developer/cli-developer/agent.yaml +1 -1
  188. package/dist/src/agents/developer/web-architecture/agent.yaml +1 -1
  189. package/dist/src/agents/developer/web-developer/agent.yaml +1 -1
  190. package/dist/src/agents/meta/agent-summoner/agent.yaml +1 -1
  191. package/dist/src/agents/meta/documentor/agent.yaml +1 -1
  192. package/dist/src/agents/meta/skill-summoner/agent.yaml +1 -1
  193. package/dist/src/agents/migration/cli-migrator/agent.yaml +1 -1
  194. package/dist/src/agents/pattern/pattern-scout/agent.yaml +1 -1
  195. package/dist/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
  196. package/dist/src/agents/planning/web-pm/agent.yaml +1 -1
  197. package/dist/src/agents/researcher/api-researcher/agent.yaml +1 -1
  198. package/dist/src/agents/researcher/web-researcher/agent.yaml +1 -1
  199. package/dist/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
  200. package/dist/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
  201. package/dist/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
  202. package/dist/src/agents/tester/cli-tester/agent.yaml +1 -1
  203. package/dist/src/agents/tester/web-tester/agent.yaml +1 -1
  204. package/dist/stores/wizard-store.js +4 -3
  205. package/dist/stores/wizard-store.test.js +51 -82
  206. package/dist/stores/wizard-store.test.js.map +1 -1
  207. package/package.json +5 -3
  208. package/src/agents/developer/api-developer/agent.yaml +1 -1
  209. package/src/agents/developer/cli-developer/agent.yaml +1 -1
  210. package/src/agents/developer/web-architecture/agent.yaml +1 -1
  211. package/src/agents/developer/web-developer/agent.yaml +1 -1
  212. package/src/agents/meta/agent-summoner/agent.yaml +1 -1
  213. package/src/agents/meta/documentor/agent.yaml +1 -1
  214. package/src/agents/meta/skill-summoner/agent.yaml +1 -1
  215. package/src/agents/migration/cli-migrator/agent.yaml +1 -1
  216. package/src/agents/pattern/pattern-scout/agent.yaml +1 -1
  217. package/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
  218. package/src/agents/planning/web-pm/agent.yaml +1 -1
  219. package/src/agents/researcher/api-researcher/agent.yaml +1 -1
  220. package/src/agents/researcher/web-researcher/agent.yaml +1 -1
  221. package/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
  222. package/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
  223. package/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
  224. package/src/agents/tester/cli-tester/agent.yaml +1 -1
  225. package/src/agents/tester/web-tester/agent.yaml +1 -1
  226. package/dist/chunk-2LSGX6R4.js.map +0 -1
  227. package/dist/chunk-2OKUEELH.js +0 -32
  228. package/dist/chunk-2OKUEELH.js.map +0 -1
  229. package/dist/chunk-374JNMR6.js +0 -212
  230. package/dist/chunk-374JNMR6.js.map +0 -1
  231. package/dist/chunk-3EHUF54X.js.map +0 -1
  232. package/dist/chunk-3XR4PALU.js +0 -529
  233. package/dist/chunk-3XR4PALU.js.map +0 -1
  234. package/dist/chunk-5K2ZLUO5.js +0 -57
  235. package/dist/chunk-5K2ZLUO5.js.map +0 -1
  236. package/dist/chunk-5KXUDHAB.js.map +0 -1
  237. package/dist/chunk-6Q3Y7KVB.js.map +0 -1
  238. package/dist/chunk-7SLV7CMF.js +0 -615
  239. package/dist/chunk-7SLV7CMF.js.map +0 -1
  240. package/dist/chunk-A46TPNBJ.js.map +0 -1
  241. package/dist/chunk-AL74GBW4.js +0 -69
  242. package/dist/chunk-AL74GBW4.js.map +0 -1
  243. package/dist/chunk-BQX23RBV.js +0 -191
  244. package/dist/chunk-BQX23RBV.js.map +0 -1
  245. package/dist/chunk-CA4LH4LI.js +0 -132
  246. package/dist/chunk-CA4LH4LI.js.map +0 -1
  247. package/dist/chunk-CBLPAMZO.js.map +0 -1
  248. package/dist/chunk-CKPQHGXR.js +0 -417
  249. package/dist/chunk-CKPQHGXR.js.map +0 -1
  250. package/dist/chunk-CXOFOJCN.js +0 -80
  251. package/dist/chunk-CXOFOJCN.js.map +0 -1
  252. package/dist/chunk-EHGD7HIE.js +0 -104
  253. package/dist/chunk-EHGD7HIE.js.map +0 -1
  254. package/dist/chunk-EHS3TWWP.js +0 -95
  255. package/dist/chunk-EHS3TWWP.js.map +0 -1
  256. package/dist/chunk-FJFEKPXF.js.map +0 -1
  257. package/dist/chunk-HEOHU5EZ.js.map +0 -1
  258. package/dist/chunk-HGCBZUH5.js.map +0 -1
  259. package/dist/chunk-HPGFY5ZN.js +0 -114
  260. package/dist/chunk-HPGFY5ZN.js.map +0 -1
  261. package/dist/chunk-INJ2EFRW.js +0 -127
  262. package/dist/chunk-INJ2EFRW.js.map +0 -1
  263. package/dist/chunk-IOBFMF6X.js +0 -61
  264. package/dist/chunk-IOBFMF6X.js.map +0 -1
  265. package/dist/chunk-KH3HA7J7.js +0 -116
  266. package/dist/chunk-KH3HA7J7.js.map +0 -1
  267. package/dist/chunk-N6JNE326.js +0 -261
  268. package/dist/chunk-N6JNE326.js.map +0 -1
  269. package/dist/chunk-NAGU7TVZ.js +0 -36
  270. package/dist/chunk-NAGU7TVZ.js.map +0 -1
  271. package/dist/chunk-OQYYMQJR.js.map +0 -1
  272. package/dist/chunk-PLZOUVDD.js +0 -419
  273. package/dist/chunk-PLZOUVDD.js.map +0 -1
  274. package/dist/chunk-Q3J43SF3.js.map +0 -1
  275. package/dist/chunk-RTE64SJA.js.map +0 -1
  276. package/dist/chunk-T25OEQFI.js +0 -26
  277. package/dist/chunk-T25OEQFI.js.map +0 -1
  278. package/dist/chunk-UMORK7OK.js.map +0 -1
  279. package/dist/chunk-VFHWU7JU.js +0 -287
  280. package/dist/chunk-VFHWU7JU.js.map +0 -1
  281. package/dist/chunk-VS4GVTZE.js +0 -91
  282. package/dist/chunk-VS4GVTZE.js.map +0 -1
  283. package/dist/chunk-WFEFICFM.js.map +0 -1
  284. package/dist/chunk-WG6KIAPK.js +0 -54
  285. package/dist/chunk-WG6KIAPK.js.map +0 -1
  286. package/dist/chunk-ZEI3ZUDU.js.map +0 -1
  287. package/dist/chunk-ZNIDWLL5.js.map +0 -1
  288. package/dist/chunk-ZSVMS677.js.map +0 -1
  289. /package/dist/{chunk-XY3XDVMI.js.map → chunk-QR2EBWL2.js.map} +0 -0
  290. /package/dist/{chunk-66UDJBF6.js.map → chunk-REJGRCVQ.js.map} +0 -0
  291. /package/dist/{chunk-Z2CWURZ6.js.map → chunk-UNN7523L.js.map} +0 -0
  292. /package/dist/{magic-string.es-RGXYGAW3.js.map → magic-string.es-PAH2SOTR.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/edit.tsx"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { render } from \"ink\";\nimport React from \"react\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { Wizard, WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport { directoryExists, ensureDir, remove } from \"../utils/fs.js\";\nimport {\n getCollectivePluginDir,\n getPluginSkillsDir,\n getPluginSkillIds,\n} from \"../lib/plugin-finder.js\";\nimport { copySkillsToPluginFromSource } from \"../lib/skill-copier.js\";\nimport { recompileAgents } from \"../lib/agent-recompiler.js\";\nimport { bumpPluginVersion } from \"../lib/plugin-version.js\";\nimport { getAgentDefinitions } from \"../lib/agent-fetcher.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { detectInstallation } from \"../lib/installation.js\";\n\nexport default class Edit extends BaseCommand {\n static summary = \"Edit skills in the plugin\";\n static description = \"Modify the currently installed skills via interactive wizard\";\n\n static flags = {\n ...BaseCommand.baseFlags,\n refresh: Flags.boolean({\n description: \"Force refresh from remote sources\",\n default: false,\n }),\n \"agent-source\": Flags.string({\n description: \"Remote agent partials source (default: local CLI)\",\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Edit);\n\n // Detect installation mode\n const installation = await detectInstallation();\n\n if (!installation) {\n this.error(\"No installation found. Run 'cc init' first to set up Claude Collective.\", {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const pluginDir = getCollectivePluginDir();\n const pluginSkillsDir =\n installation.mode === \"local\" ? installation.skillsDir : getPluginSkillsDir(pluginDir);\n\n const modeLabel = installation.mode === \"local\" ? \"Local\" : \"Plugin\";\n this.log(`Edit ${modeLabel} Skills\\n`);\n\n // Load skills matrix\n this.log(\"Resolving marketplace source...\");\n let sourceResult;\n try {\n sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir: process.cwd(),\n forceRefresh: flags.refresh,\n });\n\n const sourceInfo = sourceResult.isLocal ? \"local\" : sourceResult.sourceConfig.sourceOrigin;\n this.log(\n `✓ Loaded ${Object.keys(sourceResult.matrix.skills).length} skills (${sourceInfo})\\n`,\n );\n } catch (error) {\n this.handleError(error);\n }\n\n // Load current skills\n this.log(\"Reading current skills...\");\n let currentSkillIds: string[];\n try {\n currentSkillIds = await getPluginSkillIds(pluginSkillsDir, sourceResult.matrix);\n this.log(`✓ Current plugin has ${currentSkillIds.length} skills\\n`);\n } catch (error) {\n this.handleError(error);\n }\n\n // Run wizard with initial skills\n let wizardResult: WizardResultV2 | null = null;\n\n const { waitUntilExit } = render(\n <Wizard\n matrix={sourceResult.matrix}\n version={this.config.version}\n initialSkills={currentSkillIds}\n onComplete={(result) => {\n // Wizard always returns WizardResultV2 in the current implementation\n wizardResult = result as WizardResultV2;\n }}\n onCancel={() => {\n this.log(\"\\nEdit cancelled\");\n }}\n />,\n );\n\n await waitUntilExit();\n\n // Cast to WizardResultV2 since that's what the current wizard implementation returns\n // Use non-null assertion here since we know the wizard has completed\n const result = wizardResult as WizardResultV2 | null;\n\n // Handle cancellation - use error() which throws and TypeScript understands\n if (!result || result.cancelled) {\n this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n }\n\n // Validate selection - use error() which throws and TypeScript understands\n if (!result.validation.valid) {\n const errorMessages = result.validation.errors.map((e) => e.message).join(\"\\n \");\n this.error(`Selection has validation errors:\\n ${errorMessages}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n // Calculate changes\n const addedSkills = result.selectedSkills.filter((id: string) => !currentSkillIds.includes(id));\n const removedSkills = currentSkillIds.filter((id) => !result.selectedSkills.includes(id));\n\n // Show warnings if any\n if (result.validation.warnings.length > 0) {\n this.log(\"\\nWarnings:\");\n for (const warning of result.validation.warnings) {\n this.warn(` ! ${warning.message}`);\n }\n this.log(\"\");\n }\n\n // Check if there are no changes\n if (addedSkills.length === 0 && removedSkills.length === 0) {\n this.log(\"No changes made.\");\n this.log(\"Plugin unchanged\\n\");\n return;\n }\n\n // Show changes\n this.log(\"\\nChanges:\");\n for (const skillId of addedSkills) {\n const skill = sourceResult.matrix.skills[skillId];\n this.log(` + ${skill?.name || skillId}`);\n }\n for (const skillId of removedSkills) {\n const skill = sourceResult.matrix.skills[skillId];\n this.log(` - ${skill?.name || skillId}`);\n }\n this.log(\"\");\n\n // Update plugin skills\n this.log(\"Updating plugin skills...\");\n try {\n if (await directoryExists(pluginSkillsDir)) {\n await remove(pluginSkillsDir);\n }\n await ensureDir(pluginSkillsDir);\n\n await copySkillsToPluginFromSource(\n result.selectedSkills,\n pluginDir,\n sourceResult.matrix,\n sourceResult,\n );\n this.log(`✓ Plugin updated with ${result.selectedSkills.length} skills\\n`);\n } catch (error) {\n this.handleError(error);\n }\n\n // Fetch agent partials\n let sourcePath: string;\n this.log(flags[\"agent-source\"] ? \"Fetching agent partials...\" : \"Loading agent partials...\");\n try {\n const agentDefs = await getAgentDefinitions(flags[\"agent-source\"], {\n forceRefresh: flags.refresh,\n });\n sourcePath = agentDefs.sourcePath;\n this.log(flags[\"agent-source\"] ? \"✓ Agent partials fetched\\n\" : \"✓ Agent partials loaded\\n\");\n } catch (error) {\n this.handleError(error);\n }\n\n // Recompile agents\n this.log(\"Recompiling agents...\");\n try {\n const recompileResult = await recompileAgents({\n pluginDir,\n sourcePath,\n });\n\n if (recompileResult.failed.length > 0) {\n this.log(\n `✓ Recompiled ${recompileResult.compiled.length} agents (${recompileResult.failed.length} failed)\\n`,\n );\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n } else if (recompileResult.compiled.length > 0) {\n this.log(`✓ Recompiled ${recompileResult.compiled.length} agents\\n`);\n } else {\n this.log(\"✓ No agents to recompile\\n\");\n }\n } catch (error) {\n this.warn(\n `Agent recompilation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n this.log(\"You can manually recompile with 'cc compile'.\\n\");\n }\n\n // Update plugin version\n this.log(\"Updating plugin version...\");\n try {\n const newVersion = await bumpPluginVersion(pluginDir, \"patch\");\n this.log(`✓ Version bumped to ${newVersion}\\n`);\n } catch (error) {\n this.handleError(error);\n }\n\n this.log(\n `\\n✓ Plugin updated! (${addedSkills.length} added, ${removedSkills.length} removed)\\n`,\n );\n }\n}\n"],"mappings":"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","names":["result"]}
1
+ {"version":3,"sources":["../../src/cli/commands/edit.tsx"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { render } from \"ink\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { Wizard, WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/loading/index.js\";\nimport { directoryExists, ensureDir, remove } from \"../utils/fs.js\";\nimport {\n getCollectivePluginDir,\n getPluginSkillsDir,\n getPluginSkillIds,\n bumpPluginVersion,\n} from \"../lib/plugins/index.js\";\nimport {\n copySkillsToPluginFromSource,\n archiveLocalSkill,\n restoreArchivedSkill,\n} from \"../lib/skills/index.js\";\nimport { recompileAgents, getAgentDefinitions } from \"../lib/agents/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { detectInstallation } from \"../lib/installation/index.js\";\nimport type { SkillId } from \"../types/index.js\";\nimport { typedEntries } from \"../utils/typed-object.js\";\n\nconst SOURCE_DISPLAY_NAMES: Record<string, string> = {\n public: \"Public\",\n local: \"Local\",\n};\n\nfunction formatSourceDisplayName(sourceName: string): string {\n return SOURCE_DISPLAY_NAMES[sourceName] ?? sourceName;\n}\n\nexport default class Edit extends BaseCommand {\n static summary = \"Edit skills in the plugin\";\n static description = \"Modify the currently installed skills via interactive wizard\";\n\n static flags = {\n ...BaseCommand.baseFlags,\n refresh: Flags.boolean({\n description: \"Force refresh from remote sources\",\n default: false,\n }),\n \"agent-source\": Flags.string({\n description: \"Remote agent partials source (default: local CLI)\",\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Edit);\n\n const installation = await detectInstallation();\n\n if (!installation) {\n this.error(\"No installation found. Run 'cc init' first to set up Claude Collective.\", {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const pluginDir = getCollectivePluginDir();\n const pluginSkillsDir =\n installation.mode === \"local\" ? installation.skillsDir : getPluginSkillsDir(pluginDir);\n\n const modeLabel = installation.mode === \"local\" ? \"Local\" : \"Plugin\";\n this.log(`Edit ${modeLabel} Skills\\n`);\n\n this.log(\"Resolving marketplace source...\");\n let sourceResult;\n try {\n sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir: process.cwd(),\n forceRefresh: flags.refresh,\n });\n\n const sourceInfo = sourceResult.isLocal ? \"local\" : sourceResult.sourceConfig.sourceOrigin;\n this.log(\n `✓ Loaded ${Object.keys(sourceResult.matrix.skills).length} skills (${sourceInfo})\\n`,\n );\n } catch (error) {\n this.handleError(error);\n }\n\n this.log(\"Reading current skills...\");\n let currentSkillIds: SkillId[];\n try {\n currentSkillIds = await getPluginSkillIds(pluginSkillsDir, sourceResult.matrix);\n this.log(`✓ Current plugin has ${currentSkillIds.length} skills\\n`);\n } catch (error) {\n this.handleError(error);\n }\n\n let wizardResult: WizardResultV2 | null = null;\n\n const { waitUntilExit } = render(\n <Wizard\n matrix={sourceResult.matrix}\n version={this.config.version}\n initialStep=\"build\"\n installedSkillIds={currentSkillIds}\n projectDir={process.cwd()}\n onComplete={(result) => {\n wizardResult = result as WizardResultV2;\n }}\n onCancel={() => {\n this.log(\"\\nEdit cancelled\");\n }}\n />,\n );\n\n await waitUntilExit();\n\n const result = wizardResult as WizardResultV2 | null;\n\n if (!result || result.cancelled) {\n this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n }\n\n if (!result.validation.valid) {\n const errorMessages = result.validation.errors.map((e) => e.message).join(\"\\n \");\n this.error(`Selection has validation errors:\\n ${errorMessages}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const addedSkills = result.selectedSkills.filter((id) => !currentSkillIds.includes(id));\n const removedSkills = currentSkillIds.filter((id) => !result.selectedSkills.includes(id));\n\n // Detect source changes (user changed which source provides a skill)\n const sourceChanges = new Map<SkillId, { from: string; to: string }>();\n for (const [skillId, selectedSource] of typedEntries<SkillId, string>(\n result.sourceSelections,\n )) {\n const skill = sourceResult.matrix.skills[skillId];\n if (skill?.activeSource && skill.activeSource.name !== selectedSource) {\n sourceChanges.set(skillId, {\n from: skill.activeSource.name,\n to: selectedSource,\n });\n }\n }\n\n const hasSourceChanges = sourceChanges.size > 0;\n const hasSkillChanges = addedSkills.length > 0 || removedSkills.length > 0;\n\n if (result.validation.warnings.length > 0) {\n this.log(\"\\nWarnings:\");\n for (const warning of result.validation.warnings) {\n this.warn(` ! ${warning.message}`);\n }\n this.log(\"\");\n }\n\n if (!hasSkillChanges && !hasSourceChanges) {\n this.log(\"No changes made.\");\n this.log(\"Plugin unchanged\\n\");\n return;\n }\n\n this.log(\"\\nChanges:\");\n for (const skillId of addedSkills) {\n const skill = sourceResult.matrix.skills[skillId];\n this.log(` + ${skill?.displayName || skillId}`);\n }\n for (const skillId of removedSkills) {\n const skill = sourceResult.matrix.skills[skillId];\n this.log(` - ${skill?.displayName || skillId}`);\n }\n for (const [skillId, change] of sourceChanges) {\n const fromLabel = formatSourceDisplayName(change.from);\n const toLabel = formatSourceDisplayName(change.to);\n this.log(` ~ ${skillId} (${fromLabel} \\u2192 ${toLabel})`);\n }\n this.log(\"\");\n\n // Apply source switches (archive/restore local skills)\n const projectDir = process.cwd();\n for (const [skillId, change] of sourceChanges) {\n if (change.from === \"local\") {\n await archiveLocalSkill(projectDir, skillId);\n }\n if (change.to === \"local\") {\n await restoreArchivedSkill(projectDir, skillId);\n }\n }\n\n this.log(\"Updating plugin skills...\");\n try {\n if (await directoryExists(pluginSkillsDir)) {\n await remove(pluginSkillsDir);\n }\n await ensureDir(pluginSkillsDir);\n\n await copySkillsToPluginFromSource(\n result.selectedSkills,\n pluginDir,\n sourceResult.matrix,\n sourceResult,\n result.sourceSelections,\n );\n this.log(`✓ Plugin updated with ${result.selectedSkills.length} skills\\n`);\n } catch (error) {\n this.handleError(error);\n }\n\n let sourcePath: string;\n this.log(flags[\"agent-source\"] ? \"Fetching agent partials...\" : \"Loading agent partials...\");\n try {\n const agentDefs = await getAgentDefinitions(flags[\"agent-source\"], {\n forceRefresh: flags.refresh,\n });\n sourcePath = agentDefs.sourcePath;\n this.log(flags[\"agent-source\"] ? \"✓ Agent partials fetched\\n\" : \"✓ Agent partials loaded\\n\");\n } catch (error) {\n this.handleError(error);\n }\n\n this.log(\"Recompiling agents...\");\n try {\n const recompileResult = await recompileAgents({\n pluginDir,\n sourcePath,\n });\n\n if (recompileResult.failed.length > 0) {\n this.log(\n `✓ Recompiled ${recompileResult.compiled.length} agents (${recompileResult.failed.length} failed)\\n`,\n );\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n } else if (recompileResult.compiled.length > 0) {\n this.log(`✓ Recompiled ${recompileResult.compiled.length} agents\\n`);\n } else {\n this.log(\"✓ No agents to recompile\\n\");\n }\n } catch (error) {\n this.warn(\n `Agent recompilation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n this.log(\"You can manually recompile with 'cc compile'.\\n\");\n }\n\n this.log(\"Updating plugin version...\");\n try {\n const newVersion = await bumpPluginVersion(pluginDir, \"patch\");\n this.log(`✓ Version bumped to ${newVersion}\\n`);\n } catch (error) {\n this.handleError(error);\n }\n\n const summaryParts = [`${addedSkills.length} added`, `${removedSkills.length} removed`];\n if (hasSourceChanges) {\n summaryParts.push(`${sourceChanges.size} source${sourceChanges.size > 1 ? \"s\" : \"\"} changed`);\n }\n this.log(`\\n\\u2713 Plugin updated! (${summaryParts.join(\", \")})\\n`);\n }\n}\n"],"mappings":"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","names":["result"]}
@@ -1,43 +1,34 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- saveSourceToProjectConfig
4
- } from "../chunk-NAGU7TVZ.js";
5
- import {
6
- copySkillsToLocalFlattened
7
- } from "../chunk-KH3HA7J7.js";
8
- import "../chunk-INJ2EFRW.js";
9
- import "../chunk-IOBFMF6X.js";
10
- import {
11
- loadSkillsMatrixFromSource
12
- } from "../chunk-PLZOUVDD.js";
13
- import "../chunk-CKPQHGXR.js";
14
- import "../chunk-CA4LH4LI.js";
15
- import "../chunk-BQX23RBV.js";
16
2
  import {
17
3
  BaseCommand,
18
4
  EXIT_CODES
19
- } from "../chunk-EHS3TWWP.js";
5
+ } from "../chunk-OBXAY23Y.js";
20
6
  import {
21
- loadProjectConfig,
22
- resolveSource
23
- } from "../chunk-374JNMR6.js";
24
- import "../chunk-T25OEQFI.js";
7
+ copySkillsToLocalFlattened,
8
+ loadProjectSourceConfig,
9
+ loadSkillsMatrixFromSource,
10
+ resolveSource,
11
+ saveSourceToProjectConfig
12
+ } from "../chunk-YDBSSAJ6.js";
25
13
  import {
26
14
  copy,
27
15
  directoryExists,
28
16
  ensureDir,
29
17
  fileExists,
30
18
  writeFile
31
- } from "../chunk-AL74GBW4.js";
19
+ } from "../chunk-ZDREFYD2.js";
20
+ import {
21
+ typedKeys
22
+ } from "../chunk-HWD32NP7.js";
32
23
  import {
33
24
  CLAUDE_SRC_DIR,
34
25
  DIRS,
35
26
  LOCAL_SKILLS_PATH,
36
27
  PROJECT_ROOT
37
- } from "../chunk-FJFEKPXF.js";
28
+ } from "../chunk-O6ZTD7ZI.js";
38
29
  import {
39
30
  init_esm_shims
40
- } from "../chunk-DHET7RCE.js";
31
+ } from "../chunk-AWKZ5BDL.js";
41
32
 
42
33
  // src/cli/commands/eject.ts
43
34
  init_esm_shims();
@@ -146,11 +137,7 @@ var Eject = class _Eject extends BaseCommand {
146
137
  this.logSuccess("Eject complete!");
147
138
  this.log("");
148
139
  }
149
- /**
150
- * Ensure a minimal config.yaml exists so that `cc compile` can work after eject.
151
- * Only creates if config doesn't already exist.
152
- * Includes all resolved config values: source, marketplace, author, agents_source.
153
- */
140
+ // Ensures a minimal config.yaml exists so `cc compile` works after eject
154
141
  async ensureMinimalConfig(projectDir, sourceFlag, sourceResult) {
155
142
  const configPath = path.join(projectDir, CLAUDE_SRC_DIR, "config.yaml");
156
143
  if (await fileExists(configPath)) {
@@ -170,7 +157,7 @@ var Eject = class _Eject extends BaseCommand {
170
157
  if (resolvedConfig.marketplace) {
171
158
  config.marketplace = resolvedConfig.marketplace;
172
159
  }
173
- const existingProjectConfig = await loadProjectConfig(projectDir);
160
+ const existingProjectConfig = await loadProjectSourceConfig(projectDir);
174
161
  if (existingProjectConfig?.author) {
175
162
  config.author = existingProjectConfig.author;
176
163
  }
@@ -205,15 +192,6 @@ var Eject = class _Eject extends BaseCommand {
205
192
  await writeFile(configPath, configContent);
206
193
  this.logSuccess(`Created ${CLAUDE_SRC_DIR}/config.yaml`);
207
194
  }
208
- /**
209
- * Eject agent partials (templates + agent partial files).
210
- *
211
- * Combines the old templates and agents eject into a single operation:
212
- * - Copies `PROJECT_ROOT/src/agents/_templates/` to `<dest>/_templates/`
213
- * - Copies agent partials from `PROJECT_ROOT/src/agents/` (excluding `_templates`) to `<dest>/`
214
- *
215
- * Always copies from CLI's PROJECT_ROOT - the `--source` flag has no effect.
216
- */
217
195
  async ejectAgentPartials(outputBase, force, directOutput = false) {
218
196
  const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);
219
197
  if (!await directoryExists(sourceDir)) {
@@ -230,24 +208,14 @@ var Eject = class _Eject extends BaseCommand {
230
208
  this.logSuccess(`Agent partials ejected to ${destDir}`);
231
209
  this.log("You can now customize templates, agent intro, workflow, and examples locally.");
232
210
  }
233
- /**
234
- * Eject skills from the configured source to local .claude/skills/ directory.
235
- *
236
- * Uses the source resolution system:
237
- * - Default: Public marketplace
238
- * - `--source /path`: Custom local source
239
- * - `--source url`: Custom remote source
240
- *
241
- * Skills are copied in a flattened structure using their normalized skill IDs.
242
- */
243
211
  async ejectSkills(projectDir, force, directOutput = false, sourceResult, customOutputBase) {
244
212
  const destDir = directOutput && customOutputBase ? customOutputBase : path.join(projectDir, LOCAL_SKILLS_PATH);
245
213
  if (await directoryExists(destDir) && !force) {
246
214
  this.warn(`Skills already exist at ${destDir}. Use --force to overwrite.`);
247
215
  return;
248
216
  }
249
- const skillIds = Object.keys(sourceResult.matrix.skills).filter(
250
- (skillId) => !sourceResult.matrix.skills[skillId].local
217
+ const skillIds = typedKeys(sourceResult.matrix.skills).filter(
218
+ (skillId) => !sourceResult.matrix.skills[skillId]?.local
251
219
  );
252
220
  if (skillIds.length === 0) {
253
221
  this.warn("No skills found in source to eject.");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/eject.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport os from \"os\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { copy, ensureDir, directoryExists, fileExists, writeFile } from \"../utils/fs.js\";\nimport { CLAUDE_SRC_DIR, DIRS, LOCAL_SKILLS_PATH, PROJECT_ROOT } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/source-loader.js\";\nimport { copySkillsToLocalFlattened } from \"../lib/skill-copier.js\";\nimport { loadProjectConfig, resolveSource } from \"../lib/config.js\";\nimport { saveSourceToProjectConfig } from \"../lib/config-saver.js\";\n\nconst EJECT_TYPES = [\"agent-partials\", \"skills\", \"all\"] as const;\ntype EjectType = (typeof EJECT_TYPES)[number];\n\nexport default class Eject extends BaseCommand {\n static summary = \"Eject skills or agent partials for local customization\";\n static description =\n \"Copy agent partials or skills to your project for customization. \" +\n \"Agent partials are always copied from the CLI. \" +\n \"Skills are copied from the configured source (public marketplace by default).\";\n\n static args = {\n type: Args.string({\n description: \"What to eject: agent-partials, skills, all\",\n required: false,\n options: EJECT_TYPES as unknown as string[],\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing files\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory (default: .claude/ in current directory)\",\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote source\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Eject);\n const projectDir = process.cwd();\n\n if (!args.type) {\n this.error(\"Please specify what to eject: agent-partials, skills, or all\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (!EJECT_TYPES.includes(args.type as EjectType)) {\n this.error(`Unknown eject type: ${args.type}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n // Resolve output base directory\n let outputBase: string;\n if (flags.output) {\n // Expand ~ to home directory if present\n const expandedPath = flags.output.startsWith(\"~\")\n ? path.join(os.homedir(), flags.output.slice(1))\n : flags.output;\n outputBase = path.resolve(projectDir, expandedPath);\n\n // Validate output path is not an existing file\n if (await fileExists(outputBase)) {\n this.error(`Output path exists as a file: ${outputBase}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n } else {\n outputBase = path.join(projectDir, CLAUDE_SRC_DIR);\n }\n\n this.log(\"\");\n this.log(\"Claude Collective Eject\");\n this.log(\"\");\n\n // Show output directory when using custom path\n if (flags.output) {\n this.log(`Output directory: ${outputBase}`);\n }\n\n const ejectType = args.type as EjectType;\n const directOutput = !!flags.output;\n\n // Load source when ejecting skills or all\n let sourceResult: SourceLoadResult | undefined;\n if (ejectType === \"skills\" || ejectType === \"all\") {\n sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n forceRefresh: flags.refresh,\n });\n }\n\n switch (ejectType) {\n case \"agent-partials\":\n await this.ejectAgentPartials(outputBase, flags.force, directOutput);\n break;\n case \"skills\":\n await this.ejectSkills(\n projectDir,\n flags.force,\n directOutput,\n sourceResult!,\n directOutput ? outputBase : undefined,\n );\n break;\n case \"all\":\n await this.ejectAgentPartials(outputBase, flags.force, directOutput);\n await this.ejectSkills(\n projectDir,\n flags.force,\n directOutput,\n sourceResult!,\n directOutput ? outputBase : undefined,\n );\n break;\n }\n\n // Save source to project config if --source was provided\n if (flags.source) {\n await saveSourceToProjectConfig(projectDir, flags.source);\n this.log(`Source saved to .claude-src/config.yaml`);\n }\n\n // Create minimal config.yaml if it doesn't exist\n await this.ensureMinimalConfig(projectDir, flags.source, sourceResult);\n\n this.log(\"\");\n this.logSuccess(\"Eject complete!\");\n this.log(\"\");\n }\n\n /**\n * Ensure a minimal config.yaml exists so that `cc compile` can work after eject.\n * Only creates if config doesn't already exist.\n * Includes all resolved config values: source, marketplace, author, agents_source.\n */\n private async ensureMinimalConfig(\n projectDir: string,\n sourceFlag?: string,\n sourceResult?: SourceLoadResult,\n ): Promise<void> {\n const configPath = path.join(projectDir, CLAUDE_SRC_DIR, \"config.yaml\");\n\n // Don't overwrite existing config\n if (await fileExists(configPath)) {\n return;\n }\n\n const projectName = path.basename(projectDir);\n\n // Build config with all available values\n const config: Record<string, unknown> = {\n name: projectName,\n installMode: \"local\",\n };\n\n // Get resolved source config\n const resolvedConfig =\n sourceResult?.sourceConfig ?? (await resolveSource(sourceFlag, projectDir));\n\n // Add source (flag overrides resolved source, but always include it)\n if (sourceFlag) {\n config.source = sourceFlag;\n } else if (resolvedConfig.source) {\n config.source = resolvedConfig.source;\n }\n\n // Add marketplace if available\n if (resolvedConfig.marketplace) {\n config.marketplace = resolvedConfig.marketplace;\n }\n\n // Load project config to get author and agents_source\n const existingProjectConfig = await loadProjectConfig(projectDir);\n if (existingProjectConfig?.author) {\n config.author = existingProjectConfig.author;\n }\n if (existingProjectConfig?.agents_source) {\n config.agents_source = existingProjectConfig.agents_source;\n }\n\n await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));\n\n // Build config YAML with commented example stack blueprint\n let configContent = stringifyYaml(config, { indent: 2 });\n\n // Append commented example stack configuration as a blueprint for users\n const exampleStackComment = `\n# Example stack configuration (uncomment and customize):\n#\n# skills:\n# - web-framework-react\n# - web-styling-scss-modules\n# - api-framework-hono\n# - api-database-drizzle\n#\n# agents:\n# - web-developer\n# - api-developer\n# - web-reviewer\n#\n# stack:\n# web-developer:\n# framework: web-framework-react\n# styling: web-styling-scss-modules\n# api-developer:\n# api: api-framework-hono\n# database: api-database-drizzle\n`;\n\n configContent += exampleStackComment;\n await writeFile(configPath, configContent);\n\n this.logSuccess(`Created ${CLAUDE_SRC_DIR}/config.yaml`);\n }\n\n /**\n * Eject agent partials (templates + agent partial files).\n *\n * Combines the old templates and agents eject into a single operation:\n * - Copies `PROJECT_ROOT/src/agents/_templates/` to `<dest>/_templates/`\n * - Copies agent partials from `PROJECT_ROOT/src/agents/` (excluding `_templates`) to `<dest>/`\n *\n * Always copies from CLI's PROJECT_ROOT - the `--source` flag has no effect.\n */\n private async ejectAgentPartials(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(sourceDir))) {\n this.warn(\"No agent partials found in CLI.\");\n return;\n }\n\n // Destination directory structure:\n // When directOutput is true: write directly to outputBase\n // When false (default): add \"agents\" subdirectory (to .claude-src/agents/)\n const destDir = directOutput ? outputBase : path.join(outputBase, \"agents\");\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(`Agent partials already exist at ${destDir}. Use --force to overwrite.`);\n return;\n }\n\n await ensureDir(destDir);\n\n // Copy entire agents directory (includes _templates and all agent partials)\n await copy(sourceDir, destDir);\n\n this.logSuccess(`Agent partials ejected to ${destDir}`);\n this.log(\"You can now customize templates, agent intro, workflow, and examples locally.\");\n }\n\n /**\n * Eject skills from the configured source to local .claude/skills/ directory.\n *\n * Uses the source resolution system:\n * - Default: Public marketplace\n * - `--source /path`: Custom local source\n * - `--source url`: Custom remote source\n *\n * Skills are copied in a flattened structure using their normalized skill IDs.\n */\n private async ejectSkills(\n projectDir: string,\n force: boolean,\n directOutput: boolean = false,\n sourceResult: SourceLoadResult,\n customOutputBase?: string,\n ): Promise<void> {\n // Destination directory structure:\n // When directOutput is true (custom --output): write directly to customOutputBase\n // When false (default): use .claude/skills/ (skills are runtime files, not source files)\n const destDir =\n directOutput && customOutputBase\n ? customOutputBase\n : path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(`Skills already exist at ${destDir}. Use --force to overwrite.`);\n return;\n }\n\n // Get all non-local skill IDs from the source matrix\n const skillIds = Object.keys(sourceResult.matrix.skills).filter(\n (skillId) => !sourceResult.matrix.skills[skillId].local,\n );\n\n if (skillIds.length === 0) {\n this.warn(\"No skills found in source to eject.\");\n return;\n }\n\n await ensureDir(destDir);\n\n // Copy skills using flattened structure\n const copiedSkills = await copySkillsToLocalFlattened(\n skillIds,\n destDir,\n sourceResult.matrix,\n sourceResult,\n );\n\n const sourceLabel = sourceResult.isLocal\n ? sourceResult.sourcePath\n : sourceResult.marketplace || sourceResult.sourceConfig.source;\n\n this.logSuccess(`${copiedSkills.length} skills ejected to ${destDir} from ${sourceLabel}`);\n this.log(\"You can now customize skill content locally.\");\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/eject.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport os from \"os\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { copy, ensureDir, directoryExists, fileExists, writeFile } from \"../utils/fs.js\";\nimport { CLAUDE_SRC_DIR, DIRS, LOCAL_SKILLS_PATH, PROJECT_ROOT } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/loading/index.js\";\nimport { copySkillsToLocalFlattened } from \"../lib/skills/index.js\";\nimport type { SkillId } from \"../types/index.js\";\nimport { typedKeys } from \"../utils/typed-object.js\";\nimport {\n loadProjectSourceConfig,\n resolveSource,\n saveSourceToProjectConfig,\n} from \"../lib/configuration/index.js\";\n\nconst EJECT_TYPES = [\"agent-partials\", \"skills\", \"all\"] as const;\ntype EjectType = (typeof EJECT_TYPES)[number];\n\nexport default class Eject extends BaseCommand {\n static summary = \"Eject skills or agent partials for local customization\";\n static description =\n \"Copy agent partials or skills to your project for customization. \" +\n \"Agent partials are always copied from the CLI. \" +\n \"Skills are copied from the configured source (public marketplace by default).\";\n\n static args = {\n type: Args.string({\n description: \"What to eject: agent-partials, skills, all\",\n required: false,\n options: EJECT_TYPES as unknown as string[],\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing files\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory (default: .claude/ in current directory)\",\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote source\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Eject);\n const projectDir = process.cwd();\n\n if (!args.type) {\n this.error(\"Please specify what to eject: agent-partials, skills, or all\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (!EJECT_TYPES.includes(args.type as EjectType)) {\n this.error(`Unknown eject type: ${args.type}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n let outputBase: string;\n if (flags.output) {\n const expandedPath = flags.output.startsWith(\"~\")\n ? path.join(os.homedir(), flags.output.slice(1))\n : flags.output;\n outputBase = path.resolve(projectDir, expandedPath);\n\n if (await fileExists(outputBase)) {\n this.error(`Output path exists as a file: ${outputBase}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n } else {\n outputBase = path.join(projectDir, CLAUDE_SRC_DIR);\n }\n\n this.log(\"\");\n this.log(\"Claude Collective Eject\");\n this.log(\"\");\n\n if (flags.output) {\n this.log(`Output directory: ${outputBase}`);\n }\n\n const ejectType = args.type as EjectType;\n const directOutput = !!flags.output;\n\n let sourceResult: SourceLoadResult | undefined;\n if (ejectType === \"skills\" || ejectType === \"all\") {\n sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n forceRefresh: flags.refresh,\n });\n }\n\n switch (ejectType) {\n case \"agent-partials\":\n await this.ejectAgentPartials(outputBase, flags.force, directOutput);\n break;\n case \"skills\":\n await this.ejectSkills(\n projectDir,\n flags.force,\n directOutput,\n sourceResult!,\n directOutput ? outputBase : undefined,\n );\n break;\n case \"all\":\n await this.ejectAgentPartials(outputBase, flags.force, directOutput);\n await this.ejectSkills(\n projectDir,\n flags.force,\n directOutput,\n sourceResult!,\n directOutput ? outputBase : undefined,\n );\n break;\n }\n\n if (flags.source) {\n await saveSourceToProjectConfig(projectDir, flags.source);\n this.log(`Source saved to .claude-src/config.yaml`);\n }\n\n await this.ensureMinimalConfig(projectDir, flags.source, sourceResult);\n\n this.log(\"\");\n this.logSuccess(\"Eject complete!\");\n this.log(\"\");\n }\n\n // Ensures a minimal config.yaml exists so `cc compile` works after eject\n private async ensureMinimalConfig(\n projectDir: string,\n sourceFlag?: string,\n sourceResult?: SourceLoadResult,\n ): Promise<void> {\n const configPath = path.join(projectDir, CLAUDE_SRC_DIR, \"config.yaml\");\n\n if (await fileExists(configPath)) {\n return;\n }\n\n const projectName = path.basename(projectDir);\n\n const config: Record<string, unknown> = {\n name: projectName,\n installMode: \"local\",\n };\n\n const resolvedConfig =\n sourceResult?.sourceConfig ?? (await resolveSource(sourceFlag, projectDir));\n\n if (sourceFlag) {\n config.source = sourceFlag;\n } else if (resolvedConfig.source) {\n config.source = resolvedConfig.source;\n }\n\n if (resolvedConfig.marketplace) {\n config.marketplace = resolvedConfig.marketplace;\n }\n\n const existingProjectConfig = await loadProjectSourceConfig(projectDir);\n if (existingProjectConfig?.author) {\n config.author = existingProjectConfig.author;\n }\n if (existingProjectConfig?.agents_source) {\n config.agents_source = existingProjectConfig.agents_source;\n }\n\n await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));\n\n let configContent = stringifyYaml(config, { indent: 2 });\n\n const exampleStackComment = `\n# Example stack configuration (uncomment and customize):\n#\n# skills:\n# - web-framework-react\n# - web-styling-scss-modules\n# - api-framework-hono\n# - api-database-drizzle\n#\n# agents:\n# - web-developer\n# - api-developer\n# - web-reviewer\n#\n# stack:\n# web-developer:\n# framework: web-framework-react\n# styling: web-styling-scss-modules\n# api-developer:\n# api: api-framework-hono\n# database: api-database-drizzle\n`;\n\n configContent += exampleStackComment;\n await writeFile(configPath, configContent);\n\n this.logSuccess(`Created ${CLAUDE_SRC_DIR}/config.yaml`);\n }\n\n private async ejectAgentPartials(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(sourceDir))) {\n this.warn(\"No agent partials found in CLI.\");\n return;\n }\n\n const destDir = directOutput ? outputBase : path.join(outputBase, \"agents\");\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(`Agent partials already exist at ${destDir}. Use --force to overwrite.`);\n return;\n }\n\n await ensureDir(destDir);\n\n await copy(sourceDir, destDir);\n\n this.logSuccess(`Agent partials ejected to ${destDir}`);\n this.log(\"You can now customize templates, agent intro, workflow, and examples locally.\");\n }\n\n private async ejectSkills(\n projectDir: string,\n force: boolean,\n directOutput: boolean = false,\n sourceResult: SourceLoadResult,\n customOutputBase?: string,\n ): Promise<void> {\n const destDir =\n directOutput && customOutputBase\n ? customOutputBase\n : path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(`Skills already exist at ${destDir}. Use --force to overwrite.`);\n return;\n }\n\n const skillIds = typedKeys<SkillId>(sourceResult.matrix.skills).filter(\n (skillId) => !sourceResult.matrix.skills[skillId]?.local,\n );\n\n if (skillIds.length === 0) {\n this.warn(\"No skills found in source to eject.\");\n return;\n }\n\n await ensureDir(destDir);\n\n const copiedSkills = await copySkillsToLocalFlattened(\n skillIds,\n destDir,\n sourceResult.matrix,\n sourceResult,\n );\n\n const sourceLabel = sourceResult.isLocal\n ? sourceResult.sourcePath\n : sourceResult.marketplace || sourceResult.sourceConfig.source;\n\n this.logSuccess(`${copiedSkills.length} skills ejected to ${destDir} from ${sourceLabel}`);\n this.log(\"You can now customize skill content locally.\");\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,MAAM,aAAa;AAC5B,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,aAAa,qBAAqB;AAe3C,IAAM,cAAc,CAAC,kBAAkB,UAAU,KAAK;AAGtD,IAAqB,QAArB,MAAqB,eAAc,YAAY;AAAA,EAC7C,OAAO,UAAU;AAAA,EACjB,OAAO,cACL;AAAA,EAIF,OAAO,OAAO;AAAA,IACZ,MAAM,KAAK,OAAO;AAAA,MAChB,aAAa;AAAA,MACb,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,GAAG,YAAY;AAAA,IACf,OAAO,MAAM,QAAQ;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,IACf,CAAC;AAAA,IACD,SAAS,MAAM,QAAQ;AAAA,MACrB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AAC9C,UAAM,aAAa,QAAQ,IAAI;AAE/B,QAAI,CAAC,KAAK,MAAM;AACd,WAAK,MAAM,gEAAgE;AAAA,QACzE,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,YAAY,SAAS,KAAK,IAAiB,GAAG;AACjD,WAAK,MAAM,uBAAuB,KAAK,IAAI,IAAI;AAAA,QAC7C,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,QAAI;AACJ,QAAI,MAAM,QAAQ;AAChB,YAAM,eAAe,MAAM,OAAO,WAAW,GAAG,IAC5C,KAAK,KAAK,GAAG,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAC,CAAC,IAC7C,MAAM;AACV,mBAAa,KAAK,QAAQ,YAAY,YAAY;AAElD,UAAI,MAAM,WAAW,UAAU,GAAG;AAChC,aAAK,MAAM,iCAAiC,UAAU,IAAI;AAAA,UACxD,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,mBAAa,KAAK,KAAK,YAAY,cAAc;AAAA,IACnD;AAEA,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,yBAAyB;AAClC,SAAK,IAAI,EAAE;AAEX,QAAI,MAAM,QAAQ;AAChB,WAAK,IAAI,qBAAqB,UAAU,EAAE;AAAA,IAC5C;AAEA,UAAM,YAAY,KAAK;AACvB,UAAM,eAAe,CAAC,CAAC,MAAM;AAE7B,QAAI;AACJ,QAAI,cAAc,YAAY,cAAc,OAAO;AACjD,qBAAe,MAAM,2BAA2B;AAAA,QAC9C,YAAY,MAAM;AAAA,QAClB;AAAA,QACA,cAAc,MAAM;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,YAAQ,WAAW;AAAA,MACjB,KAAK;AACH,cAAM,KAAK,mBAAmB,YAAY,MAAM,OAAO,YAAY;AACnE;AAAA,MACF,KAAK;AACH,cAAM,KAAK;AAAA,UACT;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,eAAe,aAAa;AAAA,QAC9B;AACA;AAAA,MACF,KAAK;AACH,cAAM,KAAK,mBAAmB,YAAY,MAAM,OAAO,YAAY;AACnE,cAAM,KAAK;AAAA,UACT;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,eAAe,aAAa;AAAA,QAC9B;AACA;AAAA,IACJ;AAEA,QAAI,MAAM,QAAQ;AAChB,YAAM,0BAA0B,YAAY,MAAM,MAAM;AACxD,WAAK,IAAI,yCAAyC;AAAA,IACpD;AAEA,UAAM,KAAK,oBAAoB,YAAY,MAAM,QAAQ,YAAY;AAErE,SAAK,IAAI,EAAE;AACX,SAAK,WAAW,iBAAiB;AACjC,SAAK,IAAI,EAAE;AAAA,EACb;AAAA;AAAA,EAGA,MAAc,oBACZ,YACA,YACA,cACe;AACf,UAAM,aAAa,KAAK,KAAK,YAAY,gBAAgB,aAAa;AAEtE,QAAI,MAAM,WAAW,UAAU,GAAG;AAChC;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,SAAS,UAAU;AAE5C,UAAM,SAAkC;AAAA,MACtC,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAEA,UAAM,iBACJ,cAAc,gBAAiB,MAAM,cAAc,YAAY,UAAU;AAE3E,QAAI,YAAY;AACd,aAAO,SAAS;AAAA,IAClB,WAAW,eAAe,QAAQ;AAChC,aAAO,SAAS,eAAe;AAAA,IACjC;AAEA,QAAI,eAAe,aAAa;AAC9B,aAAO,cAAc,eAAe;AAAA,IACtC;AAEA,UAAM,wBAAwB,MAAM,wBAAwB,UAAU;AACtE,QAAI,uBAAuB,QAAQ;AACjC,aAAO,SAAS,sBAAsB;AAAA,IACxC;AACA,QAAI,uBAAuB,eAAe;AACxC,aAAO,gBAAgB,sBAAsB;AAAA,IAC/C;AAEA,UAAM,UAAU,KAAK,KAAK,YAAY,cAAc,CAAC;AAErD,QAAI,gBAAgB,cAAc,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAEvD,UAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuB5B,qBAAiB;AACjB,UAAM,UAAU,YAAY,aAAa;AAEzC,SAAK,WAAW,WAAW,cAAc,cAAc;AAAA,EACzD;AAAA,EAEA,MAAc,mBACZ,YACA,OACA,eAAwB,OACT;AACf,UAAM,YAAY,KAAK,KAAK,cAAc,KAAK,MAAM;AAErD,QAAI,CAAE,MAAM,gBAAgB,SAAS,GAAI;AACvC,WAAK,KAAK,iCAAiC;AAC3C;AAAA,IACF;AAEA,UAAM,UAAU,eAAe,aAAa,KAAK,KAAK,YAAY,QAAQ;AAE1E,QAAK,MAAM,gBAAgB,OAAO,KAAM,CAAC,OAAO;AAC9C,WAAK,KAAK,mCAAmC,OAAO,6BAA6B;AACjF;AAAA,IACF;AAEA,UAAM,UAAU,OAAO;AAEvB,UAAM,KAAK,WAAW,OAAO;AAE7B,SAAK,WAAW,6BAA6B,OAAO,EAAE;AACtD,SAAK,IAAI,+EAA+E;AAAA,EAC1F;AAAA,EAEA,MAAc,YACZ,YACA,OACA,eAAwB,OACxB,cACA,kBACe;AACf,UAAM,UACJ,gBAAgB,mBACZ,mBACA,KAAK,KAAK,YAAY,iBAAiB;AAE7C,QAAK,MAAM,gBAAgB,OAAO,KAAM,CAAC,OAAO;AAC9C,WAAK,KAAK,2BAA2B,OAAO,6BAA6B;AACzE;AAAA,IACF;AAEA,UAAM,WAAW,UAAmB,aAAa,OAAO,MAAM,EAAE;AAAA,MAC9D,CAAC,YAAY,CAAC,aAAa,OAAO,OAAO,OAAO,GAAG;AAAA,IACrD;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,WAAK,KAAK,qCAAqC;AAC/C;AAAA,IACF;AAEA,UAAM,UAAU,OAAO;AAEvB,UAAM,eAAe,MAAM;AAAA,MACzB;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb;AAAA,IACF;AAEA,UAAM,cAAc,aAAa,UAC7B,aAAa,aACb,aAAa,eAAe,aAAa,aAAa;AAE1D,SAAK,WAAW,GAAG,aAAa,MAAM,sBAAsB,OAAO,SAAS,WAAW,EAAE;AACzF,SAAK,IAAI,8CAA8C;AAAA,EACzD;AACF;","names":[]}
@@ -1,32 +1,30 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- getCurrentDate,
4
- hashFile
5
- } from "../../chunk-IOBFMF6X.js";
6
- import {
7
- fetchFromSource
8
- } from "../../chunk-CA4LH4LI.js";
9
2
  import {
10
3
  BaseCommand,
11
4
  EXIT_CODES
12
- } from "../../chunk-EHS3TWWP.js";
13
- import "../../chunk-374JNMR6.js";
14
- import "../../chunk-T25OEQFI.js";
5
+ } from "../../chunk-OBXAY23Y.js";
6
+ import {
7
+ fetchFromSource,
8
+ getCurrentDate,
9
+ hashFile
10
+ } from "../../chunk-YDBSSAJ6.js";
15
11
  import {
16
12
  copy,
17
13
  directoryExists,
18
14
  ensureDir,
19
15
  fileExists,
16
+ importedSkillMetadataSchema,
20
17
  listDirectories,
21
18
  readFile,
22
19
  writeFile
23
- } from "../../chunk-AL74GBW4.js";
20
+ } from "../../chunk-ZDREFYD2.js";
21
+ import "../../chunk-HWD32NP7.js";
24
22
  import {
25
23
  LOCAL_SKILLS_PATH
26
- } from "../../chunk-FJFEKPXF.js";
24
+ } from "../../chunk-O6ZTD7ZI.js";
27
25
  import {
28
26
  init_esm_shims
29
- } from "../../chunk-DHET7RCE.js";
27
+ } from "../../chunk-AWKZ5BDL.js";
30
28
 
31
29
  // src/cli/commands/import/skill.ts
32
30
  init_esm_shims();
@@ -238,10 +236,6 @@ Use --list to see all available skills.`,
238
236
  this.log("Run 'cc compile' to include imported skills in your agents.");
239
237
  this.log("");
240
238
  }
241
- /**
242
- * Discover valid skills in a directory.
243
- * A valid skill must have a SKILL.md file.
244
- */
245
239
  async discoverValidSkills(skillsDir, skillDirs) {
246
240
  const validSkills = [];
247
241
  for (const skillDir of skillDirs) {
@@ -252,9 +246,6 @@ Use --list to see all available skills.`,
252
246
  }
253
247
  return validSkills.sort();
254
248
  }
255
- /**
256
- * Import a single skill to the destination directory.
257
- */
258
249
  async importSkill(sourcePath, destPath, skillName, source) {
259
250
  const skillMdPath = path.join(sourcePath, SKILL_MD_FILE);
260
251
  if (!await fileExists(skillMdPath)) {
@@ -265,10 +256,6 @@ Use --list to see all available skills.`,
265
256
  await copy(sourcePath, destPath);
266
257
  await this.injectForkedFromMetadata(destPath, skillName, source, contentHash);
267
258
  }
268
- /**
269
- * Inject forked_from metadata into the skill's metadata file.
270
- * Creates metadata.yaml if it doesn't exist.
271
- */
272
259
  async injectForkedFromMetadata(destPath, skillName, source, contentHash) {
273
260
  const metadataYamlPath = path.join(destPath, METADATA_YAML_FILE);
274
261
  const metadataJsonPath = path.join(destPath, METADATA_JSON_FILE);
@@ -287,7 +274,12 @@ Use --list to see all available skills.`,
287
274
  schemaComment = lines[0] + "\n";
288
275
  yamlContent2 = lines.slice(1).join("\n");
289
276
  }
290
- const metadata = parseYaml(yamlContent2);
277
+ const raw = parseYaml(yamlContent2);
278
+ const parseResult = importedSkillMetadataSchema.safeParse(raw);
279
+ if (!parseResult.success) {
280
+ this.warn(`Malformed metadata.yaml at ${metadataYamlPath} \u2014 existing fields may be lost`);
281
+ }
282
+ const metadata = parseResult.success ? parseResult.data : { forked_from: void 0 };
291
283
  metadata.forked_from = forkedFrom;
292
284
  const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });
293
285
  await writeFile(metadataYamlPath, schemaComment + newYamlContent);
@@ -295,7 +287,15 @@ Use --list to see all available skills.`,
295
287
  }
296
288
  if (await fileExists(metadataJsonPath)) {
297
289
  const rawContent = await readFile(metadataJsonPath);
298
- const metadata = JSON.parse(rawContent);
290
+ let jsonParsed;
291
+ try {
292
+ jsonParsed = JSON.parse(rawContent);
293
+ } catch {
294
+ this.warn(`Malformed JSON in ${metadataJsonPath} \u2014 skipping metadata injection`);
295
+ return;
296
+ }
297
+ const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);
298
+ const metadata = jsonResult.success ? jsonResult.data : { forked_from: void 0 };
299
299
  metadata.forked_from = forkedFrom;
300
300
  const yamlContent2 = stringifyYaml(metadata, { lineWidth: 0 });
301
301
  await writeFile(metadataYamlPath, yamlContent2);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/import/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { fetchFromSource } from \"../../lib/source-fetcher.js\";\nimport { getCurrentDate, hashFile } from \"../../lib/versioning.js\";\nimport {\n copy,\n directoryExists,\n fileExists,\n listDirectories,\n readFile,\n writeFile,\n ensureDir,\n} from \"../../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../../consts.js\";\n\n/**\n * Metadata for tracking third-party imports. Different from ForkedFromMetadata\n * in skill-metadata.ts which tracks internal fork lineage (uses skill_id\n * instead of source/skill_name).\n */\ninterface ImportedForkedFromMetadata {\n source: string;\n skill_name: string;\n content_hash: string;\n date: string;\n}\n\ninterface SkillMetadata {\n forked_from?: ImportedForkedFromMetadata;\n [key: string]: unknown;\n}\n\nconst SKILL_MD_FILE = \"SKILL.md\";\nconst METADATA_YAML_FILE = \"metadata.yaml\";\nconst METADATA_JSON_FILE = \"metadata.json\";\nconst DEFAULT_SKILLS_SUBDIR = \"skills\";\n\n/**\n * Parse a GitHub source string into owner/repo and optional subdir.\n *\n * Supported formats:\n * - https://github.com/owner/repo\n * - github:owner/repo\n * - gh:owner/repo\n * - owner/repo (assumes GitHub)\n */\nfunction parseGitHubSource(source: string): {\n gigetSource: string;\n displaySource: string;\n} {\n // Full GitHub URL\n if (source.startsWith(\"https://github.com/\")) {\n const path = source.replace(\"https://github.com/\", \"\");\n return {\n gigetSource: `github:${path}`,\n displaySource: source,\n };\n }\n\n // Already in giget format\n if (source.startsWith(\"github:\") || source.startsWith(\"gh:\")) {\n const normalized = source.replace(/^gh:/, \"github:\");\n return {\n gigetSource: normalized,\n displaySource: `https://github.com/${normalized.replace(\"github:\", \"\")}`,\n };\n }\n\n // Assume owner/repo format\n if (source.includes(\"/\") && !source.includes(\":\")) {\n return {\n gigetSource: `github:${source}`,\n displaySource: `https://github.com/${source}`,\n };\n }\n\n // Return as-is for other sources (might be a local path or other provider)\n return {\n gigetSource: source,\n displaySource: source,\n };\n}\n\nexport default class ImportSkill extends BaseCommand {\n static summary = \"Import a skill from a third-party GitHub repository\";\n static description =\n \"Download and import skills from external GitHub repositories into your local \" +\n \".claude/skills/ directory. Supports importing specific skills or listing available skills.\";\n\n static examples = [\n {\n description: \"List available skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --list\",\n },\n {\n description: \"Import a specific skill\",\n command:\n \"<%= config.bin %> import skill github:vercel-labs/agent-skills --skill react-best-practices\",\n },\n {\n description: \"Import all skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --all\",\n },\n {\n description: \"Import with custom skills directory\",\n command:\n \"<%= config.bin %> import skill github:owner/repo --skill my-skill --subdir custom-skills\",\n },\n ];\n\n static args = {\n source: Args.string({\n description:\n \"GitHub repository source (github:owner/repo, https://github.com/owner/repo, or owner/repo)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n skill: Flags.string({\n char: \"n\",\n description: \"Name of the specific skill to import\",\n required: false,\n }),\n all: Flags.boolean({\n char: \"a\",\n description: \"Import all skills from the repository\",\n default: false,\n }),\n list: Flags.boolean({\n char: \"l\",\n description: \"List available skills without importing\",\n default: false,\n }),\n subdir: Flags.string({\n description: \"Subdirectory containing skills (default: skills)\",\n default: DEFAULT_SKILLS_SUBDIR,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skills\",\n default: false,\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote (ignore cache)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(ImportSkill);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(\"Import Third-Party Skill\");\n this.log(\"\");\n\n // Validate flags\n if (!flags.list && !flags.skill && !flags.all) {\n this.error(\"Please specify --skill <name>, --all, or --list to list available skills\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (flags.skill && flags.all) {\n this.error(\"Cannot use --skill and --all together\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n // Parse the source\n const { gigetSource, displaySource } = parseGitHubSource(args.source);\n this.log(`Source: ${displaySource}`);\n\n // Fetch the repository\n this.log(\"Fetching repository...\");\n\n let repoPath: string;\n try {\n const result = await fetchFromSource(gigetSource, {\n forceRefresh: flags.refresh,\n });\n repoPath = result.path;\n this.log(result.fromCache ? \"Using cached source\" : \"Downloaded fresh copy\");\n } catch (error) {\n this.error(error instanceof Error ? error.message : `Failed to fetch: ${args.source}`, {\n exit: EXIT_CODES.NETWORK_ERROR,\n });\n }\n\n // Find skills directory\n const skillsDir = path.join(repoPath, flags.subdir);\n if (!(await directoryExists(skillsDir))) {\n this.error(\n `Skills directory not found: ${flags.subdir}\\n` +\n `The repository doesn't have a '${flags.subdir}' directory.\\n` +\n `Use --subdir to specify a different location.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n\n // Discover available skills\n const skillDirs = await listDirectories(skillsDir);\n const availableSkills = await this.discoverValidSkills(skillsDir, skillDirs);\n\n if (availableSkills.length === 0) {\n this.error(\n `No valid skills found in ${flags.subdir}/\\n` + `Skills must have a SKILL.md file.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n // Handle --list\n if (flags.list) {\n this.log(\"\");\n this.log(`Available skills (${availableSkills.length}):`);\n this.log(\"\");\n for (const skill of availableSkills) {\n this.log(` - ${skill}`);\n }\n this.log(\"\");\n this.log(\"Use --skill <name> to import a specific skill, or --all to import all.\");\n return;\n }\n\n // Determine which skills to import\n let skillsToImport: string[] = [];\n\n if (flags.all) {\n skillsToImport = availableSkills;\n } else if (flags.skill) {\n // Validate the skill exists\n if (!availableSkills.includes(flags.skill)) {\n this.error(\n `Skill '${flags.skill}' not found in repository.\\n` +\n `Available skills: ${availableSkills.join(\", \")}\\n` +\n `Use --list to see all available skills.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n skillsToImport = [flags.skill];\n }\n\n // Destination directory\n const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (flags[\"dry-run\"]) {\n this.log(\"\");\n this.log(\"[DRY RUN] Would import the following skills:\");\n for (const skill of skillsToImport) {\n const destPath = path.join(destDir, skill);\n const exists = await directoryExists(destPath);\n this.log(` - ${skill} -> ${destPath}${exists ? \" (exists)\" : \"\"}`);\n }\n return;\n }\n\n // Import skills\n this.log(\"\");\n this.log(`Importing ${skillsToImport.length} skill(s)...`);\n\n let imported = 0;\n let skipped = 0;\n\n for (const skillName of skillsToImport) {\n const sourcePath = path.join(skillsDir, skillName);\n const destPath = path.join(destDir, skillName);\n\n // Check if already exists\n if (await directoryExists(destPath)) {\n if (!flags.force) {\n this.warn(`Skipping '${skillName}': already exists. Use --force to overwrite.`);\n skipped++;\n continue;\n }\n }\n\n try {\n await this.importSkill(sourcePath, destPath, skillName, displaySource);\n this.logSuccess(`Imported: ${skillName}`);\n imported++;\n } catch (error) {\n this.warn(\n `Failed to import '${skillName}': ${error instanceof Error ? error.message : String(error)}`,\n );\n skipped++;\n }\n }\n\n this.log(\"\");\n this.logSuccess(`Import complete: ${imported} imported, ${skipped} skipped`);\n this.log(`Skills location: ${destDir}`);\n this.log(\"\");\n this.log(\"Run 'cc compile' to include imported skills in your agents.\");\n this.log(\"\");\n }\n\n /**\n * Discover valid skills in a directory.\n * A valid skill must have a SKILL.md file.\n */\n private async discoverValidSkills(skillsDir: string, skillDirs: string[]): Promise<string[]> {\n const validSkills: string[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, SKILL_MD_FILE);\n if (await fileExists(skillMdPath)) {\n validSkills.push(skillDir);\n }\n }\n\n return validSkills.sort();\n }\n\n /**\n * Import a single skill to the destination directory.\n */\n private async importSkill(\n sourcePath: string,\n destPath: string,\n skillName: string,\n source: string,\n ): Promise<void> {\n // Validate SKILL.md exists\n const skillMdPath = path.join(sourcePath, SKILL_MD_FILE);\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\"Missing required SKILL.md file\");\n }\n\n // Generate content hash from SKILL.md\n const contentHash = await hashFile(skillMdPath);\n\n // Copy the entire skill directory\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n // Inject forked_from metadata\n await this.injectForkedFromMetadata(destPath, skillName, source, contentHash);\n }\n\n /**\n * Inject forked_from metadata into the skill's metadata file.\n * Creates metadata.yaml if it doesn't exist.\n */\n private async injectForkedFromMetadata(\n destPath: string,\n skillName: string,\n source: string,\n contentHash: string,\n ): Promise<void> {\n const metadataYamlPath = path.join(destPath, METADATA_YAML_FILE);\n const metadataJsonPath = path.join(destPath, METADATA_JSON_FILE);\n\n const forkedFrom: ImportedForkedFromMetadata = {\n source,\n skill_name: skillName,\n content_hash: contentHash,\n date: getCurrentDate(),\n };\n\n // Try to update existing metadata.yaml\n if (await fileExists(metadataYamlPath)) {\n const rawContent = await readFile(metadataYamlPath);\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n let schemaComment = \"\";\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n schemaComment = lines[0] + \"\\n\";\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const metadata = parseYaml(yamlContent) as SkillMetadata;\n metadata.forked_from = forkedFrom;\n\n const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataYamlPath, schemaComment + newYamlContent);\n return;\n }\n\n // Try to update existing metadata.json and convert to YAML\n if (await fileExists(metadataJsonPath)) {\n const rawContent = await readFile(metadataJsonPath);\n const metadata = JSON.parse(rawContent) as SkillMetadata;\n metadata.forked_from = forkedFrom;\n\n // Create metadata.yaml with converted content\n const yamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataYamlPath, yamlContent);\n return;\n }\n\n // Create minimal metadata.yaml if neither exists\n const minimalMetadata: SkillMetadata = {\n cli_name: skillName\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \"),\n cli_description: \"Imported from third-party repository\",\n category: \"imported\",\n category_exclusive: false,\n author: \"@imported\",\n forked_from: forkedFrom,\n };\n\n const yamlContent = stringifyYaml(minimalMetadata, { lineWidth: 0 });\n await writeFile(metadataYamlPath, yamlContent);\n }\n}\n"],"mappings":"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","names":["path","yamlContent"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/import/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { fetchFromSource } from \"../../lib/loading/index.js\";\nimport { importedSkillMetadataSchema } from \"../../lib/schemas.js\";\nimport { getCurrentDate, hashFile } from \"../../lib/versioning.js\";\nimport {\n copy,\n directoryExists,\n fileExists,\n listDirectories,\n readFile,\n writeFile,\n ensureDir,\n} from \"../../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../../consts.js\";\n\n/**\n * Metadata for tracking third-party imports. Different from ForkedFromMetadata\n * in skill-metadata.ts which tracks internal fork lineage (uses skill_id\n * instead of source/skill_name).\n */\ntype ImportedForkedFromMetadata = {\n source: string;\n skill_name: string;\n content_hash: string;\n date: string;\n};\n\ntype SkillMetadata = {\n forked_from?: ImportedForkedFromMetadata;\n [key: string]: unknown;\n};\n\nconst SKILL_MD_FILE = \"SKILL.md\";\nconst METADATA_YAML_FILE = \"metadata.yaml\";\nconst METADATA_JSON_FILE = \"metadata.json\";\nconst DEFAULT_SKILLS_SUBDIR = \"skills\";\n\nfunction parseGitHubSource(source: string): {\n gigetSource: string;\n displaySource: string;\n} {\n if (source.startsWith(\"https://github.com/\")) {\n const path = source.replace(\"https://github.com/\", \"\");\n return {\n gigetSource: `github:${path}`,\n displaySource: source,\n };\n }\n\n if (source.startsWith(\"github:\") || source.startsWith(\"gh:\")) {\n const normalized = source.replace(/^gh:/, \"github:\");\n return {\n gigetSource: normalized,\n displaySource: `https://github.com/${normalized.replace(\"github:\", \"\")}`,\n };\n }\n\n if (source.includes(\"/\") && !source.includes(\":\")) {\n return {\n gigetSource: `github:${source}`,\n displaySource: `https://github.com/${source}`,\n };\n }\n\n return {\n gigetSource: source,\n displaySource: source,\n };\n}\n\nexport default class ImportSkill extends BaseCommand {\n static summary = \"Import a skill from a third-party GitHub repository\";\n static description =\n \"Download and import skills from external GitHub repositories into your local \" +\n \".claude/skills/ directory. Supports importing specific skills or listing available skills.\";\n\n static examples = [\n {\n description: \"List available skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --list\",\n },\n {\n description: \"Import a specific skill\",\n command:\n \"<%= config.bin %> import skill github:vercel-labs/agent-skills --skill react-best-practices\",\n },\n {\n description: \"Import all skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --all\",\n },\n {\n description: \"Import with custom skills directory\",\n command:\n \"<%= config.bin %> import skill github:owner/repo --skill my-skill --subdir custom-skills\",\n },\n ];\n\n static args = {\n source: Args.string({\n description:\n \"GitHub repository source (github:owner/repo, https://github.com/owner/repo, or owner/repo)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n skill: Flags.string({\n char: \"n\",\n description: \"Name of the specific skill to import\",\n required: false,\n }),\n all: Flags.boolean({\n char: \"a\",\n description: \"Import all skills from the repository\",\n default: false,\n }),\n list: Flags.boolean({\n char: \"l\",\n description: \"List available skills without importing\",\n default: false,\n }),\n subdir: Flags.string({\n description: \"Subdirectory containing skills (default: skills)\",\n default: DEFAULT_SKILLS_SUBDIR,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skills\",\n default: false,\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote (ignore cache)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(ImportSkill);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(\"Import Third-Party Skill\");\n this.log(\"\");\n\n if (!flags.list && !flags.skill && !flags.all) {\n this.error(\"Please specify --skill <name>, --all, or --list to list available skills\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (flags.skill && flags.all) {\n this.error(\"Cannot use --skill and --all together\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n const { gigetSource, displaySource } = parseGitHubSource(args.source);\n this.log(`Source: ${displaySource}`);\n\n this.log(\"Fetching repository...\");\n\n let repoPath: string;\n try {\n const result = await fetchFromSource(gigetSource, {\n forceRefresh: flags.refresh,\n });\n repoPath = result.path;\n this.log(result.fromCache ? \"Using cached source\" : \"Downloaded fresh copy\");\n } catch (error) {\n this.error(error instanceof Error ? error.message : `Failed to fetch: ${args.source}`, {\n exit: EXIT_CODES.NETWORK_ERROR,\n });\n }\n\n const skillsDir = path.join(repoPath, flags.subdir);\n if (!(await directoryExists(skillsDir))) {\n this.error(\n `Skills directory not found: ${flags.subdir}\\n` +\n `The repository doesn't have a '${flags.subdir}' directory.\\n` +\n `Use --subdir to specify a different location.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n\n const skillDirs = await listDirectories(skillsDir);\n const availableSkills = await this.discoverValidSkills(skillsDir, skillDirs);\n\n if (availableSkills.length === 0) {\n this.error(\n `No valid skills found in ${flags.subdir}/\\n` + `Skills must have a SKILL.md file.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n if (flags.list) {\n this.log(\"\");\n this.log(`Available skills (${availableSkills.length}):`);\n this.log(\"\");\n for (const skill of availableSkills) {\n this.log(` - ${skill}`);\n }\n this.log(\"\");\n this.log(\"Use --skill <name> to import a specific skill, or --all to import all.\");\n return;\n }\n\n let skillsToImport: string[] = [];\n\n if (flags.all) {\n skillsToImport = availableSkills;\n } else if (flags.skill) {\n if (!availableSkills.includes(flags.skill)) {\n this.error(\n `Skill '${flags.skill}' not found in repository.\\n` +\n `Available skills: ${availableSkills.join(\", \")}\\n` +\n `Use --list to see all available skills.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n skillsToImport = [flags.skill];\n }\n\n const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (flags[\"dry-run\"]) {\n this.log(\"\");\n this.log(\"[DRY RUN] Would import the following skills:\");\n for (const skill of skillsToImport) {\n const destPath = path.join(destDir, skill);\n const exists = await directoryExists(destPath);\n this.log(` - ${skill} -> ${destPath}${exists ? \" (exists)\" : \"\"}`);\n }\n return;\n }\n\n this.log(\"\");\n this.log(`Importing ${skillsToImport.length} skill(s)...`);\n\n let imported = 0;\n let skipped = 0;\n\n for (const skillName of skillsToImport) {\n const sourcePath = path.join(skillsDir, skillName);\n const destPath = path.join(destDir, skillName);\n\n if (await directoryExists(destPath)) {\n if (!flags.force) {\n this.warn(`Skipping '${skillName}': already exists. Use --force to overwrite.`);\n skipped++;\n continue;\n }\n }\n\n try {\n await this.importSkill(sourcePath, destPath, skillName, displaySource);\n this.logSuccess(`Imported: ${skillName}`);\n imported++;\n } catch (error) {\n this.warn(\n `Failed to import '${skillName}': ${error instanceof Error ? error.message : String(error)}`,\n );\n skipped++;\n }\n }\n\n this.log(\"\");\n this.logSuccess(`Import complete: ${imported} imported, ${skipped} skipped`);\n this.log(`Skills location: ${destDir}`);\n this.log(\"\");\n this.log(\"Run 'cc compile' to include imported skills in your agents.\");\n this.log(\"\");\n }\n\n private async discoverValidSkills(skillsDir: string, skillDirs: string[]): Promise<string[]> {\n const validSkills: string[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, SKILL_MD_FILE);\n if (await fileExists(skillMdPath)) {\n validSkills.push(skillDir);\n }\n }\n\n return validSkills.sort();\n }\n\n private async importSkill(\n sourcePath: string,\n destPath: string,\n skillName: string,\n source: string,\n ): Promise<void> {\n const skillMdPath = path.join(sourcePath, SKILL_MD_FILE);\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\"Missing required SKILL.md file\");\n }\n\n const contentHash = await hashFile(skillMdPath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await this.injectForkedFromMetadata(destPath, skillName, source, contentHash);\n }\n\n private async injectForkedFromMetadata(\n destPath: string,\n skillName: string,\n source: string,\n contentHash: string,\n ): Promise<void> {\n const metadataYamlPath = path.join(destPath, METADATA_YAML_FILE);\n const metadataJsonPath = path.join(destPath, METADATA_JSON_FILE);\n\n const forkedFrom: ImportedForkedFromMetadata = {\n source,\n skill_name: skillName,\n content_hash: contentHash,\n date: getCurrentDate(),\n };\n\n if (await fileExists(metadataYamlPath)) {\n const rawContent = await readFile(metadataYamlPath);\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n let schemaComment = \"\";\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n schemaComment = lines[0] + \"\\n\";\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const raw = parseYaml(yamlContent);\n const parseResult = importedSkillMetadataSchema.safeParse(raw);\n if (!parseResult.success) {\n this.warn(`Malformed metadata.yaml at ${metadataYamlPath} — existing fields may be lost`);\n }\n const metadata = parseResult.success\n ? (parseResult.data as SkillMetadata)\n : { forked_from: undefined };\n metadata.forked_from = forkedFrom;\n\n const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataYamlPath, schemaComment + newYamlContent);\n return;\n }\n\n if (await fileExists(metadataJsonPath)) {\n const rawContent = await readFile(metadataJsonPath);\n let jsonParsed: unknown;\n try {\n jsonParsed = JSON.parse(rawContent);\n } catch {\n this.warn(`Malformed JSON in ${metadataJsonPath} — skipping metadata injection`);\n return;\n }\n const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);\n const metadata = jsonResult.success\n ? (jsonResult.data as SkillMetadata)\n : { forked_from: undefined };\n metadata.forked_from = forkedFrom;\n\n const yamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataYamlPath, yamlContent);\n return;\n }\n\n const minimalMetadata: SkillMetadata = {\n cli_name: skillName\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \"),\n cli_description: \"Imported from third-party repository\",\n category: \"imported\",\n category_exclusive: false,\n author: \"@imported\",\n forked_from: forkedFrom,\n };\n\n const yamlContent = stringifyYaml(minimalMetadata, { lineWidth: 0 });\n await writeFile(metadataYamlPath, yamlContent);\n }\n}\n"],"mappings":"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","names":["path","yamlContent"]}
@@ -1,24 +1,21 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ BaseCommand,
4
+ EXIT_CODES
5
+ } from "../chunk-OBXAY23Y.js";
2
6
  import {
3
7
  discoverLocalSkills,
4
8
  loadSkillsMatrixFromSource
5
- } from "../chunk-PLZOUVDD.js";
6
- import "../chunk-CKPQHGXR.js";
7
- import "../chunk-CA4LH4LI.js";
8
- import "../chunk-BQX23RBV.js";
9
- import {
10
- BaseCommand
11
- } from "../chunk-EHS3TWWP.js";
12
- import "../chunk-374JNMR6.js";
13
- import "../chunk-T25OEQFI.js";
9
+ } from "../chunk-YDBSSAJ6.js";
14
10
  import {
15
11
  fileExists,
16
12
  readFile
17
- } from "../chunk-AL74GBW4.js";
18
- import "../chunk-FJFEKPXF.js";
13
+ } from "../chunk-ZDREFYD2.js";
14
+ import "../chunk-HWD32NP7.js";
15
+ import "../chunk-O6ZTD7ZI.js";
19
16
  import {
20
17
  init_esm_shims
21
- } from "../chunk-DHET7RCE.js";
18
+ } from "../chunk-AWKZ5BDL.js";
22
19
 
23
20
  // src/cli/commands/info.ts
24
21
  init_esm_shims();
@@ -82,8 +79,9 @@ function findSuggestions(skills, query, maxSuggestions) {
82
79
  const lowerQuery = query.toLowerCase();
83
80
  const matches = [];
84
81
  for (const skill of Object.values(skills)) {
82
+ if (!skill) continue;
85
83
  if (matches.length >= maxSuggestions) break;
86
- if (skill.id.toLowerCase().includes(lowerQuery) || skill.alias?.toLowerCase().includes(lowerQuery) || skill.name.toLowerCase().includes(lowerQuery)) {
84
+ if (skill.id.toLowerCase().includes(lowerQuery) || skill.displayName?.toLowerCase().includes(lowerQuery)) {
87
85
  matches.push(skill.id);
88
86
  }
89
87
  }
@@ -92,8 +90,8 @@ function findSuggestions(skills, query, maxSuggestions) {
92
90
  function formatSkillInfo(skill, isInstalled) {
93
91
  const lines = [];
94
92
  lines.push(`Skill: ${skill.id}`);
95
- if (skill.alias) {
96
- lines.push(`Alias: ${skill.alias}`);
93
+ if (skill.displayName) {
94
+ lines.push(`Alias: ${skill.displayName}`);
97
95
  }
98
96
  lines.push(`Author: ${skill.author}`);
99
97
  lines.push(`Category: ${skill.category}`);
@@ -142,7 +140,7 @@ var Info = class _Info extends BaseCommand {
142
140
  this.log(`Loaded from ${isLocal ? "local" : "remote"}: ${sourcePath}`);
143
141
  let skill = matrix.skills[args.skill];
144
142
  if (!skill) {
145
- const fullId = matrix.aliases[args.skill];
143
+ const fullId = matrix.displayNameToId[args.skill];
146
144
  if (fullId) {
147
145
  skill = matrix.skills[fullId];
148
146
  }
@@ -161,7 +159,7 @@ var Info = class _Info extends BaseCommand {
161
159
  this.log("");
162
160
  this.logInfo("Use 'cc search <query>' to find available skills.");
163
161
  this.log("");
164
- this.exit(1);
162
+ this.exit(EXIT_CODES.ERROR);
165
163
  }
166
164
  const localSkillsResult = await discoverLocalSkills(process.cwd());
167
165
  const localSkillIds = localSkillsResult?.skills.map((s) => s.id) || [];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/info.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport { discoverLocalSkills } from \"../lib/local-skill-loader.js\";\nimport { fileExists, readFile } from \"../utils/fs.js\";\nimport type { ResolvedSkill, SkillRelation, SkillRequirement } from \"../types-matrix.js\";\n\n/**\n * Maximum number of lines to show in content preview\n */\nconst CONTENT_PREVIEW_LINES = 10;\n\n/**\n * Maximum line length before truncation\n */\nconst MAX_LINE_LENGTH = 80;\n\n/**\n * Maximum number of suggestions to show when skill not found\n */\nconst MAX_SUGGESTIONS = 5;\n\n/**\n * Strip frontmatter from SKILL.md content and return body\n */\nfunction stripFrontmatter(content: string): string {\n const lines = content.split(\"\\n\");\n let inFrontmatter = false;\n let frontmatterEndIndex = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (line === \"---\") {\n if (!inFrontmatter) {\n inFrontmatter = true;\n } else {\n frontmatterEndIndex = i + 1;\n break;\n }\n }\n }\n\n return lines.slice(frontmatterEndIndex).join(\"\\n\");\n}\n\n/**\n * Get first N non-empty lines from content\n */\nfunction getPreviewLines(content: string, maxLines: number): string[] {\n const body = stripFrontmatter(content);\n const lines = body.split(\"\\n\");\n const result: string[] = [];\n\n for (const line of lines) {\n if (result.length >= maxLines) break;\n // Include non-empty lines or blank lines after content has started\n if (line.trim() || result.length > 0) {\n const truncated =\n line.length > MAX_LINE_LENGTH ? line.slice(0, MAX_LINE_LENGTH - 3) + \"...\" : line;\n result.push(truncated);\n }\n }\n\n return result;\n}\n\n/**\n * Format an array of skill relations for display\n */\nfunction formatRelations(relations: SkillRelation[]): string {\n if (relations.length === 0) {\n return \"(none)\";\n }\n return relations.map((r) => r.skillId).join(\", \");\n}\n\n/**\n * Format an array of skill requirements for display\n */\nfunction formatRequirements(requirements: SkillRequirement[]): string {\n if (requirements.length === 0) {\n return \"(none)\";\n }\n return requirements\n .map((req) => {\n const prefix = req.needsAny ? \"any of: \" : \"\";\n return prefix + req.skillIds.join(\", \");\n })\n .join(\"; \");\n}\n\n/**\n * Format tags array for display\n */\nfunction formatTags(tags: string[]): string {\n if (tags.length === 0) {\n return \"(none)\";\n }\n return tags.join(\", \");\n}\n\n/**\n * Find skills that match a partial query for suggestions\n */\nfunction findSuggestions(\n skills: Record<string, ResolvedSkill>,\n query: string,\n maxSuggestions: number,\n): string[] {\n const lowerQuery = query.toLowerCase();\n const matches: string[] = [];\n\n for (const skill of Object.values(skills)) {\n if (matches.length >= maxSuggestions) break;\n if (\n skill.id.toLowerCase().includes(lowerQuery) ||\n skill.alias?.toLowerCase().includes(lowerQuery) ||\n skill.name.toLowerCase().includes(lowerQuery)\n ) {\n matches.push(skill.id);\n }\n }\n\n return matches;\n}\n\n/**\n * Format skill info for display\n */\nfunction formatSkillInfo(skill: ResolvedSkill, isInstalled: boolean): string {\n const lines: string[] = [];\n\n lines.push(`Skill: ${skill.id}`);\n if (skill.alias) {\n lines.push(`Alias: ${skill.alias}`);\n }\n lines.push(`Author: ${skill.author}`);\n lines.push(`Category: ${skill.category}`);\n lines.push(\"\");\n lines.push(\"Description:\");\n lines.push(` ${skill.description}`);\n lines.push(\"\");\n lines.push(`Tags: ${formatTags(skill.tags)}`);\n lines.push(\"\");\n lines.push(`Requires: ${formatRequirements(skill.requires)}`);\n lines.push(`Conflicts with: ${formatRelations(skill.conflictsWith)}`);\n lines.push(`Recommends: ${formatRelations(skill.recommends)}`);\n\n if (skill.usageGuidance) {\n lines.push(\"\");\n lines.push(\"Usage Guidance:\");\n lines.push(` ${skill.usageGuidance}`);\n }\n\n lines.push(\"\");\n lines.push(`Local Status: ${isInstalled ? \"Installed\" : \"Not installed\"}`);\n\n return lines.join(\"\\n\");\n}\n\nexport default class Info extends BaseCommand {\n static summary = \"Show detailed information about a skill\";\n static description =\n \"Display comprehensive information about a skill including metadata, relationships, and content preview\";\n\n static args = {\n skill: Args.string({\n description: \"Skill ID or alias to look up\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n preview: Flags.boolean({\n description: \"Show content preview from SKILL.md\",\n default: true,\n allowNo: true,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Info);\n\n try {\n this.log(\"Loading skills...\");\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n });\n\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n\n // Look up skill by ID or alias\n let skill: ResolvedSkill | undefined = matrix.skills[args.skill];\n\n if (!skill) {\n // Try alias lookup\n const fullId = matrix.aliases[args.skill];\n if (fullId) {\n skill = matrix.skills[fullId];\n }\n }\n\n if (!skill) {\n // Skill not found - show error with suggestions\n const suggestions = findSuggestions(matrix.skills, args.skill, MAX_SUGGESTIONS);\n\n this.log(\"\");\n this.error(`Skill \"${args.skill}\" not found.`, { exit: false });\n\n if (suggestions.length > 0) {\n this.log(\"\");\n this.log(\"Did you mean one of these?\");\n for (const suggestion of suggestions) {\n this.log(` - ${suggestion}`);\n }\n }\n\n this.log(\"\");\n this.logInfo(\"Use 'cc search <query>' to find available skills.\");\n this.log(\"\");\n this.exit(1);\n }\n\n // Check local installation status\n const localSkillsResult = await discoverLocalSkills(process.cwd());\n const localSkillIds = localSkillsResult?.skills.map((s) => s.id) || [];\n const isInstalled = localSkillIds.includes(skill.id);\n\n // Display skill info\n this.log(\"\");\n this.log(formatSkillInfo(skill, isInstalled));\n\n // Show content preview if enabled\n if (flags.preview) {\n // Determine source path for SKILL.md\n let skillMdPath: string;\n\n if (skill.local && skill.localPath) {\n // Local skill - path is relative to cwd\n skillMdPath = path.join(process.cwd(), skill.localPath, \"SKILL.md\");\n } else {\n // Remote skill - path is relative to source\n const sourceDir = isLocal ? sourcePath : path.dirname(sourcePath);\n skillMdPath = path.join(sourceDir, skill.path, \"SKILL.md\");\n }\n\n if (await fileExists(skillMdPath)) {\n const content = await readFile(skillMdPath);\n const previewLines = getPreviewLines(content, CONTENT_PREVIEW_LINES);\n\n if (previewLines.length > 0) {\n this.log(\"\");\n this.log(`--- Content Preview (first ${CONTENT_PREVIEW_LINES} lines) ---`);\n for (const line of previewLines) {\n this.log(line);\n }\n }\n }\n }\n\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/info.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/loading/index.js\";\nimport { discoverLocalSkills } from \"../lib/skills/index.js\";\nimport { fileExists, readFile } from \"../utils/fs.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport type {\n ResolvedSkill,\n SkillDisplayName,\n SkillId,\n SkillRelation,\n SkillRequirement,\n} from \"../types/index.js\";\n\nconst CONTENT_PREVIEW_LINES = 10;\nconst MAX_LINE_LENGTH = 80;\nconst MAX_SUGGESTIONS = 5;\n\nfunction stripFrontmatter(content: string): string {\n const lines = content.split(\"\\n\");\n let inFrontmatter = false;\n let frontmatterEndIndex = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (line === \"---\") {\n if (!inFrontmatter) {\n inFrontmatter = true;\n } else {\n frontmatterEndIndex = i + 1;\n break;\n }\n }\n }\n\n return lines.slice(frontmatterEndIndex).join(\"\\n\");\n}\n\nfunction getPreviewLines(content: string, maxLines: number): string[] {\n const body = stripFrontmatter(content);\n const lines = body.split(\"\\n\");\n const result: string[] = [];\n\n for (const line of lines) {\n if (result.length >= maxLines) break;\n if (line.trim() || result.length > 0) {\n const truncated =\n line.length > MAX_LINE_LENGTH ? line.slice(0, MAX_LINE_LENGTH - 3) + \"...\" : line;\n result.push(truncated);\n }\n }\n\n return result;\n}\n\nfunction formatRelations(relations: SkillRelation[]): string {\n if (relations.length === 0) {\n return \"(none)\";\n }\n return relations.map((r) => r.skillId).join(\", \");\n}\n\nfunction formatRequirements(requirements: SkillRequirement[]): string {\n if (requirements.length === 0) {\n return \"(none)\";\n }\n return requirements\n .map((req) => {\n const prefix = req.needsAny ? \"any of: \" : \"\";\n return prefix + req.skillIds.join(\", \");\n })\n .join(\"; \");\n}\n\nfunction formatTags(tags: string[]): string {\n if (tags.length === 0) {\n return \"(none)\";\n }\n return tags.join(\", \");\n}\n\nfunction findSuggestions(\n skills: Partial<Record<SkillId, ResolvedSkill>>,\n query: string,\n maxSuggestions: number,\n): string[] {\n const lowerQuery = query.toLowerCase();\n const matches: string[] = [];\n\n for (const skill of Object.values(skills)) {\n if (!skill) continue;\n if (matches.length >= maxSuggestions) break;\n if (\n skill.id.toLowerCase().includes(lowerQuery) ||\n skill.displayName?.toLowerCase().includes(lowerQuery)\n ) {\n matches.push(skill.id);\n }\n }\n\n return matches;\n}\n\nfunction formatSkillInfo(skill: ResolvedSkill, isInstalled: boolean): string {\n const lines: string[] = [];\n\n lines.push(`Skill: ${skill.id}`);\n if (skill.displayName) {\n lines.push(`Alias: ${skill.displayName}`);\n }\n lines.push(`Author: ${skill.author}`);\n lines.push(`Category: ${skill.category}`);\n lines.push(\"\");\n lines.push(\"Description:\");\n lines.push(` ${skill.description}`);\n lines.push(\"\");\n lines.push(`Tags: ${formatTags(skill.tags)}`);\n lines.push(\"\");\n lines.push(`Requires: ${formatRequirements(skill.requires)}`);\n lines.push(`Conflicts with: ${formatRelations(skill.conflictsWith)}`);\n lines.push(`Recommends: ${formatRelations(skill.recommends)}`);\n\n if (skill.usageGuidance) {\n lines.push(\"\");\n lines.push(\"Usage Guidance:\");\n lines.push(` ${skill.usageGuidance}`);\n }\n\n lines.push(\"\");\n lines.push(`Local Status: ${isInstalled ? \"Installed\" : \"Not installed\"}`);\n\n return lines.join(\"\\n\");\n}\n\nexport default class Info extends BaseCommand {\n static summary = \"Show detailed information about a skill\";\n static description =\n \"Display comprehensive information about a skill including metadata, relationships, and content preview\";\n\n static args = {\n skill: Args.string({\n description: \"Skill ID or alias to look up\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n preview: Flags.boolean({\n description: \"Show content preview from SKILL.md\",\n default: true,\n allowNo: true,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Info);\n\n try {\n this.log(\"Loading skills...\");\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n });\n\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n\n // CLI arg is an untyped string — cast at data boundary\n let skill: ResolvedSkill | undefined = matrix.skills[args.skill as SkillId];\n\n if (!skill) {\n // Try alias lookup — CLI arg is an untyped string\n const fullId = matrix.displayNameToId[args.skill as SkillDisplayName];\n if (fullId) {\n skill = matrix.skills[fullId];\n }\n }\n\n if (!skill) {\n const suggestions = findSuggestions(matrix.skills, args.skill, MAX_SUGGESTIONS);\n\n this.log(\"\");\n this.error(`Skill \"${args.skill}\" not found.`, { exit: false });\n\n if (suggestions.length > 0) {\n this.log(\"\");\n this.log(\"Did you mean one of these?\");\n for (const suggestion of suggestions) {\n this.log(` - ${suggestion}`);\n }\n }\n\n this.log(\"\");\n this.logInfo(\"Use 'cc search <query>' to find available skills.\");\n this.log(\"\");\n this.exit(EXIT_CODES.ERROR);\n }\n\n const localSkillsResult = await discoverLocalSkills(process.cwd());\n const localSkillIds = localSkillsResult?.skills.map((s) => s.id) || [];\n const isInstalled = localSkillIds.includes(skill.id);\n\n this.log(\"\");\n this.log(formatSkillInfo(skill, isInstalled));\n\n if (flags.preview) {\n let skillMdPath: string;\n\n if (skill.local && skill.localPath) {\n skillMdPath = path.join(process.cwd(), skill.localPath, \"SKILL.md\");\n } else {\n const sourceDir = isLocal ? sourcePath : path.dirname(sourcePath);\n skillMdPath = path.join(sourceDir, skill.path, \"SKILL.md\");\n }\n\n if (await fileExists(skillMdPath)) {\n const content = await readFile(skillMdPath);\n const previewLines = getPreviewLines(content, CONTENT_PREVIEW_LINES);\n\n if (previewLines.length > 0) {\n this.log(\"\");\n this.log(`--- Content Preview (first ${CONTENT_PREVIEW_LINES} lines) ---`);\n for (const line of previewLines) {\n this.log(line);\n }\n }\n }\n }\n\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n"],"mappings":"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","names":[]}