bmad-module-skill-forge 0.9.0 → 0.10.1-alpha.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 (268) hide show
  1. package/.claude-plugin/marketplace.json +39 -0
  2. package/.gitattributes +16 -0
  3. package/README.md +105 -38
  4. package/docs/404.md +13 -10
  5. package/docs/RELEASING.md +185 -0
  6. package/docs/STABILITY.md +123 -0
  7. package/docs/_data/pinned.yaml +98 -0
  8. package/docs/agents.md +16 -11
  9. package/docs/architecture.md +221 -0
  10. package/docs/bmad-synergy.md +11 -13
  11. package/docs/concepts.md +18 -108
  12. package/docs/examples.md +121 -80
  13. package/docs/getting-started.md +85 -147
  14. package/docs/how-it-works.md +25 -536
  15. package/docs/index.md +44 -27
  16. package/docs/skill-model.md +328 -0
  17. package/docs/troubleshooting.md +39 -0
  18. package/docs/verifying-a-skill.md +232 -0
  19. package/docs/why-skf.md +93 -0
  20. package/docs/workflows.md +119 -13
  21. package/package.json +25 -4
  22. package/src/README.md +23 -25
  23. package/src/forger/forge-tier.yaml +4 -2
  24. package/src/forger/preferences.yaml +7 -1
  25. package/src/knowledge/agentskills-spec.md +1 -1
  26. package/src/knowledge/architecture-verification.md +1 -1
  27. package/src/knowledge/ccc-bridge.md +16 -15
  28. package/src/knowledge/overview.md +11 -11
  29. package/src/knowledge/progressive-capability.md +3 -3
  30. package/src/knowledge/provenance-tracking.md +9 -3
  31. package/src/knowledge/qmd-registry.md +8 -8
  32. package/src/knowledge/skf-knowledge-index.csv +2 -2
  33. package/src/knowledge/skill-lifecycle.md +16 -1
  34. package/src/knowledge/split-body-strategy.md +1 -1
  35. package/src/knowledge/version-paths.md +17 -12
  36. package/src/module-help.csv +18 -17
  37. package/src/module.yaml +4 -0
  38. package/src/shared/health-check.md +372 -0
  39. package/src/shared/references/feasibility-report-schema.md +86 -0
  40. package/src/shared/references/headless-gate-convention.md +62 -0
  41. package/src/shared/references/output-contract-schema.md +35 -0
  42. package/src/shared/references/pipeline-contracts.md +102 -0
  43. package/src/shared/scripts/skf-atomic-write.py +370 -0
  44. package/src/shared/scripts/skf-manifest-ops.py +236 -0
  45. package/src/shared/scripts/skf-preflight.py +164 -0
  46. package/src/shared/scripts/skf-rebuild-managed-sections.py +201 -0
  47. package/src/shared/scripts/skf-severity-classify.py +163 -0
  48. package/src/shared/scripts/skf-skill-inventory.py +210 -0
  49. package/src/shared/scripts/skf-structural-diff.py +257 -0
  50. package/src/shared/scripts/skf-validate-frontmatter.py +318 -0
  51. package/src/shared/scripts/skf-validate-output.py +247 -0
  52. package/src/skf-analyze-source/SKILL.md +57 -0
  53. package/src/skf-analyze-source/assets/skill-brief-schema.md +125 -0
  54. package/src/skf-analyze-source/references/unit-detection-heuristics.md +124 -0
  55. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-01-init.md +6 -66
  56. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-01b-continue.md +4 -59
  57. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-02-scan-project.md +7 -68
  58. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-03-identify-units.md +6 -66
  59. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-04-map-and-detect.md +7 -68
  60. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-05-recommend.md +6 -66
  61. package/src/{workflows/analyze-source → skf-analyze-source}/steps-c/step-06-generate-briefs.md +14 -66
  62. package/src/skf-analyze-source/steps-c/step-07-health-check.md +22 -0
  63. package/src/skf-audit-skill/SKILL.md +59 -0
  64. package/src/{workflows/audit-skill/data → skf-audit-skill/assets}/drift-report-template.md +7 -7
  65. package/src/{workflows/audit-skill/data → skf-audit-skill/references}/severity-rules.md +11 -11
  66. package/src/{workflows/audit-skill → skf-audit-skill}/steps-c/step-01-init.md +24 -68
  67. package/src/{workflows/audit-skill → skf-audit-skill}/steps-c/step-02-re-index.md +36 -71
  68. package/src/{workflows/audit-skill → skf-audit-skill}/steps-c/step-03-structural-diff.md +21 -63
  69. package/src/{workflows/audit-skill → skf-audit-skill}/steps-c/step-04-semantic-diff.md +6 -65
  70. package/src/{workflows/audit-skill → skf-audit-skill}/steps-c/step-05-severity-classify.md +5 -63
  71. package/src/{workflows/audit-skill → skf-audit-skill}/steps-c/step-06-report.md +10 -59
  72. package/src/skf-audit-skill/steps-c/step-07-health-check.md +22 -0
  73. package/src/skf-brief-skill/SKILL.md +53 -0
  74. package/src/{workflows/brief-skill/data → skf-brief-skill/assets}/scope-templates.md +23 -0
  75. package/src/skf-brief-skill/assets/skill-brief-schema.md +206 -0
  76. package/src/{workflows/brief-skill → skf-brief-skill}/steps-c/step-01-gather-intent.md +6 -67
  77. package/src/{workflows/brief-skill → skf-brief-skill}/steps-c/step-02-analyze-target.md +6 -66
  78. package/src/{workflows/brief-skill → skf-brief-skill}/steps-c/step-03-scope-definition.md +12 -68
  79. package/src/{workflows/brief-skill → skf-brief-skill}/steps-c/step-04-confirm-brief.md +5 -63
  80. package/src/{workflows/brief-skill → skf-brief-skill}/steps-c/step-05-write-brief.md +10 -69
  81. package/src/skf-brief-skill/steps-c/step-06-health-check.md +22 -0
  82. package/src/skf-create-skill/SKILL.md +63 -0
  83. package/src/{workflows/create-skill/data → skf-create-skill/assets}/compile-assembly-rules.md +60 -0
  84. package/src/{workflows/create-skill/data → skf-create-skill/assets}/skill-sections.md +92 -23
  85. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +102 -0
  86. package/src/{workflows/create-skill/data → skf-create-skill/references}/extraction-patterns-tracing.md +13 -13
  87. package/src/{workflows/create-skill/data → skf-create-skill/references}/extraction-patterns.md +8 -3
  88. package/src/skf-create-skill/references/source-resolution-protocols.md +239 -0
  89. package/src/{workflows/create-skill/data → skf-create-skill/references}/tier-degradation-rules.md +8 -7
  90. package/src/{workflows/create-skill → skf-create-skill}/steps-c/step-01-load-brief.md +25 -63
  91. package/src/{workflows/create-skill → skf-create-skill}/steps-c/step-02-ecosystem-check.md +8 -64
  92. package/src/skf-create-skill/steps-c/step-03-extract.md +379 -0
  93. package/src/{workflows/create-skill → skf-create-skill}/steps-c/step-03d-component-extraction.md +18 -35
  94. package/src/{workflows/create-skill → skf-create-skill}/steps-c/step-04-enrich.md +12 -69
  95. package/src/{workflows/create-skill → skf-create-skill}/steps-c/step-05-compile.md +71 -75
  96. package/src/skf-create-skill/steps-c/step-06-validate.md +267 -0
  97. package/src/{workflows/create-skill → skf-create-skill}/steps-c/step-07-generate-artifacts.md +30 -74
  98. package/src/skf-create-skill/steps-c/step-08-report.md +145 -0
  99. package/src/skf-create-skill/steps-c/step-09-health-check.md +23 -0
  100. package/src/{workflows/create-skill/steps-c → skf-create-skill/steps-c/sub}/step-02b-ccc-discover.md +8 -66
  101. package/src/skf-create-skill/steps-c/sub/step-03b-fetch-temporal.md +229 -0
  102. package/src/{workflows/create-skill/steps-c → skf-create-skill/steps-c/sub}/step-03c-fetch-docs.md +18 -42
  103. package/src/skf-create-stack-skill/SKILL.md +64 -0
  104. package/src/{workflows/create-stack-skill/data → skf-create-stack-skill/assets}/stack-skill-template.md +2 -1
  105. package/src/{workflows/create-stack-skill/data → skf-create-stack-skill/references}/compose-mode-rules.md +19 -5
  106. package/src/{workflows/create-stack-skill/data → skf-create-stack-skill/references}/integration-patterns.md +1 -1
  107. package/src/{workflows/create-stack-skill/data → skf-create-stack-skill/references}/manifest-patterns.md +10 -10
  108. package/src/{workflows/create-stack-skill → skf-create-stack-skill}/steps-c/step-01-init.md +14 -55
  109. package/src/{workflows/create-stack-skill → skf-create-stack-skill}/steps-c/step-02-detect-manifests.md +29 -63
  110. package/src/{workflows/create-stack-skill → skf-create-stack-skill}/steps-c/step-03-rank-and-confirm.md +9 -59
  111. package/src/{workflows/create-stack-skill → skf-create-stack-skill}/steps-c/step-04-parallel-extract.md +29 -64
  112. package/src/skf-create-stack-skill/steps-c/step-05-detect-integrations.md +164 -0
  113. package/src/{workflows/create-stack-skill → skf-create-stack-skill}/steps-c/step-06-compile-stack.md +7 -60
  114. package/src/skf-create-stack-skill/steps-c/step-07-generate-output.md +328 -0
  115. package/src/{workflows/create-stack-skill → skf-create-stack-skill}/steps-c/step-08-validate.md +17 -63
  116. package/src/skf-create-stack-skill/steps-c/step-09-report.md +128 -0
  117. package/src/skf-create-stack-skill/steps-c/step-10-health-check.md +22 -0
  118. package/src/skf-drop-skill/SKILL.md +57 -0
  119. package/src/{workflows/drop-skill → skf-drop-skill}/steps-c/step-01-select.md +9 -69
  120. package/src/{workflows/drop-skill → skf-drop-skill}/steps-c/step-02-execute.md +30 -106
  121. package/src/skf-drop-skill/steps-c/step-03-report.md +83 -0
  122. package/src/skf-drop-skill/steps-c/step-04-health-check.md +22 -0
  123. package/src/skf-export-skill/SKILL.md +57 -0
  124. package/src/skf-export-skill/assets/managed-section-format.md +138 -0
  125. package/src/{workflows/export-skill/data → skf-export-skill/assets}/snippet-format.md +8 -12
  126. package/src/skf-export-skill/steps-c/step-01-load-skill.md +247 -0
  127. package/src/{workflows/export-skill → skf-export-skill}/steps-c/step-02-package.md +5 -58
  128. package/src/{workflows/export-skill → skf-export-skill}/steps-c/step-03-generate-snippet.md +15 -77
  129. package/src/{workflows/export-skill → skf-export-skill}/steps-c/step-04-update-context.md +59 -133
  130. package/src/{workflows/export-skill → skf-export-skill}/steps-c/step-05-token-report.md +4 -58
  131. package/src/{workflows/export-skill → skf-export-skill}/steps-c/step-06-summary.md +20 -64
  132. package/src/skf-export-skill/steps-c/step-07-health-check.md +22 -0
  133. package/src/skf-forger/SKILL.md +110 -0
  134. package/src/skf-forger/bmad-skill-manifest.yaml +11 -0
  135. package/src/skf-quick-skill/SKILL.md +56 -0
  136. package/src/{workflows/quick-skill/data → skf-quick-skill/references}/registry-resolution.md +6 -6
  137. package/src/{workflows/quick-skill → skf-quick-skill}/steps-c/step-01-resolve-target.md +9 -62
  138. package/src/{workflows/quick-skill → skf-quick-skill}/steps-c/step-02-ecosystem-check.md +5 -59
  139. package/src/{workflows/quick-skill → skf-quick-skill}/steps-c/step-03-quick-extract.md +18 -61
  140. package/src/{workflows/quick-skill → skf-quick-skill}/steps-c/step-04-compile.md +6 -60
  141. package/src/{workflows/quick-skill → skf-quick-skill}/steps-c/step-05-validate.md +58 -78
  142. package/src/skf-quick-skill/steps-c/step-06-write.md +73 -0
  143. package/src/skf-quick-skill/steps-c/step-07-health-check.md +22 -0
  144. package/src/skf-refine-architecture/SKILL.md +57 -0
  145. package/src/{workflows/refine-architecture/data → skf-refine-architecture/references}/refinement-rules.md +16 -16
  146. package/src/{workflows/refine-architecture → skf-refine-architecture}/steps-c/step-01-init.md +6 -63
  147. package/src/{workflows/refine-architecture → skf-refine-architecture}/steps-c/step-02-gap-analysis.md +29 -71
  148. package/src/{workflows/refine-architecture → skf-refine-architecture}/steps-c/step-03-issue-detection.md +5 -65
  149. package/src/{workflows/refine-architecture → skf-refine-architecture}/steps-c/step-04-improvements.md +5 -64
  150. package/src/{workflows/refine-architecture → skf-refine-architecture}/steps-c/step-05-compile.md +5 -56
  151. package/src/{workflows/refine-architecture → skf-refine-architecture}/steps-c/step-06-report.md +14 -64
  152. package/src/skf-refine-architecture/steps-c/step-07-health-check.md +22 -0
  153. package/src/skf-rename-skill/SKILL.md +58 -0
  154. package/src/{workflows/rename-skill → skf-rename-skill}/steps-c/step-01-select.md +12 -73
  155. package/src/{workflows/rename-skill → skf-rename-skill}/steps-c/step-02-execute.md +32 -113
  156. package/src/skf-rename-skill/steps-c/step-03-report.md +83 -0
  157. package/src/skf-rename-skill/steps-c/step-04-health-check.md +22 -0
  158. package/src/skf-setup/SKILL.md +55 -0
  159. package/src/{workflows/setup-forge → skf-setup}/steps-c/step-01-detect-and-tier.md +6 -62
  160. package/src/{workflows/setup-forge → skf-setup}/steps-c/step-01b-ccc-index.md +9 -65
  161. package/src/{workflows/setup-forge → skf-setup}/steps-c/step-02-write-config.md +15 -60
  162. package/src/{workflows/setup-forge → skf-setup}/steps-c/step-03-auto-index.md +7 -66
  163. package/src/skf-setup/steps-c/step-04-report.md +92 -0
  164. package/src/skf-setup/steps-c/step-05-health-check.md +22 -0
  165. package/src/skf-test-skill/SKILL.md +59 -0
  166. package/src/skf-test-skill/references/migration-section-rules.md +114 -0
  167. package/src/skf-test-skill/references/scoring-rules.md +207 -0
  168. package/src/skf-test-skill/references/source-access-protocol.md +109 -0
  169. package/src/skf-test-skill/scripts/compute-score.py +310 -0
  170. package/src/skf-test-skill/steps-c/step-01-init.md +238 -0
  171. package/src/{workflows/test-skill → skf-test-skill}/steps-c/step-02-detect-mode.md +4 -62
  172. package/src/skf-test-skill/steps-c/step-03-coverage-check.md +347 -0
  173. package/src/skf-test-skill/steps-c/step-04-coherence-check.md +239 -0
  174. package/src/{workflows/test-skill → skf-test-skill}/steps-c/step-04b-external-validators.md +42 -77
  175. package/src/skf-test-skill/steps-c/step-05-score.md +266 -0
  176. package/src/skf-test-skill/steps-c/step-06-report.md +290 -0
  177. package/src/skf-test-skill/steps-c/step-07-health-check.md +25 -0
  178. package/src/skf-test-skill/templates/test-report-template.md +58 -0
  179. package/src/skf-update-skill/SKILL.md +58 -0
  180. package/src/{workflows/update-skill/data → skf-update-skill/references}/manual-section-rules.md +6 -6
  181. package/src/{workflows/update-skill/data → skf-update-skill/references}/merge-conflict-rules.md +5 -5
  182. package/src/skf-update-skill/references/remote-source-resolution.md +94 -0
  183. package/src/{workflows/update-skill → skf-update-skill}/steps-c/step-01-init.md +22 -69
  184. package/src/skf-update-skill/steps-c/step-02-detect-changes.md +255 -0
  185. package/src/skf-update-skill/steps-c/step-03-re-extract.md +336 -0
  186. package/src/{workflows/update-skill → skf-update-skill}/steps-c/step-04-merge.md +60 -72
  187. package/src/{workflows/update-skill → skf-update-skill}/steps-c/step-05-validate.md +5 -62
  188. package/src/skf-update-skill/steps-c/step-06-write.md +278 -0
  189. package/src/{workflows/update-skill → skf-update-skill}/steps-c/step-07-report.md +11 -66
  190. package/src/skf-update-skill/steps-c/step-08-health-check.md +22 -0
  191. package/src/skf-verify-stack/SKILL.md +60 -0
  192. package/src/skf-verify-stack/assets/feasibility-report-template.md +76 -0
  193. package/src/{workflows/verify-stack/data → skf-verify-stack/references}/coverage-patterns.md +12 -4
  194. package/src/skf-verify-stack/references/integration-verification-rules.md +78 -0
  195. package/src/skf-verify-stack/steps-c/step-01-init.md +178 -0
  196. package/src/{workflows/verify-stack → skf-verify-stack}/steps-c/step-02-coverage.md +27 -72
  197. package/src/skf-verify-stack/steps-c/step-03-integrations.md +179 -0
  198. package/src/{workflows/verify-stack → skf-verify-stack}/steps-c/step-04-requirements.md +14 -67
  199. package/src/skf-verify-stack/steps-c/step-05-synthesize.md +147 -0
  200. package/src/skf-verify-stack/steps-c/step-06-report.md +156 -0
  201. package/src/skf-verify-stack/steps-c/step-07-health-check.md +25 -0
  202. package/tools/cli/commands/install.js +1 -1
  203. package/tools/cli/commands/status.js +21 -23
  204. package/tools/cli/commands/uninstall.js +11 -19
  205. package/tools/cli/commands/update.js +2 -2
  206. package/tools/cli/lib/ide-skills.js +216 -0
  207. package/tools/cli/lib/installer.js +29 -52
  208. package/tools/cli/lib/manifest.js +11 -5
  209. package/tools/cli/lib/platform-codes.yaml +223 -0
  210. package/tools/cli/lib/ui.js +76 -47
  211. package/tools/validate-docs-drift.js +193 -0
  212. package/src/agents/forger.agent.yaml +0 -114
  213. package/src/workflows/README.md +0 -174
  214. package/src/workflows/analyze-source/data/skill-brief-schema.md +0 -125
  215. package/src/workflows/analyze-source/data/unit-detection-heuristics.md +0 -124
  216. package/src/workflows/analyze-source/workflow.md +0 -61
  217. package/src/workflows/audit-skill/workflow.md +0 -64
  218. package/src/workflows/brief-skill/data/skill-brief-schema.md +0 -159
  219. package/src/workflows/brief-skill/workflow.md +0 -58
  220. package/src/workflows/create-skill/data/source-resolution-protocols.md +0 -200
  221. package/src/workflows/create-skill/steps-c/step-03-extract.md +0 -301
  222. package/src/workflows/create-skill/steps-c/step-03b-fetch-temporal.md +0 -253
  223. package/src/workflows/create-skill/steps-c/step-06-validate.md +0 -254
  224. package/src/workflows/create-skill/steps-c/step-08-report.md +0 -176
  225. package/src/workflows/create-skill/workflow.md +0 -53
  226. package/src/workflows/create-stack-skill/steps-c/step-05-detect-integrations.md +0 -196
  227. package/src/workflows/create-stack-skill/steps-c/step-07-generate-output.md +0 -270
  228. package/src/workflows/create-stack-skill/steps-c/step-09-report.md +0 -145
  229. package/src/workflows/create-stack-skill/workflow.md +0 -59
  230. package/src/workflows/drop-skill/steps-c/step-03-report.md +0 -135
  231. package/src/workflows/drop-skill/workflow.md +0 -63
  232. package/src/workflows/export-skill/data/managed-section-format.md +0 -103
  233. package/src/workflows/export-skill/steps-c/step-01-load-skill.md +0 -237
  234. package/src/workflows/export-skill/workflow.md +0 -58
  235. package/src/workflows/quick-skill/steps-c/step-06-write.md +0 -179
  236. package/src/workflows/quick-skill/workflow.md +0 -58
  237. package/src/workflows/refine-architecture/workflow.md +0 -61
  238. package/src/workflows/rename-skill/steps-c/step-03-report.md +0 -132
  239. package/src/workflows/rename-skill/workflow.md +0 -64
  240. package/src/workflows/setup-forge/steps-c/step-04-report.md +0 -156
  241. package/src/workflows/setup-forge/workflow.md +0 -51
  242. package/src/workflows/test-skill/data/scoring-rules.md +0 -123
  243. package/src/workflows/test-skill/data/source-access-protocol.md +0 -51
  244. package/src/workflows/test-skill/steps-c/step-01-init.md +0 -217
  245. package/src/workflows/test-skill/steps-c/step-03-coverage-check.md +0 -280
  246. package/src/workflows/test-skill/steps-c/step-04-coherence-check.md +0 -271
  247. package/src/workflows/test-skill/steps-c/step-05-score.md +0 -222
  248. package/src/workflows/test-skill/steps-c/step-06-report.md +0 -207
  249. package/src/workflows/test-skill/templates/test-report-template.md +0 -28
  250. package/src/workflows/test-skill/workflow.md +0 -57
  251. package/src/workflows/update-skill/data/remote-source-resolution.md +0 -57
  252. package/src/workflows/update-skill/steps-c/step-02-detect-changes.md +0 -221
  253. package/src/workflows/update-skill/steps-c/step-03-re-extract.md +0 -256
  254. package/src/workflows/update-skill/steps-c/step-06-write.md +0 -265
  255. package/src/workflows/update-skill/workflow.md +0 -56
  256. package/src/workflows/verify-stack/data/feasibility-report-template.md +0 -63
  257. package/src/workflows/verify-stack/data/integration-verification-rules.md +0 -73
  258. package/src/workflows/verify-stack/steps-c/step-01-init.md +0 -179
  259. package/src/workflows/verify-stack/steps-c/step-03-integrations.md +0 -195
  260. package/src/workflows/verify-stack/steps-c/step-05-synthesize.md +0 -191
  261. package/src/workflows/verify-stack/steps-c/step-06-report.md +0 -197
  262. package/src/workflows/verify-stack/workflow.md +0 -61
  263. package/tools/cli/lib/compiler.js +0 -306
  264. package/tools/cli/lib/ide-commands.js +0 -244
  265. /package/src/{workflows/analyze-source → skf-analyze-source}/templates/analysis-report-template.md +0 -0
  266. /package/src/{workflows/quick-skill/data → skf-quick-skill/assets}/skill-template.md +0 -0
  267. /package/src/{workflows/setup-forge/data → skf-setup/references}/tier-rules.md +0 -0
  268. /package/src/{workflows/test-skill/data → skf-test-skill/assets}/output-section-formats.md +0 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * IDE Skill Installer — Verbatim skill directory installation
3
+ *
4
+ * Replaces the legacy command-file generation approach with the BMAD standard:
5
+ * skill directories (containing SKILL.md + supporting files) are copied directly
6
+ * to each IDE's skills/ directory. IDEs read SKILL.md natively.
7
+ *
8
+ * Supports 23+ IDEs via platform-codes.yaml (config-driven, no IDE-specific code).
9
+ */
10
+
11
+ const path = require('node:path');
12
+ const fs = require('fs-extra');
13
+ const yaml = require('js-yaml');
14
+
15
+ const PLATFORM_CODES_PATH = path.join(__dirname, 'platform-codes.yaml');
16
+
17
+ // OS/editor artifacts to filter during copy
18
+ const ARTIFACT_FILTER = new Set(['.DS_Store', 'Thumbs.db', 'desktop.ini', '._.DS_Store']);
19
+
20
+ /**
21
+ * Load platform configuration from platform-codes.yaml.
22
+ * Returns { platforms: { 'claude-code': { name, preferred, installer: { target_dir, legacy_targets } }, ... } }
23
+ */
24
+ function loadPlatforms() {
25
+ const content = fs.readFileSync(PLATFORM_CODES_PATH, 'utf8');
26
+ return yaml.load(content);
27
+ }
28
+
29
+ /**
30
+ * Get available platforms for UI display.
31
+ * Returns array of { value, label, preferred, skillInvocationPrefix }.
32
+ * skillInvocationPrefix is null when the IDE only auto-invokes skills.
33
+ */
34
+ function getAvailablePlatforms() {
35
+ const config = loadPlatforms();
36
+ return Object.entries(config.platforms)
37
+ .filter(([, p]) => !p.suspended)
38
+ .map(([code, p]) => ({
39
+ value: code,
40
+ label: p.name,
41
+ preferred: p.preferred || false,
42
+ skillInvocationPrefix: p.skill_invocation_prefix ?? null,
43
+ }))
44
+ .sort((a, b) => {
45
+ // Preferred first, then alphabetical
46
+ if (a.preferred !== b.preferred) return b.preferred ? 1 : -1;
47
+ return a.label.localeCompare(b.label);
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Get IDE auto-detection markers.
53
+ * Returns { 'claude-code': ['.claude'], 'cursor': ['.cursor'], ... }
54
+ *
55
+ * Uses explicit detection_marker from platform config when available,
56
+ * otherwise derives from the top-level directory of target_dir.
57
+ * The derived marker only works when the IDE's config directory exists
58
+ * independently of the installer (e.g. .claude/ exists before SKF install).
59
+ */
60
+ function getDetectionMarkers() {
61
+ const config = loadPlatforms();
62
+ const markers = {};
63
+ for (const [code, p] of Object.entries(config.platforms)) {
64
+ if (p.suspended) continue;
65
+ const targetDir = p.installer?.target_dir;
66
+ if (!targetDir) continue;
67
+ if (p.installer.detection_marker) {
68
+ markers[code] = [p.installer.detection_marker];
69
+ } else {
70
+ // Derive from target_dir — works when top-level dir is the IDE's own config dir
71
+ const topDir = '.' + targetDir.split('/')[0].replace(/^\./, '');
72
+ markers[code] = [topDir];
73
+ }
74
+ }
75
+ return markers;
76
+ }
77
+
78
+ /**
79
+ * Install skill directories to all selected IDEs.
80
+ *
81
+ * @param {string} projectDir - Project root directory
82
+ * @param {string} skfDir - Path to installed SKF module (e.g., {projectDir}/_bmad/skf)
83
+ * @param {string[]} ideCodes - Array of IDE codes (e.g., ['claude-code', 'cursor'])
84
+ * @returns {{ installed: number, ides: string[], directories: string[] }}
85
+ */
86
+ async function installSkillsToIdes(projectDir, skfDir, ideCodes) {
87
+ if (!ideCodes || ideCodes.length === 0) return { installed: 0, ides: [], directories: [] };
88
+
89
+ const config = loadPlatforms();
90
+ let totalInstalled = 0;
91
+ const processedIdes = [];
92
+ const allDirectories = [];
93
+
94
+ // Copy filter: skip OS artifacts
95
+ const copyFilter = (src) => !ARTIFACT_FILTER.has(path.basename(src));
96
+
97
+ for (const ideCode of ideCodes) {
98
+ const platform = config.platforms[ideCode];
99
+ if (!platform || !platform.installer?.target_dir) continue;
100
+
101
+ const targetDir = path.join(projectDir, platform.installer.target_dir);
102
+
103
+ // Clean legacy targets first (old command files from previous SKF installs)
104
+ await cleanLegacyTargets(projectDir, platform);
105
+
106
+ // Clean existing SKF skills from this IDE (for update/reinstall)
107
+ await cleanSkfSkills(targetDir);
108
+
109
+ // Ensure target directory exists
110
+ await fs.ensureDir(targetDir);
111
+
112
+ // Copy all skf-* skill directories from the installed module
113
+ if (await fs.pathExists(skfDir)) {
114
+ const entries = await fs.readdir(skfDir, { withFileTypes: true });
115
+ for (const entry of entries) {
116
+ if (!entry.isDirectory()) continue;
117
+
118
+ // Copy skill directories (skf-*) and supporting resources (knowledge/, shared/)
119
+ if (entry.name.startsWith('skf-') || entry.name === 'knowledge' || entry.name === 'shared') {
120
+ const src = path.join(skfDir, entry.name);
121
+ const dest = path.join(targetDir, entry.name);
122
+ await fs.copy(src, dest, { filter: copyFilter });
123
+ totalInstalled++;
124
+ }
125
+ }
126
+ }
127
+
128
+ allDirectories.push(platform.installer.target_dir);
129
+ processedIdes.push(ideCode);
130
+ }
131
+
132
+ return { installed: totalInstalled, ides: processedIdes, directories: allDirectories };
133
+ }
134
+
135
+ /**
136
+ * Remove legacy command files from old IDE target directories.
137
+ * Handles migration from command-file approach to skill-directory approach.
138
+ */
139
+ async function cleanLegacyTargets(projectDir, platform) {
140
+ const legacyTargets = platform.installer?.legacy_targets || [];
141
+
142
+ for (const legacyDir of legacyTargets) {
143
+ const fullPath = path.join(projectDir, legacyDir);
144
+ if (!(await fs.pathExists(fullPath))) continue;
145
+
146
+ try {
147
+ const files = await fs.readdir(fullPath);
148
+ for (const file of files) {
149
+ // Remove SKF-specific command files from legacy directories
150
+ if (file.startsWith('bmad-skf-') || file.startsWith('bmad-agent-skf-')) {
151
+ await fs.remove(path.join(fullPath, file));
152
+ }
153
+ }
154
+
155
+ // Remove empty directories
156
+ const remaining = await fs.readdir(fullPath);
157
+ if (remaining.length === 0) {
158
+ await fs.remove(fullPath);
159
+ // Also try to remove empty parent
160
+ const parentDir = path.dirname(fullPath);
161
+ try {
162
+ const parentRemaining = await fs.readdir(parentDir);
163
+ if (parentRemaining.length === 0) await fs.remove(parentDir);
164
+ } catch {
165
+ /* ignore */
166
+ }
167
+ }
168
+ } catch {
169
+ /* non-critical, continue */
170
+ }
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Remove existing SKF skill directories from an IDE target.
176
+ * Called before reinstalling to ensure clean state.
177
+ */
178
+ async function cleanSkfSkills(targetDir) {
179
+ if (!(await fs.pathExists(targetDir))) return;
180
+
181
+ try {
182
+ const entries = await fs.readdir(targetDir);
183
+ for (const entry of entries) {
184
+ // Only remove SKF-owned directories (skf-*, knowledge, shared)
185
+ if (entry.startsWith('skf-') || entry === 'knowledge' || entry === 'shared') {
186
+ await fs.remove(path.join(targetDir, entry));
187
+ }
188
+ }
189
+ } catch {
190
+ /* non-critical */
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Remove all SKF skills from all known IDE directories.
196
+ * Used during uninstall.
197
+ */
198
+ async function removeAllSkfSkills(projectDir) {
199
+ const config = loadPlatforms();
200
+ const removed = [];
201
+
202
+ for (const [, platform] of Object.entries(config.platforms)) {
203
+ if (!platform.installer?.target_dir) continue;
204
+ const targetDir = path.join(projectDir, platform.installer.target_dir);
205
+ if (await fs.pathExists(targetDir)) {
206
+ await cleanSkfSkills(targetDir);
207
+ // Also clean legacy targets
208
+ await cleanLegacyTargets(projectDir, platform);
209
+ removed.push(platform.installer.target_dir);
210
+ }
211
+ }
212
+
213
+ return removed;
214
+ }
215
+
216
+ module.exports = { installSkillsToIdes, getAvailablePlatforms, getDetectionMarkers, removeAllSkfSkills, loadPlatforms };
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * SKF Installer - Core orchestrator
3
- * Copies SKF source files, compiles agents, creates folder structure.
3
+ * Copies SKF source files, installs skills to IDEs, creates folder structure.
4
4
  */
5
5
 
6
6
  const path = require('node:path');
7
7
  const fs = require('fs-extra');
8
8
  const { spinner } = require('@clack/prompts');
9
9
  const yaml = require('js-yaml');
10
- const { compileAgentFile } = require('./compiler');
11
- const { generateIdeCommands } = require('./ide-commands');
10
+ const { installSkillsToIdes } = require('./ide-skills');
12
11
  const { writeManifest } = require('./manifest');
13
12
 
14
13
  class Installer {
@@ -39,6 +38,7 @@ class Installer {
39
38
  if (!config.ides && savedData.ides) config.ides = savedData.ides;
40
39
  if (!config.skills_output_folder && savedData.skills_output_folder) config.skills_output_folder = savedData.skills_output_folder;
41
40
  if (!config.forge_data_folder && savedData.forge_data_folder) config.forge_data_folder = savedData.forge_data_folder;
41
+ if (config.install_learning == null && savedData.install_learning != null) config.install_learning = savedData.install_learning;
42
42
  } catch {
43
43
  /* ignore parse errors, defaults will apply */
44
44
  }
@@ -89,17 +89,7 @@ class Installer {
89
89
  throw error;
90
90
  }
91
91
 
92
- // Step 4: Compile agents
93
- s.start('Compiling agents...');
94
- try {
95
- const agents = await this.compileAgents(skfDir, skfFolder);
96
- s.stop(`Compiled ${agents.length} agent${agents.length === 1 ? '' : 's'}`);
97
- } catch (error) {
98
- s.stop('Failed to compile agents');
99
- throw error;
100
- }
101
-
102
- // Step 5: Create output folders
92
+ // Step 4: Create output folders
103
93
  s.start('Creating project folders...');
104
94
  try {
105
95
  await this.createOutputFolders(projectDir, config);
@@ -109,7 +99,7 @@ class Installer {
109
99
  throw error;
110
100
  }
111
101
 
112
- // Step 6: Copy learning material (optional)
102
+ // Step 5: Copy learning material (optional)
113
103
  if (config.install_learning !== false) {
114
104
  s.start('Copying learning & reference material...');
115
105
  try {
@@ -121,32 +111,32 @@ class Installer {
121
111
  }
122
112
  }
123
113
 
124
- // Step 7: Generate IDE command files
125
- let ideFiles = [];
114
+ // Step 6: Install skills to selected IDEs
115
+ let ideDirectories = [];
126
116
  const selectedIdes = config.ides || [];
127
- if (selectedIdes.length > 0 && !selectedIdes.every((ide) => ide === 'other')) {
128
- s.start('Generating IDE commands...');
117
+ if (selectedIdes.length > 0) {
118
+ s.start('Installing skills to IDEs...');
129
119
  try {
130
- const ideResult = await generateIdeCommands(projectDir, skfFolder, selectedIdes);
131
- ideFiles = ideResult.files || [];
132
- if (ideResult.generated > 0) {
133
- s.stop(`IDE commands generated for ${ideResult.ides.join(', ')}`);
120
+ const ideResult = await installSkillsToIdes(projectDir, skfDir, selectedIdes);
121
+ ideDirectories = ideResult.directories || [];
122
+ if (ideResult.installed > 0) {
123
+ s.stop(`Skills installed for ${ideResult.ides.join(', ')}`);
134
124
  } else {
135
- s.stop('No IDE commands to generate');
125
+ s.stop('No IDE skill installation needed');
136
126
  }
137
127
  } catch (error) {
138
- s.stop('Failed to generate IDE commands');
128
+ s.stop('Failed to install skills to IDEs');
139
129
  throw error;
140
130
  }
141
131
  }
142
132
 
143
- // Step 8: Write installation manifest
133
+ // Step 7: Write installation manifest
144
134
  s.start('Writing manifest...');
145
135
  try {
146
136
  const packageJson = require('../../../package.json');
147
137
  await writeManifest(projectDir, config, {
148
138
  version: packageJson.version,
149
- ideFiles,
139
+ ideDirectories,
150
140
  });
151
141
  s.stop('Installation manifest saved');
152
142
  } catch (error) {
@@ -159,11 +149,19 @@ class Installer {
159
149
 
160
150
  /**
161
151
  * Copy src/ content into the target SKF directory.
162
- * Workflows are placed under a skillforge/ subdirectory to match agent path references.
152
+ * Skill directories (skf-*) are copied flat alongside module-level resources.
163
153
  */
164
154
  async copySrcFiles(skfDir) {
165
- // Copy agents and knowledge directly
166
- for (const dir of ['agents', 'knowledge']) {
155
+ // Copy skill directories (skf-*) — each is a self-contained skill
156
+ const srcEntries = await fs.readdir(this.srcDir, { withFileTypes: true });
157
+ for (const entry of srcEntries) {
158
+ if (entry.isDirectory() && entry.name.startsWith('skf-')) {
159
+ await fs.copy(path.join(this.srcDir, entry.name), path.join(skfDir, entry.name));
160
+ }
161
+ }
162
+
163
+ // Copy module-level resources
164
+ for (const dir of ['knowledge', 'shared']) {
167
165
  const src = path.join(this.srcDir, dir);
168
166
  const dest = path.join(skfDir, dir);
169
167
  if (await fs.pathExists(src)) {
@@ -171,13 +169,6 @@ class Installer {
171
169
  }
172
170
  }
173
171
 
174
- // Workflows go under workflows/skillforge/ to match agent YAML paths
175
- const workflowsSrc = path.join(this.srcDir, 'workflows');
176
- const workflowsDest = path.join(skfDir, 'workflows', 'skillforge');
177
- if (await fs.pathExists(workflowsSrc)) {
178
- await fs.copy(workflowsSrc, workflowsDest);
179
- }
180
-
181
172
  // Copy module.yaml and module-help.csv
182
173
  for (const file of ['module.yaml', 'module-help.csv']) {
183
174
  const src = path.join(this.srcDir, file);
@@ -241,27 +232,13 @@ class Installer {
241
232
  sidecar_path: '_bmad/_memory/forger-sidecar',
242
233
  skf_folder: config.skfFolder,
243
234
  ides: config.ides || [],
235
+ install_learning: config.install_learning !== false,
244
236
  };
245
237
 
246
238
  const yamlStr = yaml.dump(configData, { lineWidth: -1 });
247
239
  await fs.writeFile(path.join(skfDir, 'config.yaml'), `# SKF Configuration - Generated by installer\n${yamlStr}`, 'utf8');
248
240
  }
249
241
 
250
- async compileAgents(skfDir, skfFolder) {
251
- const agentsDir = path.join(skfDir, 'agents');
252
- const files = await fs.readdir(agentsDir);
253
- const agentFiles = files.filter((f) => f.endsWith('.agent.yaml'));
254
- const results = [];
255
-
256
- for (const file of agentFiles) {
257
- const yamlPath = path.join(agentsDir, file);
258
- const result = compileAgentFile(yamlPath, { skfFolder });
259
- results.push(result);
260
- }
261
-
262
- return results;
263
- }
264
-
265
242
  async createOutputFolders(projectDir, config) {
266
243
  const skillsFolder = config.skills_output_folder || 'skills';
267
244
  const forgeDataFolder = config.forge_data_folder || 'forge-data';
@@ -36,7 +36,7 @@ async function collectFiles(dir, projectDir) {
36
36
  *
37
37
  * @param {string} projectDir - Project root
38
38
  * @param {object} config - Install config (skfFolder, ides, etc.)
39
- * @param {object} options - Additional info (version, ideFiles)
39
+ * @param {object} options - Additional info (version, ideDirectories)
40
40
  */
41
41
  async function writeManifest(projectDir, config, options = {}) {
42
42
  const skfFolder = config.skfFolder || '_bmad/skf';
@@ -47,8 +47,14 @@ async function writeManifest(projectDir, config, options = {}) {
47
47
  const skfFiles = await collectFiles(skfDir, projectDir);
48
48
  const sidecarFiles = await collectFiles(sidecarDir, projectDir);
49
49
 
50
- // Collect IDE command files
51
- const ideFiles = options.ideFiles || [];
50
+ // Collect IDE skill directory files (installed to each IDE's skills/ dir)
51
+ const ideDirectories = options.ideDirectories || [];
52
+ const ideSkillFiles = [];
53
+ for (const ideDir of ideDirectories) {
54
+ const fullDir = path.join(projectDir, ideDir);
55
+ const files = await collectFiles(fullDir, projectDir);
56
+ ideSkillFiles.push(...files);
57
+ }
52
58
 
53
59
  // Collect learning material files
54
60
  const learnDir = path.join(projectDir, '_skf-learn');
@@ -72,11 +78,11 @@ async function writeManifest(projectDir, config, options = {}) {
72
78
  ides: config.ides || [],
73
79
  skills_output_folder: config.skills_output_folder || 'skills',
74
80
  forge_data_folder: config.forge_data_folder || 'forge-data',
75
- directories: [skfFolder, '_bmad/_memory/forger-sidecar', ...(learnFiles.length > 0 ? ['_skf-learn'] : [])],
81
+ directories: [skfFolder, '_bmad/_memory/forger-sidecar', ...ideDirectories, ...(learnFiles.length > 0 ? ['_skf-learn'] : [])],
76
82
  files: {
77
83
  skf: skfFiles,
78
84
  sidecar: sidecarFiles,
79
- ide_commands: ideFiles,
85
+ ide_skills: ideSkillFiles,
80
86
  learning: learnFiles,
81
87
  output: outputFiles,
82
88
  },
@@ -0,0 +1,223 @@
1
+ # BMAD Platform Codes Configuration
2
+ #
3
+ # Each platform entry has:
4
+ # name: Display name shown to users
5
+ # preferred: Whether shown as a recommended option on install
6
+ # suspended: (optional) Message explaining why install is blocked
7
+ # skill_invocation_prefix: (optional) Prefix users type to invoke a named
8
+ # skill in this IDE's chat. Examples:
9
+ # "/" — slash command, e.g. /skf-forger (most IDEs)
10
+ # "$" — dollar mention, e.g. $skf-forger (Codex)
11
+ # "/skill:" — namespaced slash, e.g. /skill:skf-forger (Pi)
12
+ # Omit when the IDE only auto-invokes skills from descriptions and has
13
+ # no manual invocation form (Cline, GitHub Copilot, Junie, etc.).
14
+ # installer:
15
+ # target_dir: Directory where skill directories are installed
16
+ # legacy_targets: (optional) Old target dirs to clean up on reinstall
17
+ platforms:
18
+ antigravity:
19
+ name: "Google Antigravity"
20
+ preferred: false
21
+ skill_invocation_prefix: "/"
22
+ installer:
23
+ detection_marker: .agent/antigravity
24
+ legacy_targets:
25
+ - .agent/workflows
26
+ target_dir: .agent/skills
27
+
28
+ auggie:
29
+ name: "Auggie"
30
+ preferred: false
31
+ skill_invocation_prefix: "/"
32
+ installer:
33
+ legacy_targets:
34
+ - .augment/commands
35
+ target_dir: .augment/skills
36
+
37
+ claude-code:
38
+ name: "Claude Code"
39
+ preferred: true
40
+ skill_invocation_prefix: "/"
41
+ installer:
42
+ legacy_targets:
43
+ - .claude/commands
44
+ target_dir: .claude/skills
45
+
46
+ cline:
47
+ name: "Cline"
48
+ preferred: false
49
+ # Auto-invoked from descriptions; no manual prefix
50
+ installer:
51
+ detection_marker: .clinerules
52
+ legacy_targets:
53
+ - .clinerules/workflows
54
+ target_dir: .cline/skills
55
+
56
+ codex:
57
+ name: "Codex"
58
+ preferred: false
59
+ skill_invocation_prefix: "$"
60
+ installer:
61
+ detection_marker: .codex
62
+ legacy_targets:
63
+ - .codex/prompts
64
+ target_dir: .agents/skills
65
+
66
+ codebuddy:
67
+ name: "CodeBuddy"
68
+ preferred: false
69
+ skill_invocation_prefix: "/"
70
+ installer:
71
+ legacy_targets:
72
+ - .codebuddy/commands
73
+ target_dir: .codebuddy/skills
74
+
75
+ crush:
76
+ name: "Crush"
77
+ preferred: false
78
+ # Auto-invoked from descriptions; no manual prefix
79
+ installer:
80
+ legacy_targets:
81
+ - .crush/commands
82
+ target_dir: .crush/skills
83
+
84
+ cursor:
85
+ name: "Cursor"
86
+ preferred: true
87
+ skill_invocation_prefix: "/"
88
+ installer:
89
+ legacy_targets:
90
+ - .cursor/commands
91
+ target_dir: .cursor/skills
92
+
93
+ gemini:
94
+ name: "Gemini CLI"
95
+ preferred: false
96
+ skill_invocation_prefix: "/"
97
+ installer:
98
+ legacy_targets:
99
+ - .gemini/commands
100
+ target_dir: .gemini/skills
101
+
102
+ github-copilot:
103
+ name: "GitHub Copilot"
104
+ preferred: false
105
+ # Auto-invoked from descriptions; no manual prefix
106
+ installer:
107
+ detection_marker: .github/copilot-instructions.md
108
+ legacy_targets:
109
+ - .github/agents
110
+ - .github/prompts
111
+ target_dir: .github/skills
112
+
113
+ iflow:
114
+ name: "iFlow"
115
+ preferred: false
116
+ skill_invocation_prefix: "/"
117
+ installer:
118
+ legacy_targets:
119
+ - .iflow/commands
120
+ target_dir: .iflow/skills
121
+
122
+ junie:
123
+ name: "Junie"
124
+ preferred: false
125
+ # Auto-invoked from descriptions; no manual prefix
126
+ installer:
127
+ target_dir: .junie/skills
128
+
129
+ kilo:
130
+ name: "KiloCoder"
131
+ preferred: false
132
+ # Auto-invoked from descriptions; no manual prefix
133
+ installer:
134
+ legacy_targets:
135
+ - .kilocode/workflows
136
+ target_dir: .kilocode/skills
137
+
138
+ kiro:
139
+ name: "Kiro"
140
+ preferred: false
141
+ # Auto-invoked from descriptions; no manual prefix
142
+ installer:
143
+ legacy_targets:
144
+ - .kiro/steering
145
+ target_dir: .kiro/skills
146
+
147
+ ona:
148
+ name: "Ona"
149
+ preferred: false
150
+ skill_invocation_prefix: "/"
151
+ installer:
152
+ target_dir: .ona/skills
153
+
154
+ opencode:
155
+ name: "OpenCode"
156
+ preferred: false
157
+ skill_invocation_prefix: "/"
158
+ installer:
159
+ legacy_targets:
160
+ - .opencode/agents
161
+ - .opencode/commands
162
+ - .opencode/agent
163
+ - .opencode/command
164
+ target_dir: .opencode/skills
165
+
166
+ pi:
167
+ name: "Pi"
168
+ preferred: false
169
+ skill_invocation_prefix: "/skill:"
170
+ installer:
171
+ target_dir: .pi/skills
172
+
173
+ qoder:
174
+ name: "Qoder"
175
+ preferred: false
176
+ skill_invocation_prefix: "/"
177
+ installer:
178
+ target_dir: .qoder/skills
179
+
180
+ qwen:
181
+ name: "QwenCoder"
182
+ preferred: false
183
+ skill_invocation_prefix: "/"
184
+ installer:
185
+ legacy_targets:
186
+ - .qwen/commands
187
+ target_dir: .qwen/skills
188
+
189
+ roo:
190
+ name: "Roo Code"
191
+ preferred: false
192
+ skill_invocation_prefix: "/"
193
+ installer:
194
+ legacy_targets:
195
+ - .roo/commands
196
+ target_dir: .roo/skills
197
+
198
+ rovo-dev:
199
+ name: "Rovo Dev"
200
+ preferred: false
201
+ # Auto-invoked from descriptions; no manual prefix
202
+ installer:
203
+ legacy_targets:
204
+ - .rovodev/workflows
205
+ target_dir: .rovodev/skills
206
+
207
+ trae:
208
+ name: "Trae"
209
+ preferred: false
210
+ # Auto-invoked from descriptions; no manual prefix
211
+ installer:
212
+ legacy_targets:
213
+ - .trae/rules
214
+ target_dir: .trae/skills
215
+
216
+ windsurf:
217
+ name: "Windsurf"
218
+ preferred: false
219
+ skill_invocation_prefix: "/"
220
+ installer:
221
+ legacy_targets:
222
+ - .windsurf/workflows
223
+ target_dir: .windsurf/skills