@claude-collective/cli 0.2.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CHANGELOG.md +178 -0
  2. package/README.md +1 -1
  3. package/dist/chunk-3HBTELJN.js +114 -0
  4. package/dist/chunk-3HBTELJN.js.map +1 -0
  5. package/dist/chunk-3ZCB5K33.js +54 -0
  6. package/dist/chunk-3ZCB5K33.js.map +1 -0
  7. package/dist/chunk-66UDJBF6.js +96 -0
  8. package/dist/chunk-66UDJBF6.js.map +1 -0
  9. package/dist/chunk-6LS7XO3H.js +31 -0
  10. package/dist/chunk-6LS7XO3H.js.map +1 -0
  11. package/dist/chunk-A3J6IAXK.js +57 -0
  12. package/dist/chunk-A3J6IAXK.js.map +1 -0
  13. package/dist/chunk-A65SBAAJ.js +69 -0
  14. package/dist/chunk-A65SBAAJ.js.map +1 -0
  15. package/dist/chunk-ALEPJ6YN.js +80 -0
  16. package/dist/chunk-ALEPJ6YN.js.map +1 -0
  17. package/dist/chunk-C4ZTIYFR.js +84 -0
  18. package/dist/chunk-C4ZTIYFR.js.map +1 -0
  19. package/dist/chunk-CIY5UBRB.js +453 -0
  20. package/dist/chunk-CIY5UBRB.js.map +1 -0
  21. package/dist/chunk-DHET7RCE.js +50 -0
  22. package/dist/chunk-DHET7RCE.js.map +1 -0
  23. package/dist/chunk-DHFFRMF6.js +31 -0
  24. package/dist/chunk-DHFFRMF6.js.map +1 -0
  25. package/dist/chunk-DKGL77IY.js +307 -0
  26. package/dist/chunk-DKGL77IY.js.map +1 -0
  27. package/dist/chunk-ED73HCW2.js +315 -0
  28. package/dist/chunk-ED73HCW2.js.map +1 -0
  29. package/dist/chunk-FNOYEXUE.js +308 -0
  30. package/dist/chunk-FNOYEXUE.js.map +1 -0
  31. package/dist/chunk-G2FBJOZG.js +141 -0
  32. package/dist/chunk-G2FBJOZG.js.map +1 -0
  33. package/dist/chunk-HNDT5QRB.js +120 -0
  34. package/dist/chunk-HNDT5QRB.js.map +1 -0
  35. package/dist/chunk-K7PTOVX4.js +158 -0
  36. package/dist/chunk-K7PTOVX4.js.map +1 -0
  37. package/dist/chunk-LQTST4WY.js +91 -0
  38. package/dist/chunk-LQTST4WY.js.map +1 -0
  39. package/dist/chunk-LVKRVFYR.js +54 -0
  40. package/dist/chunk-LVKRVFYR.js.map +1 -0
  41. package/dist/chunk-M7YCPFIX.js +108 -0
  42. package/dist/chunk-M7YCPFIX.js.map +1 -0
  43. package/dist/chunk-MJSFR562.js +57 -0
  44. package/dist/chunk-MJSFR562.js.map +1 -0
  45. package/dist/chunk-MMDXNZPF.js +69 -0
  46. package/dist/chunk-MMDXNZPF.js.map +1 -0
  47. package/dist/chunk-MYAVQ23U.js +356 -0
  48. package/dist/chunk-MYAVQ23U.js.map +1 -0
  49. package/dist/chunk-NGBFJJ7Q.js +124 -0
  50. package/dist/chunk-NGBFJJ7Q.js.map +1 -0
  51. package/dist/chunk-OLBOTK3O.js +64 -0
  52. package/dist/chunk-OLBOTK3O.js.map +1 -0
  53. package/dist/chunk-PPNTD5LO.js +330 -0
  54. package/dist/chunk-PPNTD5LO.js.map +1 -0
  55. package/dist/chunk-Q2LH2DAB.js +392 -0
  56. package/dist/chunk-Q2LH2DAB.js.map +1 -0
  57. package/dist/chunk-Q6DR5QUH.js +547 -0
  58. package/dist/chunk-Q6DR5QUH.js.map +1 -0
  59. package/dist/chunk-QESUUPOE.js +241 -0
  60. package/dist/chunk-QESUUPOE.js.map +1 -0
  61. package/dist/chunk-QGGSLMO3.js +607 -0
  62. package/dist/chunk-QGGSLMO3.js.map +1 -0
  63. package/dist/chunk-SEBPPFUW.js +478 -0
  64. package/dist/chunk-SEBPPFUW.js.map +1 -0
  65. package/dist/chunk-SYQ7R2JO.js +95 -0
  66. package/dist/chunk-SYQ7R2JO.js.map +1 -0
  67. package/dist/chunk-TOPAIL5W.js +22 -0
  68. package/dist/chunk-TOPAIL5W.js.map +1 -0
  69. package/dist/chunk-U4VYHKPM.js +110 -0
  70. package/dist/chunk-U4VYHKPM.js.map +1 -0
  71. package/dist/chunk-UOWHJ6BE.js +83 -0
  72. package/dist/chunk-UOWHJ6BE.js.map +1 -0
  73. package/dist/chunk-XKEG3SCV.js +86 -0
  74. package/dist/chunk-XKEG3SCV.js.map +1 -0
  75. package/dist/chunk-XY3XDVMI.js +15599 -0
  76. package/dist/chunk-XY3XDVMI.js.map +1 -0
  77. package/dist/chunk-Y3V43XCU.js +76 -0
  78. package/dist/chunk-Y3V43XCU.js.map +1 -0
  79. package/dist/chunk-YKXBGCFD.js +129 -0
  80. package/dist/chunk-YKXBGCFD.js.map +1 -0
  81. package/dist/cli-v2/defaults/agent-mappings.yaml +185 -0
  82. package/dist/commands/build/marketplace.js +254 -0
  83. package/dist/commands/build/marketplace.js.map +1 -0
  84. package/dist/commands/build/plugins.js +324 -0
  85. package/dist/commands/build/plugins.js.map +1 -0
  86. package/dist/commands/build/stack.js +169 -0
  87. package/dist/commands/build/stack.js.map +1 -0
  88. package/dist/commands/compile.js +461 -0
  89. package/dist/commands/compile.js.map +1 -0
  90. package/dist/commands/config/get.js +60 -0
  91. package/dist/commands/config/get.js.map +1 -0
  92. package/dist/commands/config/index.js +22 -0
  93. package/dist/commands/config/index.js.map +1 -0
  94. package/dist/commands/config/path.js +35 -0
  95. package/dist/commands/config/path.js.map +1 -0
  96. package/dist/commands/config/set-project.js +61 -0
  97. package/dist/commands/config/set-project.js.map +1 -0
  98. package/dist/commands/config/set.js +60 -0
  99. package/dist/commands/config/set.js.map +1 -0
  100. package/dist/commands/config/show.js +13 -0
  101. package/dist/commands/config/show.js.map +1 -0
  102. package/dist/commands/config/unset-project.js +57 -0
  103. package/dist/commands/config/unset-project.js.map +1 -0
  104. package/dist/commands/config/unset.js +56 -0
  105. package/dist/commands/config/unset.js.map +1 -0
  106. package/dist/commands/diff.js +755 -0
  107. package/dist/commands/diff.js.map +1 -0
  108. package/dist/commands/doctor.js +413 -0
  109. package/dist/commands/doctor.js.map +1 -0
  110. package/dist/commands/edit.js +254 -0
  111. package/dist/commands/edit.js.map +1 -0
  112. package/dist/commands/eject.js +208 -0
  113. package/dist/commands/eject.js.map +1 -0
  114. package/dist/commands/info.js +205 -0
  115. package/dist/commands/info.js.map +1 -0
  116. package/dist/commands/init.js +915 -0
  117. package/dist/commands/init.js.map +1 -0
  118. package/dist/commands/list.js +44 -0
  119. package/dist/commands/list.js.map +1 -0
  120. package/dist/commands/new/agent.js +230 -0
  121. package/dist/commands/new/agent.js.map +1 -0
  122. package/dist/commands/new/skill.js +204 -0
  123. package/dist/commands/new/skill.js.map +1 -0
  124. package/dist/commands/outdated.js +242 -0
  125. package/dist/commands/outdated.js.map +1 -0
  126. package/dist/commands/search.js +115 -0
  127. package/dist/commands/search.js.map +1 -0
  128. package/dist/commands/test-imports.js +92 -0
  129. package/dist/commands/test-imports.js.map +1 -0
  130. package/dist/commands/uninstall.js +309 -0
  131. package/dist/commands/uninstall.js.map +1 -0
  132. package/dist/commands/update.js +428 -0
  133. package/dist/commands/update.js.map +1 -0
  134. package/dist/commands/validate.js +375 -0
  135. package/dist/commands/validate.js.map +1 -0
  136. package/dist/commands/version/bump.js +95 -0
  137. package/dist/commands/version/bump.js.map +1 -0
  138. package/dist/commands/version/index.js +70 -0
  139. package/dist/commands/version/index.js.map +1 -0
  140. package/dist/commands/version/set.js +101 -0
  141. package/dist/commands/version/set.js.map +1 -0
  142. package/dist/commands/version/show.js +70 -0
  143. package/dist/commands/version/show.js.map +1 -0
  144. package/dist/components/common/confirm.js +9 -0
  145. package/dist/components/common/confirm.js.map +1 -0
  146. package/dist/components/common/message.js +24 -0
  147. package/dist/components/common/message.js.map +1 -0
  148. package/dist/components/common/spinner.js +14 -0
  149. package/dist/components/common/spinner.js.map +1 -0
  150. package/dist/components/wizard/category-grid.js +9 -0
  151. package/dist/components/wizard/category-grid.js.map +1 -0
  152. package/dist/components/wizard/category-grid.test.js +728 -0
  153. package/dist/components/wizard/category-grid.test.js.map +1 -0
  154. package/dist/components/wizard/section-progress.js +9 -0
  155. package/dist/components/wizard/section-progress.js.map +1 -0
  156. package/dist/components/wizard/section-progress.test.js +281 -0
  157. package/dist/components/wizard/section-progress.test.js.map +1 -0
  158. package/dist/components/wizard/step-approach.js +11 -0
  159. package/dist/components/wizard/step-approach.js.map +1 -0
  160. package/dist/components/wizard/step-build.js +15 -0
  161. package/dist/components/wizard/step-build.js.map +1 -0
  162. package/dist/components/wizard/step-build.test.js +729 -0
  163. package/dist/components/wizard/step-build.test.js.map +1 -0
  164. package/dist/components/wizard/step-confirm.js +9 -0
  165. package/dist/components/wizard/step-confirm.js.map +1 -0
  166. package/dist/components/wizard/step-refine.js +9 -0
  167. package/dist/components/wizard/step-refine.js.map +1 -0
  168. package/dist/components/wizard/step-refine.test.js +235 -0
  169. package/dist/components/wizard/step-refine.test.js.map +1 -0
  170. package/dist/components/wizard/step-stack-options.js +11 -0
  171. package/dist/components/wizard/step-stack-options.js.map +1 -0
  172. package/dist/components/wizard/step-stack.js +11 -0
  173. package/dist/components/wizard/step-stack.js.map +1 -0
  174. package/dist/components/wizard/wizard-tabs.js +11 -0
  175. package/dist/components/wizard/wizard-tabs.js.map +1 -0
  176. package/dist/components/wizard/wizard.js +20 -0
  177. package/dist/components/wizard/wizard.js.map +1 -0
  178. package/dist/hooks/init.js +41 -0
  179. package/dist/hooks/init.js.map +1 -0
  180. package/dist/index.js +10 -0
  181. package/dist/index.js.map +1 -0
  182. package/dist/magic-string.es-RGXYGAW3.js +1316 -0
  183. package/dist/magic-string.es-RGXYGAW3.js.map +1 -0
  184. package/dist/stores/wizard-store.js +10 -0
  185. package/dist/stores/wizard-store.js.map +1 -0
  186. package/dist/stores/wizard-store.test.js +405 -0
  187. package/dist/stores/wizard-store.test.js.map +1 -0
  188. package/package.json +44 -25
  189. package/dist/cli/index.js +0 -6314
  190. package/dist/cli/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli-v2/commands/build/marketplace.ts","../../../src/cli-v2/lib/marketplace-generator.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport {\n generateMarketplace,\n writeMarketplace,\n getMarketplaceStats,\n} from \"../../lib/marketplace-generator\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { DEFAULT_VERSION } from \"../../consts\";\n\nconst DEFAULT_PLUGINS_DIR = \"dist/plugins\";\nconst DEFAULT_OUTPUT_FILE = \".claude-plugin/marketplace.json\";\nconst DEFAULT_NAME = \"claude-collective\";\nconst DEFAULT_DESCRIPTION = \"Community skills and stacks for Claude Code\";\nconst DEFAULT_OWNER_NAME = \"Claude Collective\";\nconst DEFAULT_OWNER_EMAIL = \"hello@claude-collective.com\";\n\nexport default class BuildMarketplace extends BaseCommand {\n static summary =\n \"Generate marketplace.json from built plugins (requires skills repo)\";\n\n static description =\n \"Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks\",\n \"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json\",\n \"<%= config.bin %> <%= command.id %> --name my-marketplace --version 2.0.0\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n \"plugins-dir\": Flags.string({\n char: \"p\",\n description: \"Plugins directory\",\n default: DEFAULT_PLUGINS_DIR,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output file\",\n default: DEFAULT_OUTPUT_FILE,\n }),\n name: Flags.string({\n description: \"Marketplace name\",\n default: DEFAULT_NAME,\n }),\n version: Flags.string({\n description: \"Marketplace version\",\n default: DEFAULT_VERSION,\n }),\n description: Flags.string({\n description: \"Marketplace description\",\n default: DEFAULT_DESCRIPTION,\n }),\n \"owner-name\": Flags.string({\n description: \"Owner name\",\n default: DEFAULT_OWNER_NAME,\n }),\n \"owner-email\": Flags.string({\n description: \"Owner email\",\n default: DEFAULT_OWNER_EMAIL,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildMarketplace);\n\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const pluginsDir = path.resolve(projectRoot, flags[\"plugins-dir\"]);\n const outputPath = path.resolve(projectRoot, flags.output);\n\n this.log(\"\");\n this.log(\"Generating marketplace.json\");\n this.log(` Plugins directory: ${pluginsDir}`);\n this.log(` Output file: ${outputPath}`);\n this.log(\"\");\n\n try {\n this.log(\"Scanning plugins...\");\n\n const marketplace = await generateMarketplace(pluginsDir, {\n name: flags.name,\n version: flags.version,\n description: flags.description,\n ownerName: flags[\"owner-name\"],\n ownerEmail: flags[\"owner-email\"],\n pluginRoot: `./${flags[\"plugins-dir\"]}`,\n });\n\n const stats = getMarketplaceStats(marketplace);\n this.log(`Found ${stats.total} plugins`);\n\n this.log(\"\");\n this.log(\"Category breakdown:\");\n const sortedCategories = Object.entries(stats.byCategory).sort(\n ([, a], [, b]) => b - a,\n );\n for (const [category, count] of sortedCategories) {\n this.log(` ${category}: ${count}`);\n }\n\n this.log(\"Writing marketplace.json...\");\n await writeMarketplace(outputPath, marketplace);\n this.log(`Wrote ${outputPath}`);\n\n this.log(\"\");\n this.log(\"Sample plugins:\");\n const sampleSize = 5;\n for (const plugin of marketplace.plugins.slice(0, sampleSize)) {\n const version = plugin.version ? `v${plugin.version}` : \"\";\n const category = plugin.category ? `[${plugin.category}]` : \"\";\n this.log(` ${plugin.name} ${version} ${category}`);\n if (plugin.description) {\n this.log(` ${plugin.description}`);\n }\n }\n if (marketplace.plugins.length > sampleSize) {\n this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);\n }\n\n this.log(\"\");\n this.logSuccess(`Marketplace generated with ${stats.total} plugins!`);\n this.log(\"\");\n } catch (error) {\n this.log(\"Generation failed\");\n this.error(error instanceof Error ? error.message : String(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n}\n","import path from \"path\";\nimport { readFile, writeFile, glob, ensureDir } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport type {\n Marketplace,\n MarketplacePlugin,\n PluginManifest,\n} from \"../../types\";\n\nconst PLUGIN_MANIFEST_PATH = \".claude-plugin/plugin.json\";\nconst MARKETPLACE_SCHEMA_URL =\n \"https://anthropic.com/claude-code/marketplace.schema.json\";\n\n/**\n * Category patterns for marketplace plugins.\n *\n * With normalized skill IDs (e.g., \"web-framework-react\"), the category\n * is typically the first segment of the normalized ID:\n * - skill-web-* -> frontend (web skills)\n * - skill-api-* -> backend (api skills)\n * - skill-cli-* -> cli\n * - skill-meta-* -> methodology\n * - skill-infra-* -> infrastructure\n * - skill-mobile-* -> mobile\n * - skill-security-* -> security\n */\nconst CATEGORY_PATTERNS: Array<{ pattern: RegExp; category: string }> = [\n // Primary patterns based on normalized ID category prefix\n { pattern: /^skill-web-/, category: \"frontend\" },\n { pattern: /^skill-api-/, category: \"backend\" },\n { pattern: /^skill-cli-/, category: \"cli\" },\n { pattern: /^skill-meta-/, category: \"methodology\" },\n { pattern: /^skill-infra-/, category: \"infrastructure\" },\n { pattern: /^skill-mobile-/, category: \"mobile\" },\n { pattern: /^skill-security-/, category: \"security\" },\n // Fallback patterns for non-prefixed skills\n { pattern: /^skill-setup-/, category: \"setup\" },\n { pattern: /^skill-backend-/, category: \"backend\" },\n { pattern: /^skill-frontend-/, category: \"frontend\" },\n];\n\nexport interface MarketplaceOptions {\n name: string;\n version?: string;\n description?: string;\n ownerName: string;\n ownerEmail?: string;\n pluginRoot: string;\n}\n\nfunction inferCategory(pluginName: string): string | undefined {\n for (const { pattern, category } of CATEGORY_PATTERNS) {\n if (pattern.test(pluginName)) {\n return category;\n }\n }\n return undefined;\n}\n\nasync function readPluginManifest(\n pluginDir: string,\n): Promise<PluginManifest | null> {\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_PATH);\n\n try {\n const content = await readFile(manifestPath);\n return JSON.parse(content) as PluginManifest;\n } catch {\n return null;\n }\n}\n\nfunction toMarketplacePlugin(\n manifest: PluginManifest,\n pluginRoot: string,\n pluginDirName: string,\n): MarketplacePlugin {\n const category = inferCategory(manifest.name);\n\n const plugin: MarketplacePlugin = {\n name: manifest.name,\n source: `./${pluginRoot}/${pluginDirName}`,\n description: manifest.description,\n version: manifest.version,\n author: manifest.author,\n keywords: manifest.keywords,\n };\n\n if (category) {\n plugin.category = category;\n }\n\n return plugin;\n}\n\nexport async function generateMarketplace(\n pluginsDir: string,\n options: MarketplaceOptions,\n): Promise<Marketplace> {\n verbose(`Scanning plugins directory: ${pluginsDir}`);\n\n const manifestFiles = await glob(`**/${PLUGIN_MANIFEST_PATH}`, pluginsDir);\n verbose(`Found ${manifestFiles.length} plugin manifests`);\n\n const plugins: MarketplacePlugin[] = [];\n\n for (const manifestFile of manifestFiles) {\n const pluginDirName = manifestFile.split(\"/\")[0];\n const pluginDir = path.join(pluginsDir, pluginDirName);\n\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) {\n verbose(` [WARN] Could not read manifest: ${manifestFile}`);\n continue;\n }\n\n const plugin = toMarketplacePlugin(\n manifest,\n options.pluginRoot.replace(/^\\.\\//, \"\"),\n pluginDirName,\n );\n plugins.push(plugin);\n verbose(` [OK] ${plugin.name}`);\n }\n\n plugins.sort((a, b) => a.name.localeCompare(b.name));\n\n const marketplace: Marketplace = {\n $schema: MARKETPLACE_SCHEMA_URL,\n name: options.name,\n version: options.version ?? \"1.0.0\",\n owner: {\n name: options.ownerName,\n },\n metadata: {\n pluginRoot: options.pluginRoot,\n },\n plugins,\n };\n\n if (options.description) {\n marketplace.description = options.description;\n }\n\n if (options.ownerEmail) {\n marketplace.owner.email = options.ownerEmail;\n }\n\n return marketplace;\n}\n\nexport async function writeMarketplace(\n outputPath: string,\n marketplace: Marketplace,\n): Promise<void> {\n await ensureDir(path.dirname(outputPath));\n const content = JSON.stringify(marketplace, null, 2) + \"\\n\";\n await writeFile(outputPath, content);\n}\n\nexport function getMarketplaceStats(marketplace: Marketplace): {\n total: number;\n byCategory: Record<string, number>;\n} {\n const byCategory: Record<string, number> = {};\n\n for (const plugin of marketplace.plugins) {\n const category = plugin.category ?? \"uncategorized\";\n byCategory[category] = (byCategory[category] ?? 0) + 1;\n }\n\n return {\n total: marketplace.plugins.length,\n byCategory,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,aAAa;AACtB,OAAOA,WAAU;;;ACDjB;AAAA,OAAO,UAAU;AASjB,IAAM,uBAAuB;AAC7B,IAAM,yBACJ;AAeF,IAAM,oBAAkE;AAAA;AAAA,EAEtE,EAAE,SAAS,eAAe,UAAU,WAAW;AAAA,EAC/C,EAAE,SAAS,eAAe,UAAU,UAAU;AAAA,EAC9C,EAAE,SAAS,eAAe,UAAU,MAAM;AAAA,EAC1C,EAAE,SAAS,gBAAgB,UAAU,cAAc;AAAA,EACnD,EAAE,SAAS,iBAAiB,UAAU,iBAAiB;AAAA,EACvD,EAAE,SAAS,kBAAkB,UAAU,SAAS;AAAA,EAChD,EAAE,SAAS,oBAAoB,UAAU,WAAW;AAAA;AAAA,EAEpD,EAAE,SAAS,iBAAiB,UAAU,QAAQ;AAAA,EAC9C,EAAE,SAAS,mBAAmB,UAAU,UAAU;AAAA,EAClD,EAAE,SAAS,oBAAoB,UAAU,WAAW;AACtD;AAWA,SAAS,cAAc,YAAwC;AAC7D,aAAW,EAAE,SAAS,SAAS,KAAK,mBAAmB;AACrD,QAAI,QAAQ,KAAK,UAAU,GAAG;AAC5B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,mBACb,WACgC;AAChC,QAAM,eAAe,KAAK,KAAK,WAAW,oBAAoB;AAE9D,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,YAAY;AAC3C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,oBACP,UACA,YACA,eACmB;AACnB,QAAM,WAAW,cAAc,SAAS,IAAI;AAE5C,QAAM,SAA4B;AAAA,IAChC,MAAM,SAAS;AAAA,IACf,QAAQ,KAAK,UAAU,IAAI,aAAa;AAAA,IACxC,aAAa,SAAS;AAAA,IACtB,SAAS,SAAS;AAAA,IAClB,QAAQ,SAAS;AAAA,IACjB,UAAU,SAAS;AAAA,EACrB;AAEA,MAAI,UAAU;AACZ,WAAO,WAAW;AAAA,EACpB;AAEA,SAAO;AACT;AAEA,eAAsB,oBACpB,YACA,SACsB;AACtB,UAAQ,+BAA+B,UAAU,EAAE;AAEnD,QAAM,gBAAgB,MAAM,KAAK,MAAM,oBAAoB,IAAI,UAAU;AACzE,UAAQ,SAAS,cAAc,MAAM,mBAAmB;AAExD,QAAM,UAA+B,CAAC;AAEtC,aAAW,gBAAgB,eAAe;AACxC,UAAM,gBAAgB,aAAa,MAAM,GAAG,EAAE,CAAC;AAC/C,UAAM,YAAY,KAAK,KAAK,YAAY,aAAa;AAErD,UAAM,WAAW,MAAM,mBAAmB,SAAS;AACnD,QAAI,CAAC,UAAU;AACb,cAAQ,qCAAqC,YAAY,EAAE;AAC3D;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,QAAQ,WAAW,QAAQ,SAAS,EAAE;AAAA,MACtC;AAAA,IACF;AACA,YAAQ,KAAK,MAAM;AACnB,YAAQ,UAAU,OAAO,IAAI,EAAE;AAAA,EACjC;AAEA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAEnD,QAAM,cAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ,WAAW;AAAA,IAC5B,OAAO;AAAA,MACL,MAAM,QAAQ;AAAA,IAChB;AAAA,IACA,UAAU;AAAA,MACR,YAAY,QAAQ;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAEA,MAAI,QAAQ,aAAa;AACvB,gBAAY,cAAc,QAAQ;AAAA,EACpC;AAEA,MAAI,QAAQ,YAAY;AACtB,gBAAY,MAAM,QAAQ,QAAQ;AAAA,EACpC;AAEA,SAAO;AACT;AAEA,eAAsB,iBACpB,YACA,aACe;AACf,QAAM,UAAU,KAAK,QAAQ,UAAU,CAAC;AACxC,QAAM,UAAU,KAAK,UAAU,aAAa,MAAM,CAAC,IAAI;AACvD,QAAM,UAAU,YAAY,OAAO;AACrC;AAEO,SAAS,oBAAoB,aAGlC;AACA,QAAM,aAAqC,CAAC;AAE5C,aAAW,UAAU,YAAY,SAAS;AACxC,UAAM,WAAW,OAAO,YAAY;AACpC,eAAW,QAAQ,KAAK,WAAW,QAAQ,KAAK,KAAK;AAAA,EACvD;AAEA,SAAO;AAAA,IACL,OAAO,YAAY,QAAQ;AAAA,IAC3B;AAAA,EACF;AACF;;;ADnKA,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAC5B,IAAM,eAAe;AACrB,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAE5B,IAAqB,mBAArB,MAAqB,0BAAyB,YAAY;AAAA,EACxD,OAAO,UACL;AAAA,EAEF,OAAO,cACL;AAAA,EAEF,OAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,GAAG,YAAY;AAAA,IACf,eAAe,MAAM,OAAO;AAAA,MAC1B,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,MAAM,MAAM,OAAO;AAAA,MACjB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,SAAS,MAAM,OAAO;AAAA,MACpB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,aAAa,MAAM,OAAO;AAAA,MACxB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,cAAc,MAAM,OAAO;AAAA,MACzB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,eAAe,MAAM,OAAO;AAAA,MAC1B,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,SAAS,MAAM,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,iBAAgB;AAEnD,eAAW,MAAM,OAAO;AAExB,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,aAAaC,MAAK,QAAQ,aAAa,MAAM,aAAa,CAAC;AACjE,UAAM,aAAaA,MAAK,QAAQ,aAAa,MAAM,MAAM;AAEzD,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,6BAA6B;AACtC,SAAK,IAAI,wBAAwB,UAAU,EAAE;AAC7C,SAAK,IAAI,kBAAkB,UAAU,EAAE;AACvC,SAAK,IAAI,EAAE;AAEX,QAAI;AACF,WAAK,IAAI,qBAAqB;AAE9B,YAAM,cAAc,MAAM,oBAAoB,YAAY;AAAA,QACxD,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,aAAa,MAAM;AAAA,QACnB,WAAW,MAAM,YAAY;AAAA,QAC7B,YAAY,MAAM,aAAa;AAAA,QAC/B,YAAY,KAAK,MAAM,aAAa,CAAC;AAAA,MACvC,CAAC;AAED,YAAM,QAAQ,oBAAoB,WAAW;AAC7C,WAAK,IAAI,SAAS,MAAM,KAAK,UAAU;AAEvC,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,qBAAqB;AAC9B,YAAM,mBAAmB,OAAO,QAAQ,MAAM,UAAU,EAAE;AAAA,QACxD,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI;AAAA,MACxB;AACA,iBAAW,CAAC,UAAU,KAAK,KAAK,kBAAkB;AAChD,aAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,EAAE;AAAA,MACpC;AAEA,WAAK,IAAI,6BAA6B;AACtC,YAAM,iBAAiB,YAAY,WAAW;AAC9C,WAAK,IAAI,SAAS,UAAU,EAAE;AAE9B,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,iBAAiB;AAC1B,YAAM,aAAa;AACnB,iBAAW,UAAU,YAAY,QAAQ,MAAM,GAAG,UAAU,GAAG;AAC7D,cAAM,UAAU,OAAO,UAAU,IAAI,OAAO,OAAO,KAAK;AACxD,cAAM,WAAW,OAAO,WAAW,IAAI,OAAO,QAAQ,MAAM;AAC5D,aAAK,IAAI,KAAK,OAAO,IAAI,IAAI,OAAO,IAAI,QAAQ,EAAE;AAClD,YAAI,OAAO,aAAa;AACtB,eAAK,IAAI,OAAO,OAAO,WAAW,EAAE;AAAA,QACtC;AAAA,MACF;AACA,UAAI,YAAY,QAAQ,SAAS,YAAY;AAC3C,aAAK,IAAI,aAAa,YAAY,QAAQ,SAAS,UAAU,OAAO;AAAA,MACtE;AAEA,WAAK,IAAI,EAAE;AACX,WAAK,WAAW,8BAA8B,MAAM,KAAK,WAAW;AACpE,WAAK,IAAI,EAAE;AAAA,IACb,SAAS,OAAO;AACd,WAAK,IAAI,mBAAmB;AAC5B,WAAK,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;AAAA,QACjE,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":["path","path"]}
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ generateSkillPluginManifest,
4
+ getPluginManifestPath,
5
+ writePluginManifest
6
+ } from "../../chunk-LQTST4WY.js";
7
+ import {
8
+ hashSkillFolder
9
+ } from "../../chunk-MJSFR562.js";
10
+ import {
11
+ DEFAULT_VERSION,
12
+ DIRS
13
+ } from "../../chunk-A3J6IAXK.js";
14
+ import {
15
+ BaseCommand,
16
+ EXIT_CODES
17
+ } from "../../chunk-SYQ7R2JO.js";
18
+ import {
19
+ setVerbose,
20
+ verbose
21
+ } from "../../chunk-TOPAIL5W.js";
22
+ import {
23
+ copy,
24
+ ensureDir,
25
+ fileExists,
26
+ glob,
27
+ readFile,
28
+ writeFile
29
+ } from "../../chunk-MMDXNZPF.js";
30
+ import {
31
+ init_esm_shims
32
+ } from "../../chunk-DHET7RCE.js";
33
+
34
+ // src/cli-v2/commands/build/plugins.ts
35
+ init_esm_shims();
36
+ import { Flags } from "@oclif/core";
37
+ import path2 from "path";
38
+
39
+ // src/cli-v2/lib/skill-plugin-compiler.ts
40
+ init_esm_shims();
41
+ import path from "path";
42
+ import { parse as parseYaml } from "yaml";
43
+ var FRONTMATTER_REGEX = /^---\n([\s\S]*?)\n---/;
44
+ var SKILL_FILES = ["SKILL.md", "reference.md"];
45
+ var SKILL_DIRS = ["examples", "scripts"];
46
+ function parseFrontmatter(content) {
47
+ const match = content.match(FRONTMATTER_REGEX);
48
+ if (!match) return null;
49
+ const yamlContent = match[1];
50
+ const frontmatter = parseYaml(yamlContent);
51
+ if (!frontmatter.name || !frontmatter.description) return null;
52
+ return frontmatter;
53
+ }
54
+ function sanitizeSkillName(name) {
55
+ return name.replace(/\+/g, "-");
56
+ }
57
+ function parseMajorVersion(version) {
58
+ const match = version.match(/^(\d+)\./);
59
+ return match ? parseInt(match[1], 10) : 1;
60
+ }
61
+ function bumpMajorVersion(version) {
62
+ const major = parseMajorVersion(version);
63
+ return `${major + 1}.0.0`;
64
+ }
65
+ var CONTENT_HASH_FILE = ".content-hash";
66
+ async function readExistingManifest(pluginDir) {
67
+ const manifestPath = getPluginManifestPath(pluginDir);
68
+ if (!await fileExists(manifestPath)) {
69
+ return null;
70
+ }
71
+ try {
72
+ const content = await readFile(manifestPath);
73
+ const manifest = JSON.parse(content);
74
+ const hashFilePath = manifestPath.replace("plugin.json", CONTENT_HASH_FILE);
75
+ let contentHash;
76
+ if (await fileExists(hashFilePath)) {
77
+ contentHash = (await readFile(hashFilePath)).trim();
78
+ }
79
+ return {
80
+ version: manifest.version ?? DEFAULT_VERSION,
81
+ contentHash
82
+ };
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+ async function determineVersion(skillPath, pluginDir) {
88
+ const newHash = await hashSkillFolder(skillPath);
89
+ const existing = await readExistingManifest(pluginDir);
90
+ if (!existing) {
91
+ return {
92
+ version: DEFAULT_VERSION,
93
+ contentHash: newHash
94
+ };
95
+ }
96
+ if (existing.contentHash !== newHash) {
97
+ return {
98
+ version: bumpMajorVersion(existing.version),
99
+ contentHash: newHash
100
+ };
101
+ }
102
+ return {
103
+ version: existing.version,
104
+ contentHash: newHash
105
+ };
106
+ }
107
+ async function readSkillMetadata(skillPath) {
108
+ const metadataPath = path.join(skillPath, "metadata.yaml");
109
+ if (!await fileExists(metadataPath)) {
110
+ return null;
111
+ }
112
+ try {
113
+ const content = await readFile(metadataPath);
114
+ const lines = content.split("\n");
115
+ const yamlContent = lines[0]?.startsWith("# yaml-language-server:") ? lines.slice(1).join("\n") : content;
116
+ return parseYaml(yamlContent);
117
+ } catch {
118
+ return null;
119
+ }
120
+ }
121
+ function generateReadme(skillName, frontmatter, metadata) {
122
+ const lines = [];
123
+ lines.push(`# ${skillName}`);
124
+ lines.push("");
125
+ lines.push(frontmatter.description);
126
+ lines.push("");
127
+ if (metadata?.tags && metadata.tags.length > 0) {
128
+ lines.push("## Tags");
129
+ lines.push("");
130
+ lines.push(metadata.tags.map((t) => `\`${t}\``).join(" "));
131
+ lines.push("");
132
+ }
133
+ lines.push("## Installation");
134
+ lines.push("");
135
+ lines.push("Add this plugin to your Claude Code configuration:");
136
+ lines.push("");
137
+ lines.push("```json");
138
+ lines.push(`{`);
139
+ lines.push(` "plugins": ["skill-${skillName}"]`);
140
+ lines.push(`}`);
141
+ lines.push("```");
142
+ lines.push("");
143
+ lines.push("## Usage");
144
+ lines.push("");
145
+ lines.push(`This skill is automatically available when installed.`);
146
+ if (metadata?.requires && metadata.requires.length > 0) {
147
+ lines.push("");
148
+ lines.push("**Requires:** " + metadata.requires.join(", "));
149
+ }
150
+ lines.push("");
151
+ lines.push("---");
152
+ lines.push("");
153
+ lines.push("*Generated by Claude Collective skill-plugin-compiler*");
154
+ lines.push("");
155
+ return lines.join("\n");
156
+ }
157
+ async function compileSkillPlugin(options) {
158
+ const { skillPath, outputDir, skillName: overrideName } = options;
159
+ const dirBasename = path.basename(skillPath);
160
+ const skillMdPath = path.join(skillPath, "SKILL.md");
161
+ if (!await fileExists(skillMdPath)) {
162
+ throw new Error(
163
+ `Skill '${dirBasename}' is missing required SKILL.md file. Expected at: ${skillMdPath}`
164
+ );
165
+ }
166
+ const skillMdContent = await readFile(skillMdPath);
167
+ const frontmatter = parseFrontmatter(skillMdContent);
168
+ if (!frontmatter) {
169
+ throw new Error(
170
+ `Skill '${dirBasename}' has invalid or missing YAML frontmatter in SKILL.md. Required fields: 'name' and 'description'. File: ${skillMdPath}`
171
+ );
172
+ }
173
+ const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);
174
+ verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);
175
+ const metadata = await readSkillMetadata(skillPath);
176
+ const pluginDir = path.join(outputDir, `skill-${skillName}`);
177
+ const skillsDir = path.join(pluginDir, "skills", skillName);
178
+ await ensureDir(pluginDir);
179
+ await ensureDir(skillsDir);
180
+ const { version, contentHash } = await determineVersion(skillPath, pluginDir);
181
+ const manifest = generateSkillPluginManifest({
182
+ skillName,
183
+ description: frontmatter.description,
184
+ author: metadata?.author,
185
+ version,
186
+ keywords: metadata?.tags
187
+ });
188
+ await writePluginManifest(pluginDir, manifest);
189
+ const hashFilePath = getPluginManifestPath(pluginDir).replace(
190
+ "plugin.json",
191
+ CONTENT_HASH_FILE
192
+ );
193
+ await writeFile(hashFilePath, contentHash);
194
+ verbose(` Wrote plugin.json for ${skillName} (v${version})`);
195
+ await writeFile(path.join(skillsDir, "SKILL.md"), skillMdContent);
196
+ verbose(` Copied SKILL.md`);
197
+ for (const fileName of SKILL_FILES) {
198
+ if (fileName === "SKILL.md") continue;
199
+ const sourcePath = path.join(skillPath, fileName);
200
+ if (await fileExists(sourcePath)) {
201
+ const content = await readFile(sourcePath);
202
+ await writeFile(path.join(skillsDir, fileName), content);
203
+ verbose(` Copied ${fileName}`);
204
+ }
205
+ }
206
+ for (const dirName of SKILL_DIRS) {
207
+ const sourceDir = path.join(skillPath, dirName);
208
+ if (await fileExists(sourceDir)) {
209
+ await copy(sourceDir, path.join(skillsDir, dirName));
210
+ verbose(` Copied ${dirName}/`);
211
+ }
212
+ }
213
+ const readme = generateReadme(skillName, frontmatter, metadata);
214
+ await writeFile(path.join(pluginDir, "README.md"), readme);
215
+ verbose(` Generated README.md`);
216
+ return {
217
+ pluginPath: pluginDir,
218
+ manifest,
219
+ skillName
220
+ };
221
+ }
222
+ async function compileAllSkillPlugins(skillsDir, outputDir) {
223
+ const results = [];
224
+ const skillMdFiles = await glob("**/SKILL.md", skillsDir);
225
+ for (const skillMdFile of skillMdFiles) {
226
+ const skillPath = path.join(skillsDir, path.dirname(skillMdFile));
227
+ try {
228
+ const result = await compileSkillPlugin({
229
+ skillPath,
230
+ outputDir
231
+ });
232
+ results.push(result);
233
+ console.log(` [OK] skill-${result.skillName}`);
234
+ } catch (error) {
235
+ const errorMessage = error instanceof Error ? error.message : String(error);
236
+ const dirBasename = path.basename(skillPath);
237
+ console.warn(
238
+ ` [WARN] Failed to compile skill from ${dirBasename}: ${errorMessage}`
239
+ );
240
+ }
241
+ }
242
+ return results;
243
+ }
244
+ function printCompilationSummary(results) {
245
+ console.log(`
246
+ Compiled ${results.length} skill plugins:`);
247
+ for (const result of results) {
248
+ console.log(` - skill-${result.skillName} (v${result.manifest.version})`);
249
+ }
250
+ }
251
+
252
+ // src/cli-v2/commands/build/plugins.ts
253
+ var DEFAULT_OUTPUT_DIR = "dist/plugins";
254
+ var BuildPlugins = class _BuildPlugins extends BaseCommand {
255
+ static summary = "Build skills into standalone plugins (requires skills repo)";
256
+ static description = "Build skills into standalone plugins. By default, compiles all skills. Use --skill to compile a specific skill only.";
257
+ static examples = [
258
+ "<%= config.bin %> <%= command.id %>",
259
+ "<%= config.bin %> <%= command.id %> --skill cli-commander",
260
+ "<%= config.bin %> <%= command.id %> --skills-dir ./src/skills --output-dir ./plugins",
261
+ "<%= config.bin %> <%= command.id %> --verbose"
262
+ ];
263
+ static flags = {
264
+ ...BaseCommand.baseFlags,
265
+ "skills-dir": Flags.string({
266
+ char: "s",
267
+ description: "Skills source directory",
268
+ default: DIRS.skills
269
+ }),
270
+ "output-dir": Flags.string({
271
+ char: "o",
272
+ description: "Output directory",
273
+ default: DEFAULT_OUTPUT_DIR
274
+ }),
275
+ skill: Flags.string({
276
+ description: "Compile only a specific skill (path to skill directory)"
277
+ }),
278
+ verbose: Flags.boolean({
279
+ char: "v",
280
+ description: "Enable verbose logging",
281
+ default: false
282
+ })
283
+ };
284
+ async run() {
285
+ const { flags } = await this.parse(_BuildPlugins);
286
+ setVerbose(flags.verbose);
287
+ const projectRoot = process.cwd();
288
+ const skillsDir = path2.resolve(projectRoot, flags["skills-dir"]);
289
+ const outputDir = path2.resolve(projectRoot, flags["output-dir"]);
290
+ this.log("");
291
+ this.log("Compiling skill plugins");
292
+ this.log(` Skills directory: ${skillsDir}`);
293
+ this.log(` Output directory: ${outputDir}`);
294
+ this.log("");
295
+ try {
296
+ if (flags.skill) {
297
+ const skillPath = path2.resolve(skillsDir, flags.skill);
298
+ this.log(`Compiling skill at ${skillPath}...`);
299
+ const result = await compileSkillPlugin({
300
+ skillPath,
301
+ outputDir
302
+ });
303
+ this.log(`Compiled skill-${result.skillName}`);
304
+ this.log(` Plugin path: ${result.pluginPath}`);
305
+ } else {
306
+ this.log("Finding and compiling all skills...");
307
+ const results = await compileAllSkillPlugins(skillsDir, outputDir);
308
+ this.log(`Compiled ${results.length} skill plugins`);
309
+ printCompilationSummary(results);
310
+ }
311
+ this.log("");
312
+ this.logSuccess("Plugin compilation complete!");
313
+ } catch (error) {
314
+ this.log("Compilation failed");
315
+ this.error(error instanceof Error ? error.message : String(error), {
316
+ exit: EXIT_CODES.ERROR
317
+ });
318
+ }
319
+ }
320
+ };
321
+ export {
322
+ BuildPlugins as default
323
+ };
324
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli-v2/commands/build/plugins.ts","../../../src/cli-v2/lib/skill-plugin-compiler.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport { DIRS } from \"../../consts\";\nimport {\n compileAllSkillPlugins,\n compileSkillPlugin,\n printCompilationSummary,\n} from \"../../lib/skill-plugin-compiler\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\n\nconst DEFAULT_OUTPUT_DIR = \"dist/plugins\";\n\nexport default class BuildPlugins extends BaseCommand {\n static summary =\n \"Build skills into standalone plugins (requires skills repo)\";\n\n static description =\n \"Build skills into standalone plugins. By default, compiles all skills. Use --skill to compile a specific skill only.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --skill cli-commander\",\n \"<%= config.bin %> <%= command.id %> --skills-dir ./src/skills --output-dir ./plugins\",\n \"<%= config.bin %> <%= command.id %> --verbose\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n \"skills-dir\": Flags.string({\n char: \"s\",\n description: \"Skills source directory\",\n default: DIRS.skills,\n }),\n \"output-dir\": Flags.string({\n char: \"o\",\n description: \"Output directory\",\n default: DEFAULT_OUTPUT_DIR,\n }),\n skill: Flags.string({\n description: \"Compile only a specific skill (path to skill directory)\",\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildPlugins);\n\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const skillsDir = path.resolve(projectRoot, flags[\"skills-dir\"]);\n const outputDir = path.resolve(projectRoot, flags[\"output-dir\"]);\n\n this.log(\"\");\n this.log(\"Compiling skill plugins\");\n this.log(` Skills directory: ${skillsDir}`);\n this.log(` Output directory: ${outputDir}`);\n this.log(\"\");\n\n try {\n if (flags.skill) {\n const skillPath = path.resolve(skillsDir, flags.skill);\n this.log(`Compiling skill at ${skillPath}...`);\n\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n\n this.log(`Compiled skill-${result.skillName}`);\n this.log(` Plugin path: ${result.pluginPath}`);\n } else {\n this.log(\"Finding and compiling all skills...\");\n\n const results = await compileAllSkillPlugins(skillsDir, outputDir);\n\n this.log(`Compiled ${results.length} skill plugins`);\n printCompilationSummary(results);\n }\n\n this.log(\"\");\n this.logSuccess(\"Plugin compilation complete!\");\n } catch (error) {\n this.log(\"Compilation failed\");\n this.error(error instanceof Error ? error.message : String(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n}\n","import path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport {\n readFile,\n writeFile,\n ensureDir,\n glob,\n fileExists,\n copy,\n} from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport {\n generateSkillPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"./plugin-manifest\";\nimport { hashSkillFolder } from \"./versioning\";\nimport { DEFAULT_VERSION } from \"../consts\";\nimport type {\n PluginManifest,\n SkillFrontmatter,\n SkillMetadataConfig,\n} from \"../../types\";\n\nexport interface SkillPluginOptions {\n skillPath: string;\n outputDir: string;\n skillName?: string;\n}\n\nexport interface CompiledSkillPlugin {\n pluginPath: string;\n manifest: PluginManifest;\n skillName: string;\n}\n\nconst FRONTMATTER_REGEX = /^---\\n([\\s\\S]*?)\\n---/;\n\nconst SKILL_FILES = [\"SKILL.md\", \"reference.md\"] as const;\n\nconst SKILL_DIRS = [\"examples\", \"scripts\"] as const;\n\nfunction parseFrontmatter(content: string): SkillFrontmatter | null {\n const match = content.match(FRONTMATTER_REGEX);\n if (!match) return null;\n\n const yamlContent = match[1];\n const frontmatter = parseYaml(yamlContent) as SkillFrontmatter;\n\n if (!frontmatter.name || !frontmatter.description) return null;\n return frontmatter;\n}\n\nfunction sanitizeSkillName(name: string): string {\n return name.replace(/\\+/g, \"-\");\n}\n\nfunction parseMajorVersion(version: string): number {\n const match = version.match(/^(\\d+)\\./);\n return match ? parseInt(match[1], 10) : 1;\n}\n\nfunction bumpMajorVersion(version: string): string {\n const major = parseMajorVersion(version);\n return `${major + 1}.0.0`;\n}\n\nconst CONTENT_HASH_FILE = \".content-hash\";\n\nasync function readExistingManifest(\n pluginDir: string,\n): Promise<{ version: string; contentHash: string | undefined } | null> {\n const manifestPath = getPluginManifestPath(pluginDir);\n\n if (!(await fileExists(manifestPath))) {\n return null;\n }\n\n try {\n const content = await readFile(manifestPath);\n const manifest = JSON.parse(content) as PluginManifest;\n\n const hashFilePath = manifestPath.replace(\"plugin.json\", CONTENT_HASH_FILE);\n let contentHash: string | undefined;\n if (await fileExists(hashFilePath)) {\n contentHash = (await readFile(hashFilePath)).trim();\n }\n\n return {\n version: manifest.version ?? DEFAULT_VERSION,\n contentHash,\n };\n } catch {\n return null;\n }\n}\n\nasync function determineVersion(\n skillPath: string,\n pluginDir: string,\n): Promise<{ version: string; contentHash: string }> {\n const newHash = await hashSkillFolder(skillPath);\n\n const existing = await readExistingManifest(pluginDir);\n\n if (!existing) {\n return {\n version: DEFAULT_VERSION,\n contentHash: newHash,\n };\n }\n\n if (existing.contentHash !== newHash) {\n return {\n version: bumpMajorVersion(existing.version),\n contentHash: newHash,\n };\n }\n\n return {\n version: existing.version,\n contentHash: newHash,\n };\n}\n\n/**\n * @deprecated Legacy function - skill names now come from SKILL.md frontmatter.name\n * Keeping for backwards compatibility with any external callers.\n */\nexport function extractSkillName(skillPath: string): string {\n const dirName = path.basename(skillPath);\n return sanitizeSkillName(dirName);\n}\n\n/**\n * @deprecated Legacy function - categories no longer used with flat directory structure.\n * Always returns undefined.\n */\nexport function extractCategory(\n _skillPath: string,\n _skillsRoot: string,\n): string | undefined {\n return undefined;\n}\n\n/**\n * @deprecated Legacy function - author info now comes from metadata.yaml.\n * Always returns undefined.\n */\nexport function extractAuthor(_skillPath: string): string | undefined {\n return undefined;\n}\n\nasync function readSkillMetadata(\n skillPath: string,\n): Promise<SkillMetadataConfig | null> {\n const metadataPath = path.join(skillPath, \"metadata.yaml\");\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n try {\n const content = await readFile(metadataPath);\n const lines = content.split(\"\\n\");\n const yamlContent = lines[0]?.startsWith(\"# yaml-language-server:\")\n ? lines.slice(1).join(\"\\n\")\n : content;\n\n return parseYaml(yamlContent) as SkillMetadataConfig;\n } catch {\n return null;\n }\n}\n\nfunction generateReadme(\n skillName: string,\n frontmatter: SkillFrontmatter,\n metadata: SkillMetadataConfig | null,\n): string {\n const lines: string[] = [];\n\n lines.push(`# ${skillName}`);\n lines.push(\"\");\n lines.push(frontmatter.description);\n lines.push(\"\");\n\n if (metadata?.tags && metadata.tags.length > 0) {\n lines.push(\"## Tags\");\n lines.push(\"\");\n lines.push(metadata.tags.map((t) => `\\`${t}\\``).join(\" \"));\n lines.push(\"\");\n }\n\n lines.push(\"## Installation\");\n lines.push(\"\");\n lines.push(\"Add this plugin to your Claude Code configuration:\");\n lines.push(\"\");\n lines.push(\"```json\");\n lines.push(`{`);\n lines.push(` \"plugins\": [\"skill-${skillName}\"]`);\n lines.push(`}`);\n lines.push(\"```\");\n lines.push(\"\");\n\n lines.push(\"## Usage\");\n lines.push(\"\");\n lines.push(`This skill is automatically available when installed.`);\n if (metadata?.requires && metadata.requires.length > 0) {\n lines.push(\"\");\n lines.push(\"**Requires:** \" + metadata.requires.join(\", \"));\n }\n lines.push(\"\");\n\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(\"*Generated by Claude Collective skill-plugin-compiler*\");\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\nexport async function compileSkillPlugin(\n options: SkillPluginOptions,\n): Promise<CompiledSkillPlugin> {\n const { skillPath, outputDir, skillName: overrideName } = options;\n\n // Use directory basename for initial error messages before frontmatter is parsed\n const dirBasename = path.basename(skillPath);\n\n const skillMdPath = path.join(skillPath, \"SKILL.md\");\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\n `Skill '${dirBasename}' is missing required SKILL.md file. Expected at: ${skillMdPath}`,\n );\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent);\n\n if (!frontmatter) {\n throw new Error(\n `Skill '${dirBasename}' has invalid or missing YAML frontmatter in SKILL.md. ` +\n `Required fields: 'name' and 'description'. File: ${skillMdPath}`,\n );\n }\n\n // Use frontmatter.name as the canonical skill name (source of truth)\n // Override name takes precedence if explicitly provided\n const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);\n\n verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);\n\n const metadata = await readSkillMetadata(skillPath);\n\n const pluginDir = path.join(outputDir, `skill-${skillName}`);\n const skillsDir = path.join(pluginDir, \"skills\", skillName);\n\n await ensureDir(pluginDir);\n await ensureDir(skillsDir);\n\n const { version, contentHash } = await determineVersion(skillPath, pluginDir);\n\n const manifest = generateSkillPluginManifest({\n skillName,\n description: frontmatter.description,\n author: metadata?.author,\n version,\n keywords: metadata?.tags,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n const hashFilePath = getPluginManifestPath(pluginDir).replace(\n \"plugin.json\",\n CONTENT_HASH_FILE,\n );\n await writeFile(hashFilePath, contentHash);\n\n verbose(` Wrote plugin.json for ${skillName} (v${version})`);\n\n await writeFile(path.join(skillsDir, \"SKILL.md\"), skillMdContent);\n verbose(` Copied SKILL.md`);\n\n for (const fileName of SKILL_FILES) {\n if (fileName === \"SKILL.md\") continue;\n\n const sourcePath = path.join(skillPath, fileName);\n if (await fileExists(sourcePath)) {\n const content = await readFile(sourcePath);\n await writeFile(path.join(skillsDir, fileName), content);\n verbose(` Copied ${fileName}`);\n }\n }\n\n for (const dirName of SKILL_DIRS) {\n const sourceDir = path.join(skillPath, dirName);\n if (await fileExists(sourceDir)) {\n await copy(sourceDir, path.join(skillsDir, dirName));\n verbose(` Copied ${dirName}/`);\n }\n }\n\n const readme = generateReadme(skillName, frontmatter, metadata);\n await writeFile(path.join(pluginDir, \"README.md\"), readme);\n verbose(` Generated README.md`);\n\n return {\n pluginPath: pluginDir,\n manifest,\n skillName,\n };\n}\n\nexport async function compileAllSkillPlugins(\n skillsDir: string,\n outputDir: string,\n): Promise<CompiledSkillPlugin[]> {\n const results: CompiledSkillPlugin[] = [];\n\n const skillMdFiles = await glob(\"**/SKILL.md\", skillsDir);\n\n for (const skillMdFile of skillMdFiles) {\n const skillPath = path.join(skillsDir, path.dirname(skillMdFile));\n\n try {\n // compileSkillPlugin uses frontmatter.name as the canonical skill name\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n results.push(result);\n console.log(` [OK] skill-${result.skillName}`);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const dirBasename = path.basename(skillPath);\n console.warn(\n ` [WARN] Failed to compile skill from ${dirBasename}: ${errorMessage}`,\n );\n }\n }\n\n return results;\n}\n\nexport function printCompilationSummary(results: CompiledSkillPlugin[]): void {\n console.log(`\\nCompiled ${results.length} skill plugins:`);\n for (const result of results) {\n console.log(` - skill-${result.skillName} (v${result.manifest.version})`);\n }\n}\n"],"mappings":"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","names":["path","path"]}
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getAgentDefinitions
4
+ } from "../../chunk-C4ZTIYFR.js";
5
+ import {
6
+ compileStackPlugin,
7
+ printStackCompilationSummary
8
+ } from "../../chunk-Q2LH2DAB.js";
9
+ import "../../chunk-LQTST4WY.js";
10
+ import "../../chunk-MJSFR562.js";
11
+ import "../../chunk-SEBPPFUW.js";
12
+ import {
13
+ loadStacks
14
+ } from "../../chunk-QGGSLMO3.js";
15
+ import "../../chunk-NGBFJJ7Q.js";
16
+ import "../../chunk-QESUUPOE.js";
17
+ import {
18
+ PROJECT_ROOT
19
+ } from "../../chunk-A3J6IAXK.js";
20
+ import {
21
+ BaseCommand,
22
+ EXIT_CODES
23
+ } from "../../chunk-SYQ7R2JO.js";
24
+ import {
25
+ setVerbose
26
+ } from "../../chunk-TOPAIL5W.js";
27
+ import "../../chunk-MMDXNZPF.js";
28
+ import {
29
+ init_esm_shims
30
+ } from "../../chunk-DHET7RCE.js";
31
+
32
+ // src/cli-v2/commands/build/stack.tsx
33
+ init_esm_shims();
34
+ import { Flags } from "@oclif/core";
35
+ import { render, Box, Text } from "ink";
36
+ import { Select } from "@inkjs/ui";
37
+ import path from "path";
38
+ import { jsx, jsxs } from "react/jsx-runtime";
39
+ var DEFAULT_OUTPUT_DIR = "dist/stacks";
40
+ var StackSelector = ({
41
+ availableStacks,
42
+ onSelect
43
+ }) => {
44
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
45
+ /* @__PURE__ */ jsx(Text, { children: "Select a stack to compile:" }),
46
+ /* @__PURE__ */ jsx(
47
+ Select,
48
+ {
49
+ options: availableStacks.map((name) => ({
50
+ value: name,
51
+ label: name
52
+ })),
53
+ onChange: (value) => {
54
+ onSelect(value);
55
+ }
56
+ }
57
+ )
58
+ ] });
59
+ };
60
+ var BuildStack = class _BuildStack extends BaseCommand {
61
+ static summary = "Build a stack into a standalone plugin";
62
+ static description = "Build a stack into a standalone plugin (requires skills repo). If no stack is specified, you will be prompted to select one.";
63
+ static examples = [
64
+ "<%= config.bin %> <%= command.id %>",
65
+ "<%= config.bin %> <%= command.id %> --stack frontend-stack",
66
+ "<%= config.bin %> <%= command.id %> --stack frontend-stack --output-dir ./plugins",
67
+ "<%= config.bin %> <%= command.id %> --agent-source /path/to/agents --refresh"
68
+ ];
69
+ static flags = {
70
+ ...BaseCommand.baseFlags,
71
+ stack: Flags.string({
72
+ description: "Stack ID to compile (directory name in src/stacks/)"
73
+ }),
74
+ "output-dir": Flags.string({
75
+ char: "o",
76
+ description: "Output directory",
77
+ default: DEFAULT_OUTPUT_DIR
78
+ }),
79
+ "agent-source": Flags.string({
80
+ description: "Agent partials source (default: local CLI)"
81
+ }),
82
+ refresh: Flags.boolean({
83
+ description: "Force refresh remote agent source",
84
+ default: false
85
+ }),
86
+ verbose: Flags.boolean({
87
+ char: "v",
88
+ description: "Enable verbose logging",
89
+ default: false
90
+ })
91
+ };
92
+ async run() {
93
+ const { flags } = await this.parse(_BuildStack);
94
+ setVerbose(flags.verbose);
95
+ const projectRoot = process.cwd();
96
+ const outputDir = path.resolve(projectRoot, flags["output-dir"]);
97
+ let stackId = flags.stack;
98
+ if (!stackId) {
99
+ const stacks = await loadStacks(projectRoot);
100
+ const availableStacks = stacks.map((s) => s.id).sort();
101
+ if (availableStacks.length === 0) {
102
+ this.error(`No stacks found in config/stacks.yaml`, {
103
+ exit: EXIT_CODES.ERROR
104
+ });
105
+ }
106
+ stackId = await new Promise((resolve, reject) => {
107
+ const { waitUntilExit } = render(
108
+ /* @__PURE__ */ jsx(
109
+ StackSelector,
110
+ {
111
+ availableStacks,
112
+ onSelect: (selected) => {
113
+ resolve(selected);
114
+ }
115
+ }
116
+ )
117
+ );
118
+ waitUntilExit().catch(reject);
119
+ }).catch(() => {
120
+ this.log("Cancelled");
121
+ this.exit(EXIT_CODES.CANCELLED);
122
+ });
123
+ }
124
+ this.log("");
125
+ this.log(`Compiling stack plugin: ${stackId}`);
126
+ this.log(` Output directory: ${outputDir}`);
127
+ this.log("");
128
+ let agentSourcePath;
129
+ try {
130
+ this.log(
131
+ flags["agent-source"] ? "Fetching agent partials..." : "Loading agent partials..."
132
+ );
133
+ const agentDefs = await getAgentDefinitions(flags["agent-source"], {
134
+ forceRefresh: flags.refresh
135
+ });
136
+ agentSourcePath = agentDefs.sourcePath;
137
+ this.log(
138
+ flags["agent-source"] ? `Agent partials fetched from: ${flags["agent-source"]}` : `Agent partials loaded from: ${PROJECT_ROOT}`
139
+ );
140
+ } catch (error) {
141
+ this.log("Failed to load agent partials");
142
+ this.error(error instanceof Error ? error.message : String(error), {
143
+ exit: EXIT_CODES.ERROR
144
+ });
145
+ }
146
+ try {
147
+ this.log(`Compiling stack "${stackId}"...`);
148
+ const result = await compileStackPlugin({
149
+ stackId,
150
+ outputDir,
151
+ projectRoot,
152
+ agentSourcePath
153
+ });
154
+ this.log(`Compiled stack plugin: ${result.stackName}`);
155
+ printStackCompilationSummary(result);
156
+ this.log("");
157
+ this.logSuccess("Stack plugin compilation complete!");
158
+ } catch (error) {
159
+ this.log("Compilation failed");
160
+ this.error(error instanceof Error ? error.message : String(error), {
161
+ exit: EXIT_CODES.ERROR
162
+ });
163
+ }
164
+ }
165
+ };
166
+ export {
167
+ BuildStack as default
168
+ };
169
+ //# sourceMappingURL=stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli-v2/commands/build/stack.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text } from \"ink\";\nimport { Select } from \"@inkjs/ui\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport { PROJECT_ROOT } from \"../../consts\";\nimport {\n compileStackPlugin,\n printStackCompilationSummary,\n} from \"../../lib/stack-plugin-compiler\";\nimport { getAgentDefinitions } from \"../../lib/agent-fetcher\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { loadStacks } from \"../../lib/stacks-loader\";\n\nconst DEFAULT_OUTPUT_DIR = \"dist/stacks\";\n\ninterface StackSelectorProps {\n availableStacks: string[];\n onSelect: (stackId: string) => void;\n}\n\nconst StackSelector: React.FC<StackSelectorProps> = ({\n availableStacks,\n onSelect,\n}) => {\n return (\n <Box flexDirection=\"column\">\n <Text>Select a stack to compile:</Text>\n <Select\n options={availableStacks.map((name) => ({\n value: name,\n label: name,\n }))}\n onChange={(value) => {\n onSelect(value);\n }}\n />\n </Box>\n );\n};\n\nexport default class BuildStack extends BaseCommand {\n static summary = \"Build a stack into a standalone plugin\";\n\n static description =\n \"Build a stack into a standalone plugin (requires skills repo). If no stack is specified, you will be prompted to select one.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --stack frontend-stack\",\n \"<%= config.bin %> <%= command.id %> --stack frontend-stack --output-dir ./plugins\",\n \"<%= config.bin %> <%= command.id %> --agent-source /path/to/agents --refresh\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n stack: Flags.string({\n description: \"Stack ID to compile (directory name in src/stacks/)\",\n }),\n \"output-dir\": Flags.string({\n char: \"o\",\n description: \"Output directory\",\n default: DEFAULT_OUTPUT_DIR,\n }),\n \"agent-source\": Flags.string({\n description: \"Agent partials source (default: local CLI)\",\n }),\n refresh: Flags.boolean({\n description: \"Force refresh remote agent source\",\n default: false,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildStack);\n\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const outputDir = path.resolve(projectRoot, flags[\"output-dir\"]);\n\n let stackId = flags.stack;\n\n // If no stack specified, prompt for selection\n if (!stackId) {\n const stacks = await loadStacks(projectRoot);\n const availableStacks = stacks.map((s) => s.id).sort();\n\n if (availableStacks.length === 0) {\n this.error(`No stacks found in config/stacks.yaml`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n // Render interactive selector\n stackId = await new Promise<string>((resolve, reject) => {\n const { waitUntilExit } = render(\n <StackSelector\n availableStacks={availableStacks}\n onSelect={(selected) => {\n resolve(selected);\n }}\n />,\n );\n\n waitUntilExit().catch(reject);\n }).catch(() => {\n this.log(\"Cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n });\n }\n\n this.log(\"\");\n this.log(`Compiling stack plugin: ${stackId}`);\n this.log(` Output directory: ${outputDir}`);\n this.log(\"\");\n\n // Load agent partials\n let agentSourcePath: string;\n try {\n this.log(\n flags[\"agent-source\"]\n ? \"Fetching agent partials...\"\n : \"Loading agent partials...\",\n );\n const agentDefs = await getAgentDefinitions(flags[\"agent-source\"], {\n forceRefresh: flags.refresh,\n });\n agentSourcePath = agentDefs.sourcePath;\n this.log(\n flags[\"agent-source\"]\n ? `Agent partials fetched from: ${flags[\"agent-source\"]}`\n : `Agent partials loaded from: ${PROJECT_ROOT}`,\n );\n } catch (error) {\n this.log(\"Failed to load agent partials\");\n this.error(error instanceof Error ? error.message : String(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n // Compile the stack\n try {\n this.log(`Compiling stack \"${stackId}\"...`);\n\n const result = await compileStackPlugin({\n stackId,\n outputDir,\n projectRoot,\n agentSourcePath,\n });\n\n this.log(`Compiled stack plugin: ${result.stackName}`);\n\n printStackCompilationSummary(result);\n\n this.log(\"\");\n this.logSuccess(\"Stack plugin compilation complete!\");\n } catch (error) {\n this.log(\"Compilation failed\");\n this.error(error instanceof Error ? error.message : String(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n}\n"],"mappings":"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","names":[]}