@bovinphang/frontend-craft 2.7.0 → 2.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 (380) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +34 -0
  4. package/CHANGELOG.zh-CN.md +34 -0
  5. package/README.md +1 -1
  6. package/README.openclaw.md +99 -43
  7. package/README.openclaw.zh-CN.md +99 -43
  8. package/README.zh-CN.md +1 -1
  9. package/agents/fec-architect.md +70 -70
  10. package/agents/fec-code-reviewer.md +82 -82
  11. package/agents/fec-debugger.md +20 -20
  12. package/agents/fec-design-token-mapper.md +36 -36
  13. package/agents/fec-doc-updater.md +13 -13
  14. package/agents/fec-e2e-runner.md +45 -45
  15. package/agents/fec-figma-implementer.md +59 -59
  16. package/agents/fec-performance-optimizer.md +128 -128
  17. package/agents/fec-refactor-cleaner.md +14 -14
  18. package/agents/fec-security-reviewer.md +66 -67
  19. package/agents/fec-test-planner.md +27 -27
  20. package/agents/fec-typescript-reviewer.md +87 -87
  21. package/agents/fec-ui-checker.md +74 -74
  22. package/commands/fec-debug.md +19 -19
  23. package/commands/fec-doc-sync.md +11 -11
  24. package/commands/fec-init.md +37 -38
  25. package/commands/fec-plan.md +58 -58
  26. package/commands/fec-refactor-clean.md +11 -11
  27. package/commands/fec-review.md +41 -41
  28. package/commands/fec-scaffold.md +41 -41
  29. package/commands/fec-tdd.md +13 -13
  30. package/dist/bin/frontend-craft.js +29 -27
  31. package/docs/example-prompts.md +3 -0
  32. package/docs/ja-JP/README.md +1 -1
  33. package/docs/ko-KR/README.md +1 -1
  34. package/docs/project-structure.md +13 -5
  35. package/docs/zh-CN/example-prompts.md +3 -0
  36. package/docs/zh-CN/project-structure.md +6 -1
  37. package/docs/zh-TW/README.md +1 -1
  38. package/localized/zh-CN/agents/fec-architect.md +125 -0
  39. package/localized/zh-CN/agents/fec-code-reviewer.md +152 -0
  40. package/localized/zh-CN/agents/fec-debugger.md +44 -0
  41. package/localized/zh-CN/agents/fec-design-token-mapper.md +75 -0
  42. package/localized/zh-CN/agents/fec-doc-updater.md +30 -0
  43. package/localized/zh-CN/agents/fec-e2e-runner.md +107 -0
  44. package/localized/zh-CN/agents/fec-figma-implementer.md +104 -0
  45. package/localized/zh-CN/agents/fec-performance-optimizer.md +293 -0
  46. package/localized/zh-CN/agents/fec-refactor-cleaner.md +32 -0
  47. package/localized/zh-CN/agents/fec-security-reviewer.md +116 -0
  48. package/localized/zh-CN/agents/fec-test-planner.md +50 -0
  49. package/localized/zh-CN/agents/fec-typescript-reviewer.md +142 -0
  50. package/localized/zh-CN/agents/fec-ui-checker.md +120 -0
  51. package/localized/zh-CN/commands/fec-debug.md +30 -0
  52. package/localized/zh-CN/commands/fec-doc-sync.md +19 -0
  53. package/localized/zh-CN/commands/fec-init.md +70 -0
  54. package/localized/zh-CN/commands/fec-plan.md +94 -0
  55. package/localized/zh-CN/commands/fec-refactor-clean.md +19 -0
  56. package/localized/zh-CN/commands/fec-review.md +66 -0
  57. package/localized/zh-CN/commands/fec-scaffold.md +205 -0
  58. package/localized/zh-CN/commands/fec-tdd.md +21 -0
  59. package/localized/zh-CN/skills/TEMPLATE.md +155 -0
  60. package/localized/zh-CN/skills/eval_queries.json +1013 -0
  61. package/localized/zh-CN/skills/fec-accessibility-check/SKILL.md +39 -0
  62. package/localized/zh-CN/skills/fec-accessibility-check/references/report-template.md +23 -0
  63. package/localized/zh-CN/skills/fec-accessibility-check/references/screen-reader-testing.md +33 -0
  64. package/localized/zh-CN/skills/fec-alchemy/SKILL.md +74 -0
  65. package/localized/zh-CN/skills/fec-alchemy/assets/absorption-plan-template.md +47 -0
  66. package/localized/zh-CN/skills/fec-alchemy/assets/intake-template.md +55 -0
  67. package/localized/zh-CN/skills/fec-alchemy/assets/review-checklist.md +31 -0
  68. package/localized/zh-CN/skills/fec-alchemy/references/methodology.md +94 -0
  69. package/localized/zh-CN/skills/fec-alchemy/references/originality-and-licensing.md +57 -0
  70. package/localized/zh-CN/skills/fec-api-integration/SKILL.md +78 -0
  71. package/localized/zh-CN/skills/fec-api-integration/references/integration-patterns.md +80 -0
  72. package/localized/zh-CN/skills/fec-backend-requirements-handoff/SKILL.md +45 -0
  73. package/localized/zh-CN/skills/fec-browser-storage/SKILL.md +34 -0
  74. package/localized/zh-CN/skills/fec-browser-storage/references/storage-patterns.md +65 -0
  75. package/localized/zh-CN/skills/fec-canvas-threejs/SKILL.md +66 -0
  76. package/localized/zh-CN/skills/fec-canvas-threejs/references/rendering-patterns.md +67 -0
  77. package/localized/zh-CN/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +67 -0
  78. package/localized/zh-CN/skills/fec-code-review/SKILL.md +143 -0
  79. package/localized/zh-CN/skills/fec-code-review/references/report-template.md +29 -0
  80. package/localized/zh-CN/skills/fec-component-testing/SKILL.md +119 -0
  81. package/localized/zh-CN/skills/fec-data-fetching/SKILL.md +62 -0
  82. package/localized/zh-CN/skills/fec-data-fetching/references/query-patterns.md +103 -0
  83. package/localized/zh-CN/skills/fec-debug-framework/SKILL.md +157 -0
  84. package/localized/zh-CN/skills/fec-debug-framework/references/report-template.md +58 -0
  85. package/localized/zh-CN/skills/fec-dependency-upgrade/SKILL.md +34 -0
  86. package/localized/zh-CN/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +56 -0
  87. package/localized/zh-CN/skills/fec-doc-sync/SKILL.md +39 -0
  88. package/localized/zh-CN/skills/fec-drawio-studio/SKILL.md +73 -0
  89. package/localized/zh-CN/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
  90. package/localized/zh-CN/skills/fec-drawio-studio/data/brand-icons.json +878 -0
  91. package/localized/zh-CN/skills/fec-drawio-studio/data/shape-index.json +83570 -0
  92. package/localized/zh-CN/skills/fec-drawio-studio/references/data-residency.md +27 -0
  93. package/localized/zh-CN/skills/fec-drawio-studio/references/diagram-patterns.md +60 -0
  94. package/localized/zh-CN/skills/fec-drawio-studio/references/flowchart-quality.md +49 -0
  95. package/localized/zh-CN/skills/fec-drawio-studio/references/layout-and-export.md +72 -0
  96. package/localized/zh-CN/skills/fec-drawio-studio/references/troubleshooting.md +29 -0
  97. package/localized/zh-CN/skills/fec-drawio-studio/references/xml-and-mermaid.md +58 -0
  98. package/localized/zh-CN/skills/fec-drawio-studio/scripts/brand-symbols.mjs +99 -0
  99. package/localized/zh-CN/skills/fec-drawio-studio/scripts/diagram-lint.mjs +205 -0
  100. package/localized/zh-CN/skills/fec-drawio-studio/scripts/diagram-url.mjs +102 -0
  101. package/localized/zh-CN/skills/fec-drawio-studio/scripts/drawio-export.mjs +134 -0
  102. package/localized/zh-CN/skills/fec-drawio-studio/scripts/layout-graph.mjs +107 -0
  103. package/localized/zh-CN/skills/fec-drawio-studio/scripts/png-embed-fix.mjs +26 -0
  104. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-go-packages.mjs +36 -0
  105. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-js-modules.mjs +52 -0
  106. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-python-classes.mjs +30 -0
  107. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-python-modules.mjs +55 -0
  108. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
  109. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
  110. package/localized/zh-CN/skills/fec-drawio-studio/scripts/shape-query.mjs +121 -0
  111. package/localized/zh-CN/skills/fec-drawio-studio/scripts/studio-core.mjs +139 -0
  112. package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/corporate.json +49 -0
  113. package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/default.json +49 -0
  114. package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/handdrawn.json +49 -0
  115. package/localized/zh-CN/skills/fec-drawio-studio/styles/schema.json +112 -0
  116. package/localized/zh-CN/skills/fec-e2e-testing/SKILL.md +42 -0
  117. package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-ci-reporting.md +62 -0
  118. package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-special-scenarios.md +52 -0
  119. package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-visual-regression.md +60 -0
  120. package/localized/zh-CN/skills/fec-e2e-testing/references/playwright-patterns.md +95 -0
  121. package/localized/zh-CN/skills/fec-form-handling/SKILL.md +76 -0
  122. package/localized/zh-CN/skills/fec-form-handling/references/advanced-form-patterns.md +101 -0
  123. package/localized/zh-CN/skills/fec-image-generation/SKILL.md +80 -0
  124. package/localized/zh-CN/skills/fec-image-generation/assets/interactive-diagram.html +371 -0
  125. package/localized/zh-CN/skills/fec-image-generation/references/artifact-routing.md +80 -0
  126. package/localized/zh-CN/skills/fec-image-generation/references/diagram-workflows.md +74 -0
  127. package/localized/zh-CN/skills/fec-image-generation/references/html-technical-diagrams.md +236 -0
  128. package/localized/zh-CN/skills/fec-image-generation/references/png-qa-autofix.md +30 -0
  129. package/localized/zh-CN/skills/fec-image-generation/scripts/export-diagram.mjs +364 -0
  130. package/localized/zh-CN/skills/fec-image-generation/scripts/interactive-diagram-server.mjs +654 -0
  131. package/localized/zh-CN/skills/fec-image-generation/scripts/png-qa.mjs +431 -0
  132. package/localized/zh-CN/skills/fec-image-generation/scripts/tech-diagram-render.mjs +1397 -0
  133. package/localized/zh-CN/skills/fec-implement-from-design/SKILL.md +129 -0
  134. package/localized/zh-CN/skills/fec-implement-from-design/references/design-plan-template.md +36 -0
  135. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/SKILL.md +46 -0
  136. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +110 -0
  137. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +41 -0
  138. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +48 -0
  139. package/localized/zh-CN/skills/fec-legacy-web-standard/SKILL.md +35 -0
  140. package/localized/zh-CN/skills/fec-legacy-web-standard/references/legacy-patterns.md +85 -0
  141. package/localized/zh-CN/skills/fec-list-virtualization/SKILL.md +34 -0
  142. package/localized/zh-CN/skills/fec-list-virtualization/references/virtualization-patterns.md +80 -0
  143. package/localized/zh-CN/skills/fec-monorepo-project-standard/SKILL.md +142 -0
  144. package/localized/zh-CN/skills/fec-motion-interaction/SKILL.md +73 -0
  145. package/localized/zh-CN/skills/fec-motion-interaction/references/motion-patterns.md +112 -0
  146. package/localized/zh-CN/skills/fec-nextjs-project-standard/SKILL.md +123 -0
  147. package/localized/zh-CN/skills/fec-nuxt-project-standard/SKILL.md +122 -0
  148. package/localized/zh-CN/skills/fec-performance-optimization/SKILL.md +80 -0
  149. package/localized/zh-CN/skills/fec-performance-optimization/references/framework-performance-patterns.md +38 -0
  150. package/localized/zh-CN/skills/fec-performance-optimization/references/report-template.md +59 -0
  151. package/localized/zh-CN/skills/fec-pwa-implementation/SKILL.md +35 -0
  152. package/localized/zh-CN/skills/fec-pwa-implementation/references/manifest-and-icons.md +53 -0
  153. package/localized/zh-CN/skills/fec-pwa-implementation/references/service-worker-workbox.md +68 -0
  154. package/localized/zh-CN/skills/fec-react-project-standard/SKILL.md +91 -0
  155. package/localized/zh-CN/skills/fec-react-project-standard/references/react-performance-patterns.md +35 -0
  156. package/localized/zh-CN/skills/fec-react-project-standard/references/react-project-structure.md +197 -0
  157. package/localized/zh-CN/skills/fec-react-project-standard/references/react-quality-patterns.md +131 -0
  158. package/localized/zh-CN/skills/fec-react-project-standard/references/react-runtime-patterns.md +293 -0
  159. package/localized/zh-CN/skills/fec-refactor-clean/SKILL.md +51 -0
  160. package/localized/zh-CN/skills/fec-refactor-clean/references/report-template.md +42 -0
  161. package/localized/zh-CN/skills/fec-responsive-layout/SKILL.md +34 -0
  162. package/localized/zh-CN/skills/fec-responsive-layout/references/responsive-layout-patterns.md +70 -0
  163. package/localized/zh-CN/skills/fec-route-protection/SKILL.md +135 -0
  164. package/localized/zh-CN/skills/fec-security-review/SKILL.md +38 -0
  165. package/localized/zh-CN/skills/fec-security-review/references/report-template.md +27 -0
  166. package/localized/zh-CN/skills/fec-security-review/references/security-checklist.md +64 -0
  167. package/localized/zh-CN/skills/fec-source-driven-development/SKILL.md +87 -0
  168. package/localized/zh-CN/skills/fec-state-management/SKILL.md +140 -0
  169. package/localized/zh-CN/skills/fec-state-management/references/state-patterns.md +109 -0
  170. package/localized/zh-CN/skills/fec-storybook-component-doc/SKILL.md +37 -0
  171. package/localized/zh-CN/skills/fec-storybook-component-doc/references/story-patterns.md +118 -0
  172. package/localized/zh-CN/skills/fec-svg-animation/SKILL.md +148 -0
  173. package/localized/zh-CN/skills/fec-tailwind-design-system/SKILL.md +34 -0
  174. package/localized/zh-CN/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +59 -0
  175. package/localized/zh-CN/skills/fec-tdd-workflow/SKILL.md +52 -0
  176. package/localized/zh-CN/skills/fec-testing-strategy/SKILL.md +45 -0
  177. package/localized/zh-CN/skills/fec-typescript-project-standard/SKILL.md +54 -0
  178. package/localized/zh-CN/skills/fec-typescript-project-standard/references/type-safety-patterns.md +102 -0
  179. package/localized/zh-CN/skills/fec-typescript-project-standard/references/type-safety.md +148 -0
  180. package/localized/zh-CN/skills/fec-ui-design/SKILL.md +108 -0
  181. package/localized/zh-CN/skills/fec-ui-design/data/product-rules.json +231 -0
  182. package/localized/zh-CN/skills/fec-ui-design/data/stack-ui-rules.json +146 -0
  183. package/localized/zh-CN/skills/fec-ui-design/data/style-archetypes.json +373 -0
  184. package/localized/zh-CN/skills/fec-ui-design/data/ux-quality-rules.json +203 -0
  185. package/localized/zh-CN/skills/fec-ui-design/references/design-intelligence.md +97 -0
  186. package/localized/zh-CN/skills/fec-ui-design/references/master-page-overrides.md +30 -0
  187. package/localized/zh-CN/skills/fec-ui-design/references/pre-delivery-checklist.md +39 -0
  188. package/localized/zh-CN/skills/fec-ui-design/scripts/design-system.mjs +648 -0
  189. package/localized/zh-CN/skills/fec-validation-fix/SKILL.md +51 -0
  190. package/localized/zh-CN/skills/fec-validation-fix/references/report-template.md +43 -0
  191. package/localized/zh-CN/skills/fec-vite-project-standard/SKILL.md +83 -0
  192. package/localized/zh-CN/skills/fec-vue3-project-standard/SKILL.md +58 -0
  193. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +162 -0
  194. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +13 -0
  195. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-project-structure.md +176 -0
  196. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +216 -0
  197. package/localized/zh-CN/skills/fec-web-video-presentation/SKILL.md +61 -0
  198. package/localized/zh-CN/skills/fec-web-video-presentation/data/starter-themes.json +59 -0
  199. package/localized/zh-CN/skills/fec-web-video-presentation/references/chapter-craft.md +37 -0
  200. package/localized/zh-CN/skills/fec-web-video-presentation/references/content-plan.md +38 -0
  201. package/localized/zh-CN/skills/fec-web-video-presentation/references/recording-and-audio.md +33 -0
  202. package/localized/zh-CN/skills/fec-web-video-presentation/references/theme-system.md +36 -0
  203. package/localized/zh-CN/skills/fec-web-video-presentation/scripts/create-video-presentation.mjs +430 -0
  204. package/localized/zh-CN/skills/fec-web-workers/SKILL.md +35 -0
  205. package/localized/zh-CN/skills/fec-web-workers/references/advanced-workers.md +54 -0
  206. package/localized/zh-CN/skills/fec-web-workers/references/basic-worker.md +67 -0
  207. package/localized/zh-CN/skills/metadata.json +1646 -0
  208. package/localized/zh-CN/skills/relations.json +755 -0
  209. package/localized/zh-CN/templates/claude/CLAUDE.md +106 -0
  210. package/localized/zh-CN/templates/claude/settings.json +62 -0
  211. package/localized/zh-CN/templates/codex/AGENTS.md +105 -0
  212. package/localized/zh-CN/templates/codex/config.toml +32 -0
  213. package/localized/zh-CN/templates/openclaw/AGENTS.md +101 -0
  214. package/localized/zh-CN/templates/openclaw/OPENCLAW-CONFIG.md +12 -0
  215. package/localized/zh-CN/templates/shared/rules/fec-agent-workflow.md +54 -0
  216. package/localized/zh-CN/templates/shared/rules/fec-api-layer.md +99 -0
  217. package/localized/zh-CN/templates/shared/rules/fec-ci-cd.md +40 -0
  218. package/localized/zh-CN/templates/shared/rules/fec-code-comments.md +33 -0
  219. package/localized/zh-CN/templates/shared/rules/fec-design-system.md +72 -0
  220. package/localized/zh-CN/templates/shared/rules/fec-error-handling.md +56 -0
  221. package/localized/zh-CN/templates/shared/rules/fec-git-conventions.md +73 -0
  222. package/localized/zh-CN/templates/shared/rules/fec-i18n.md +64 -0
  223. package/localized/zh-CN/templates/shared/rules/fec-naming-conventions.md +120 -0
  224. package/localized/zh-CN/templates/shared/rules/fec-performance.md +101 -0
  225. package/localized/zh-CN/templates/shared/rules/fec-react.md +82 -0
  226. package/localized/zh-CN/templates/shared/rules/fec-refactoring.md +47 -0
  227. package/localized/zh-CN/templates/shared/rules/fec-rendering-patterns.md +40 -0
  228. package/localized/zh-CN/templates/shared/rules/fec-responsive-design.md +50 -0
  229. package/localized/zh-CN/templates/shared/rules/fec-source-driven-development.md +31 -0
  230. package/localized/zh-CN/templates/shared/rules/fec-state-management.md +60 -0
  231. package/localized/zh-CN/templates/shared/rules/fec-testing.md +98 -0
  232. package/localized/zh-CN/templates/shared/rules/fec-typescript.md +112 -0
  233. package/localized/zh-CN/templates/shared/rules/fec-vue.md +64 -0
  234. package/localized/zh-CN/templates/shared/rules/fec-working-modes.md +50 -0
  235. package/openclaw.plugin.json +1 -1
  236. package/package.json +3 -2
  237. package/skills/TEMPLATE.md +74 -74
  238. package/skills/eval_queries.json +678 -678
  239. package/skills/fec-accessibility-check/SKILL.md +21 -21
  240. package/skills/fec-accessibility-check/references/report-template.md +12 -12
  241. package/skills/fec-accessibility-check/references/screen-reader-testing.md +24 -24
  242. package/skills/fec-alchemy/SKILL.md +50 -50
  243. package/skills/fec-alchemy/assets/absorption-plan-template.md +32 -32
  244. package/skills/fec-alchemy/assets/intake-template.md +55 -55
  245. package/skills/fec-alchemy/assets/review-checklist.md +23 -23
  246. package/skills/fec-alchemy/references/methodology.md +66 -66
  247. package/skills/fec-alchemy/references/originality-and-licensing.md +42 -42
  248. package/skills/fec-api-integration/SKILL.md +61 -61
  249. package/skills/fec-api-integration/references/integration-patterns.md +30 -30
  250. package/skills/fec-backend-requirements-handoff/SKILL.md +25 -25
  251. package/skills/fec-browser-storage/SKILL.md +16 -16
  252. package/skills/fec-browser-storage/references/storage-patterns.md +16 -16
  253. package/skills/fec-canvas-threejs/SKILL.md +21 -21
  254. package/skills/fec-canvas-threejs/references/rendering-patterns.md +10 -10
  255. package/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +37 -37
  256. package/skills/fec-code-review/SKILL.md +94 -94
  257. package/skills/fec-code-review/references/report-template.md +13 -13
  258. package/skills/fec-component-testing/SKILL.md +39 -39
  259. package/skills/fec-data-fetching/SKILL.md +16 -16
  260. package/skills/fec-data-fetching/references/query-patterns.md +27 -27
  261. package/skills/fec-debug-framework/SKILL.md +95 -95
  262. package/skills/fec-debug-framework/references/report-template.md +34 -34
  263. package/skills/fec-dependency-upgrade/SKILL.md +17 -17
  264. package/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +31 -31
  265. package/skills/fec-doc-sync/SKILL.md +23 -23
  266. package/skills/fec-drawio-studio/SKILL.md +42 -38
  267. package/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +1 -1
  268. package/skills/fec-drawio-studio/data/shape-index.json +83570 -0
  269. package/skills/fec-drawio-studio/references/diagram-patterns.md +19 -0
  270. package/skills/fec-drawio-studio/references/flowchart-quality.md +49 -0
  271. package/skills/fec-drawio-studio/references/layout-and-export.md +18 -3
  272. package/skills/fec-drawio-studio/references/xml-and-mermaid.md +5 -1
  273. package/skills/fec-drawio-studio/scripts/diagram-lint.mjs +62 -0
  274. package/skills/fec-drawio-studio/scripts/drawio-export.mjs +134 -0
  275. package/skills/fec-drawio-studio/scripts/shape-query.mjs +55 -15
  276. package/skills/fec-e2e-testing/SKILL.md +24 -24
  277. package/skills/fec-e2e-testing/references/e2e-ci-reporting.md +20 -20
  278. package/skills/fec-e2e-testing/references/e2e-special-scenarios.md +10 -10
  279. package/skills/fec-e2e-testing/references/e2e-visual-regression.md +17 -17
  280. package/skills/fec-e2e-testing/references/playwright-patterns.md +6 -6
  281. package/skills/fec-form-handling/SKILL.md +21 -21
  282. package/skills/fec-form-handling/references/advanced-form-patterns.md +41 -41
  283. package/skills/fec-image-generation/SKILL.md +54 -29
  284. package/skills/fec-image-generation/assets/interactive-diagram.html +371 -0
  285. package/skills/fec-image-generation/references/diagram-workflows.md +33 -2
  286. package/skills/fec-image-generation/references/html-technical-diagrams.md +236 -0
  287. package/skills/fec-image-generation/scripts/export-diagram.mjs +364 -0
  288. package/skills/fec-image-generation/scripts/interactive-diagram-server.mjs +654 -0
  289. package/skills/fec-image-generation/scripts/tech-diagram-render.mjs +1397 -0
  290. package/skills/fec-implement-from-design/SKILL.md +81 -81
  291. package/skills/fec-implement-from-design/references/design-plan-template.md +16 -16
  292. package/skills/fec-legacy-to-modern-migration/SKILL.md +29 -29
  293. package/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +81 -81
  294. package/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +37 -37
  295. package/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +31 -31
  296. package/skills/fec-legacy-web-standard/SKILL.md +17 -17
  297. package/skills/fec-legacy-web-standard/references/legacy-patterns.md +16 -16
  298. package/skills/fec-list-virtualization/SKILL.md +16 -16
  299. package/skills/fec-list-virtualization/references/virtualization-patterns.md +31 -31
  300. package/skills/fec-monorepo-project-standard/SKILL.md +52 -52
  301. package/skills/fec-motion-interaction/SKILL.md +51 -51
  302. package/skills/fec-motion-interaction/references/motion-patterns.md +11 -11
  303. package/skills/fec-nextjs-project-standard/SKILL.md +64 -64
  304. package/skills/fec-nuxt-project-standard/SKILL.md +57 -57
  305. package/skills/fec-performance-optimization/SKILL.md +54 -54
  306. package/skills/fec-performance-optimization/references/framework-performance-patterns.md +23 -23
  307. package/skills/fec-performance-optimization/references/report-template.md +31 -31
  308. package/skills/fec-pwa-implementation/SKILL.md +17 -17
  309. package/skills/fec-pwa-implementation/references/manifest-and-icons.md +12 -12
  310. package/skills/fec-pwa-implementation/references/service-worker-workbox.md +13 -13
  311. package/skills/fec-react-project-standard/SKILL.md +72 -72
  312. package/skills/fec-react-project-standard/references/react-performance-patterns.md +28 -28
  313. package/skills/fec-react-project-standard/references/react-project-structure.md +112 -112
  314. package/skills/fec-react-project-standard/references/react-quality-patterns.md +72 -72
  315. package/skills/fec-react-project-standard/references/react-runtime-patterns.md +94 -94
  316. package/skills/fec-refactor-clean/SKILL.md +30 -30
  317. package/skills/fec-refactor-clean/references/report-template.md +23 -23
  318. package/skills/fec-responsive-layout/SKILL.md +17 -17
  319. package/skills/fec-responsive-layout/references/responsive-layout-patterns.md +37 -37
  320. package/skills/fec-route-protection/SKILL.md +26 -26
  321. package/skills/fec-security-review/SKILL.md +20 -20
  322. package/skills/fec-security-review/references/report-template.md +12 -12
  323. package/skills/fec-security-review/references/security-checklist.md +27 -27
  324. package/skills/fec-source-driven-development/SKILL.md +59 -59
  325. package/skills/fec-state-management/SKILL.md +34 -34
  326. package/skills/fec-state-management/references/state-patterns.md +19 -19
  327. package/skills/fec-storybook-component-doc/SKILL.md +19 -19
  328. package/skills/fec-storybook-component-doc/references/story-patterns.md +12 -12
  329. package/skills/fec-svg-animation/SKILL.md +32 -32
  330. package/skills/fec-tailwind-design-system/SKILL.md +17 -17
  331. package/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +36 -36
  332. package/skills/fec-tdd-workflow/SKILL.md +28 -28
  333. package/skills/fec-testing-strategy/SKILL.md +29 -29
  334. package/skills/fec-typescript-project-standard/SKILL.md +38 -38
  335. package/skills/fec-typescript-project-standard/references/type-safety-patterns.md +20 -20
  336. package/skills/fec-typescript-project-standard/references/type-safety.md +18 -18
  337. package/skills/fec-ui-design/SKILL.md +90 -90
  338. package/skills/fec-ui-design/references/design-intelligence.md +61 -61
  339. package/skills/fec-ui-design/references/master-page-overrides.md +15 -15
  340. package/skills/fec-ui-design/references/pre-delivery-checklist.md +38 -38
  341. package/skills/fec-validation-fix/SKILL.md +26 -26
  342. package/skills/fec-validation-fix/references/report-template.md +25 -25
  343. package/skills/fec-vite-project-standard/SKILL.md +39 -39
  344. package/skills/fec-vue3-project-standard/SKILL.md +38 -38
  345. package/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +36 -36
  346. package/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +8 -8
  347. package/skills/fec-vue3-project-standard/references/vue3-project-structure.md +112 -112
  348. package/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +74 -74
  349. package/skills/fec-web-video-presentation/SKILL.md +33 -33
  350. package/skills/fec-web-workers/SKILL.md +16 -16
  351. package/skills/fec-web-workers/references/advanced-workers.md +13 -13
  352. package/skills/fec-web-workers/references/basic-worker.md +8 -8
  353. package/skills/metadata.json +121 -115
  354. package/skills/relations.json +4 -0
  355. package/templates/claude/CLAUDE.md +60 -60
  356. package/templates/codex/AGENTS.md +76 -76
  357. package/templates/codex/config.toml +4 -4
  358. package/templates/openclaw/AGENTS.md +68 -68
  359. package/templates/openclaw/OPENCLAW-CONFIG.md +8 -8
  360. package/templates/shared/rules/fec-agent-workflow.md +40 -40
  361. package/templates/shared/rules/fec-api-layer.md +52 -52
  362. package/templates/shared/rules/fec-ci-cd.md +29 -29
  363. package/templates/shared/rules/fec-code-comments.md +22 -22
  364. package/templates/shared/rules/fec-design-system.md +53 -53
  365. package/templates/shared/rules/fec-error-handling.md +40 -40
  366. package/templates/shared/rules/fec-git-conventions.md +42 -42
  367. package/templates/shared/rules/fec-i18n.md +48 -48
  368. package/templates/shared/rules/fec-naming-conventions.md +91 -91
  369. package/templates/shared/rules/fec-performance.md +78 -78
  370. package/templates/shared/rules/fec-react.md +58 -58
  371. package/templates/shared/rules/fec-refactoring.md +34 -34
  372. package/templates/shared/rules/fec-rendering-patterns.md +36 -36
  373. package/templates/shared/rules/fec-responsive-design.md +37 -37
  374. package/templates/shared/rules/fec-source-driven-development.md +22 -22
  375. package/templates/shared/rules/fec-state-management.md +56 -56
  376. package/templates/shared/rules/fec-testing.md +64 -64
  377. package/templates/shared/rules/fec-typescript.md +75 -75
  378. package/templates/shared/rules/fec-vue.md +42 -42
  379. package/templates/shared/rules/fec-working-modes.md +34 -34
  380. package/skills/fec-drawio-studio/data/shape-index.json.gz +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import m from"node:fs";import d from"node:path";import It from"node:readline";import j from"node:path";import z from"node:fs";import k from"node:fs";import v from"node:path";import Vn from"node:crypto";import qn from"node:os";var B;function Ge({baseDir:e,cwd:n=process.cwd(),mode:t,packageVersion:o,runtime:i,isGlobal:r}){let s=v.join(e,"frontend-craft.manifest.json");B={baseDir:v.resolve(e),cwd:v.resolve(n),homeDir:v.resolve(qn.homedir()),mode:t,packageVersion:o,runtime:i,scope:r?"global":"local",manifestPath:s,previousFiles:Bn(s),writtenFiles:new Map,skippedFiles:new Set}}function Le(){let e=B;if(B=void 0,!e)return;for(let[o,i]of e.previousFiles)e.skippedFiles.has(o)&&!e.writtenFiles.has(o)&&e.writtenFiles.set(o,i);let n=[...e.writtenFiles.entries()].map(([o,i])=>Be(o,i)).sort((o,i)=>o.path.localeCompare(i.path)),t={packageVersion:e.packageVersion,runtime:e.runtime,scope:e.scope,installedAt:new Date().toISOString(),files:n};f(v.dirname(e.manifestPath)),k.writeFileSync(e.manifestPath,`${JSON.stringify(t,null,2)}
3
- `,"utf8")}function Ue(){B=void 0}function ae(e){return v.join(e,"frontend-craft.manifest.json")}function Ie(e){if(k.existsSync(e))try{let n=JSON.parse(k.readFileSync(e,"utf8"));return{...n,files:(n.files??[]).map(t=>({...t,path:ke(t.path)}))}}catch{return}}function Bn(e){let n=Ie(e);return new Map((n?.files??[]).map(t=>[qe(t.root??"baseDir",ke(t.path)),t.hash]))}function We(e){return Vn.createHash("sha256").update(e).digest("hex")}function ve(e){return We(k.readFileSync(e))}function Ve(e){let n=B;if(!n)return;let t=v.resolve(e),o=[["baseDir",n.baseDir],["cwd",n.cwd],["home",n.homeDir]];for(let[i,r]of o){let s=v.relative(r,t);if(s&&!s.startsWith("..")&&!v.isAbsolute(s))return qe(i,ke(s))}}function ke(e){return e.split(v.sep).join("/")}function qe(e,n){return`${e}:${n}`}function Be(e,n){let t=/^(baseDir|cwd|home):(.*)$/.exec(e);if(!t)return{path:e,hash:n};let o=t[1];return{...o==="baseDir"?{}:{root:o},path:t[2],hash:n}}function ze(e){let n=B,t=Ve(e);if(!n||!t||n.mode!=="update"||!k.existsSync(e))return!1;let o=n.previousFiles.get(t);return!o||ve(e)===o?!1:(n.skippedFiles.add(t),console.log(`Skipped modified file: ${Be(t,o).path}`),!0)}function He(e,n){let t=B,o=Ve(e);!t||!o||t.writtenFiles.set(o,We(n))}function f(e){k.existsSync(e)||k.mkdirSync(e,{recursive:!0})}function D(e,n){if(ze(n))return;f(v.dirname(n));let t=k.readFileSync(e);k.copyFileSync(e,n),He(n,t)}function p(e,n,t={}){if(k.existsSync(e)){f(n);for(let o of k.readdirSync(e)){let i=v.join(e,o),r=o;if(t.filter&&!t.filter(r))continue;let s=v.join(n,o);k.statSync(i).isDirectory()?p(i,s,t):D(i,s)}}}function C(e){return k.readFileSync(e,"utf8")}function y(e,n){ze(e)||(f(v.dirname(e)),k.writeFileSync(e,n,"utf8"),He(e,n))}function zn(e,n){let t=j.resolve(e);return n.replaceAll("${CLAUDE_PLUGIN_ROOT}",t).replaceAll("${FRONTEND_CRAFT_ROOT}",t)}function Hn(e){let n=j.join(e,"hooks","hooks.json"),t=C(n);return zn(e,t)}async function Ke(e){let{pluginRoot:n,baseDir:t,dryRun:o,cwd:i,isGlobal:r}=e;if(o){console.log(`[dry-run] would install Claude Code files into ${t}`);return}f(t),p(j.join(n,"skills"),j.join(t,"skills")),p(j.join(n,"agents"),j.join(t,"agents")),p(j.join(n,"commands"),j.join(t,"commands")),r||p(j.join(n,"templates","shared","rules"),j.join(t,"rules"));let s=j.join(n,"templates","claude");if(z.existsSync(s))for(let l of z.readdirSync(s)){let c=j.join(t,l);z.existsSync(c)||D(j.join(s,l),c)}if(y(j.join(t,"hooks.json"),Hn(n)),!r&&z.existsSync(j.join(n,".mcp.json"))){let l=j.join(i,".mcp.json");z.existsSync(l)||D(j.join(n,".mcp.json"),l)}let a=j.join(n,".claude-plugin","plugin.json");if(!r&&z.existsSync(a)){f(j.join(i,".claude-plugin")),D(a,j.join(i,".claude-plugin","plugin.json"));let l=j.join(n,".claude-plugin","marketplace.json");z.existsSync(l)&&D(l,j.join(i,".claude-plugin","marketplace.json"))}}import $ from"node:path";import se from"node:fs";import Kn from"node:os";function Je(e,n){let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);if(!t)throw new Error(`no frontmatter: ${n}`);let o=t[1],i=t[2].trim().replace(/\.claude\/rules/g,".codex/rules").replace(/\bCLAUDE\.md\b/g,"AGENTS.md"),r=o.match(/^name:\s*(.+)$/m);if(!r)throw new Error(`no name in frontmatter: ${n}`);let s=r[1].trim(),a=o.match(/^description:\s*(.+)$/m),l=a?a[1].trim():"";return`name = "${s}"
4
- description = "${(u=>u.replace(/\\/g,"\\\\").replace(/"/g,'\\"'))(l)}"
2
+ import m from"node:fs";import d from"node:path";import At from"node:readline";import S from"node:path";import K from"node:fs";import k from"node:fs";import v from"node:path";import Zn from"node:crypto";import et from"node:os";var H;function Ke({baseDir:e,cwd:n=process.cwd(),mode:t,packageVersion:o,runtime:i,isGlobal:r,language:s}){let l=v.join(e,"frontend-craft.manifest.json");H={baseDir:v.resolve(e),cwd:v.resolve(n),homeDir:v.resolve(et.homedir()),mode:t,packageVersion:o,runtime:i,scope:r?"global":"local",language:s,manifestPath:l,previousFiles:nt(l),writtenFiles:new Map,skippedFiles:new Set}}function Je(){let e=H;if(H=void 0,!e)return;for(let[o,i]of e.previousFiles)e.skippedFiles.has(o)&&!e.writtenFiles.has(o)&&e.writtenFiles.set(o,i);let n=[...e.writtenFiles.entries()].map(([o,i])=>en(o,i)).sort((o,i)=>o.path.localeCompare(i.path)),t={packageVersion:e.packageVersion,runtime:e.runtime,scope:e.scope,language:e.language,installedAt:new Date().toISOString(),files:n};f(v.dirname(e.manifestPath)),k.writeFileSync(e.manifestPath,`${JSON.stringify(t,null,2)}
3
+ `,"utf8")}function Ye(){H=void 0}function re(e){return v.join(e,"frontend-craft.manifest.json")}function le(e){if(k.existsSync(e))try{let n=JSON.parse(k.readFileSync(e,"utf8"));return{...n,files:(n.files??[]).map(t=>({...t,path:Ne(t.path)}))}}catch{return}}function nt(e){let n=le(e);return new Map((n?.files??[]).map(t=>[Ze(t.root??"baseDir",Ne(t.path)),t.hash]))}function Qe(e){return Zn.createHash("sha256").update(e).digest("hex")}function $e(e){return Qe(k.readFileSync(e))}function Xe(e){let n=H;if(!n)return;let t=v.resolve(e),o=[["baseDir",n.baseDir],["cwd",n.cwd],["home",n.homeDir]];for(let[i,r]of o){let s=v.relative(r,t);if(s&&!s.startsWith("..")&&!v.isAbsolute(s))return Ze(i,Ne(s))}}function Ne(e){return e.split(v.sep).join("/")}function Ze(e,n){return`${e}:${n}`}function en(e,n){let t=/^(baseDir|cwd|home):(.*)$/.exec(e);if(!t)return{path:e,hash:n};let o=t[1];return{...o==="baseDir"?{}:{root:o},path:t[2],hash:n}}function nn(e){let n=H,t=Xe(e);if(!n||!t||n.mode!=="update"||!k.existsSync(e))return!1;let o=n.previousFiles.get(t);return!o||$e(e)===o?!1:(n.skippedFiles.add(t),console.log(`Skipped modified file: ${en(t,o).path}`),!0)}function tn(e,n){let t=H,o=Xe(e);!t||!o||t.writtenFiles.set(o,Qe(n))}function f(e){k.existsSync(e)||k.mkdirSync(e,{recursive:!0})}function D(e,n){if(nn(n))return;f(v.dirname(n));let t=k.readFileSync(e);k.copyFileSync(e,n),tn(n,t)}function p(e,n,t={}){if(k.existsSync(e)){f(n);for(let o of k.readdirSync(e)){let i=v.join(e,o),r=o;if(t.filter&&!t.filter(r))continue;let s=v.join(n,o);k.statSync(i).isDirectory()?p(i,s,t):D(i,s)}}}function C(e){return k.readFileSync(e,"utf8")}function y(e,n){nn(e)||(f(v.dirname(e)),k.writeFileSync(e,n,"utf8"),tn(e,n))}function tt(e,n){let t=S.resolve(e);return n.replaceAll("${CLAUDE_PLUGIN_ROOT}",t).replaceAll("${FRONTEND_CRAFT_ROOT}",t)}function ot(e){let n=S.join(e,"hooks","hooks.json"),t=C(n);return tt(e,t)}async function on(e){let{pluginRoot:n,contentRoot:t,baseDir:o,dryRun:i,cwd:r,isGlobal:s}=e;if(i){console.log(`[dry-run] would install Claude Code files into ${o}`);return}f(o),p(S.join(t,"skills"),S.join(o,"skills")),p(S.join(t,"agents"),S.join(o,"agents")),p(S.join(t,"commands"),S.join(o,"commands")),s||p(S.join(t,"templates","shared","rules"),S.join(o,"rules"));let l=S.join(t,"templates","claude");if(K.existsSync(l))for(let c of K.readdirSync(l)){let u=S.join(o,c);K.existsSync(u)||D(S.join(l,c),u)}if(y(S.join(o,"hooks.json"),ot(n)),!s&&K.existsSync(S.join(n,".mcp.json"))){let c=S.join(r,".mcp.json");K.existsSync(c)||D(S.join(n,".mcp.json"),c)}let a=S.join(n,".claude-plugin","plugin.json");if(!s&&K.existsSync(a)){f(S.join(r,".claude-plugin")),D(a,S.join(r,".claude-plugin","plugin.json"));let c=S.join(n,".claude-plugin","marketplace.json");K.existsSync(c)&&D(c,S.join(r,".claude-plugin","marketplace.json"))}}import $ from"node:path";import ae from"node:fs";import st from"node:os";function sn(e,n){let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);if(!t)throw new Error(`no frontmatter: ${n}`);let o=t[1],i=t[2].trim().replace(/\.claude\/rules/g,".codex/rules").replace(/\bCLAUDE\.md\b/g,"AGENTS.md"),r=o.match(/^name:\s*(.+)$/m);if(!r)throw new Error(`no name in frontmatter: ${n}`);let s=r[1].trim(),l=o.match(/^description:\s*(.+)$/m),a=l?l[1].trim():"";return`name = "${s}"
4
+ description = "${(u=>u.replace(/\\/g,"\\\\").replace(/"/g,'\\"'))(a)}"
5
5
 
6
6
  model = "gpt-5.4"
7
7
  model_reasoning_effort = "high"
@@ -9,43 +9,44 @@ model_reasoning_effort = "high"
9
9
  developer_instructions = """
10
10
  `+i+`
11
11
  """
12
- `}async function Ye(e){let{pluginRoot:n,baseDir:t,cwd:o,dryRun:i,isGlobal:r}=e,s=$.join(n,"agents"),a=$.join(t,"agents"),l=$.join(t,"rules"),c=r?$.join(Kn.homedir(),".agents","skills"):$.join(o,".agents","skills");if(i){console.log(`[dry-run] codex: ${t}, agents -> ${a}, skills -> ${c}`);return}f(a),f(c);for(let S of se.readdirSync(s)){if(!S.endsWith(".md"))continue;let M=C($.join(s,S)),I=Je(M,S);y($.join(a,S.replace(/\.md$/,".toml")),I)}p($.join(n,"skills"),c);let u=$.join(n,"templates","shared","rules");!r&&se.existsSync(u)&&p(u,l);let g=$.join(n,"templates","codex","AGENTS.md"),R=$.join(n,"templates","codex","config.toml");if(!r&&se.existsSync(g)){let S=$.join(o,"AGENTS.md");se.existsSync(S)||D(g,S)}se.existsSync(R)&&D(R,$.join(t,"config.toml"))}import Y from"node:path";import Qe from"node:fs";async function Xe(e){let{pluginRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] cursor -> ${t}`);return}f(t);let r=Y.join(t,"skills");p(Y.join(n,"skills"),r);let s=Y.join(n,"templates","shared","rules"),a=Y.join(t,"rules");if(!i&&Qe.existsSync(s)){f(a);for(let l of Qe.readdirSync(s)){if(!l.endsWith(".md"))continue;let c=C(Y.join(s,l)),u=l.replace(/\.md$/,""),g=`---
12
+ `}async function rn(e){let{contentRoot:n,baseDir:t,cwd:o,dryRun:i,isGlobal:r}=e,s=$.join(n,"agents"),l=$.join(t,"agents"),a=$.join(t,"rules"),c=r?$.join(st.homedir(),".agents","skills"):$.join(o,".agents","skills");if(i){console.log(`[dry-run] codex: ${t}, agents -> ${l}, skills -> ${c}`);return}f(l),f(c);for(let j of ae.readdirSync(s)){if(!j.endsWith(".md"))continue;let R=C($.join(s,j)),M=sn(R,j);y($.join(l,j.replace(/\.md$/,".toml")),M)}p($.join(n,"skills"),c);let u=$.join(n,"templates","shared","rules");!r&&ae.existsSync(u)&&p(u,a);let g=$.join(n,"templates","codex","AGENTS.md"),b=$.join(n,"templates","codex","config.toml");if(!r&&ae.existsSync(g)){let j=$.join(o,"AGENTS.md");ae.existsSync(j)||D(g,j)}ae.existsSync(b)&&D(b,$.join(t,"config.toml"))}import Z from"node:path";import ln from"node:fs";async function an(e){let{contentRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] cursor -> ${t}`);return}f(t);let r=Z.join(t,"skills");p(Z.join(n,"skills"),r);let s=Z.join(n,"templates","shared","rules"),l=Z.join(t,"rules");if(!i&&ln.existsSync(s)){f(l);for(let a of ln.readdirSync(s)){if(!a.endsWith(".md"))continue;let c=C(Z.join(s,a)),u=a.replace(/\.md$/,""),g=`---
13
13
  description: Frontend Craft - ${u}
14
14
  globs: "**/*.{ts,tsx,vue,js,jsx,css,scss,less,html}"
15
15
  ---
16
16
 
17
17
  `+c+`
18
- `;y(Y.join(a,`${u}.mdc`),g)}}}import E from"node:path";import we from"node:fs";async function Ze(e){let{pluginRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] windsurf -> ${t}`);return}f(t);let r=E.join(t,"workflows"),s=E.join(t,"rules");f(r);let a=E.join(n,"commands");for(let c of we.readdirSync(a)){if(!c.endsWith(".md"))continue;let u=C(E.join(a,c));y(E.join(r,c),u)}let l=E.join(n,"templates","shared","rules");if(!i&&we.existsSync(l)){f(s);for(let c of we.readdirSync(l)){if(!c.endsWith(".md"))continue;let u=C(E.join(l,c));y(E.join(s,c),u)}}p(E.join(n,"skills"),E.join(t,"skills"))}import A from"node:path";import ie from"node:fs";async function ce(e){let{pluginRoot:n,baseDir:t,dryRun:o}=e,i=A.join(t,"command");if(o){console.log(`[dry-run] opencode/kilo commands -> ${i}`);return}f(i);let r=A.join(n,"commands");for(let c of ie.readdirSync(r)){if(!c.endsWith(".md"))continue;let u=C(A.join(r,c));y(A.join(i,c),u)}let s=A.join(t,"skills");f(s);let a=A.join(n,"skills");for(let c of ie.readdirSync(a)){let u=A.join(a,c);if(!ie.statSync(u).isDirectory())continue;let g=A.join(u,"SKILL.md");if(ie.existsSync(g)){let R=A.join(s,c);p(u,R)}}let l=A.join(t,"opencode.jsonc");e.runtime==="opencode"&&!ie.existsSync(l)&&y(l,`{
18
+ `;y(Z.join(l,`${u}.mdc`),g)}}}import E from"node:path";import Oe from"node:fs";async function cn(e){let{contentRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] windsurf -> ${t}`);return}f(t);let r=E.join(t,"workflows"),s=E.join(t,"rules");f(r);let l=E.join(n,"commands");for(let c of Oe.readdirSync(l)){if(!c.endsWith(".md"))continue;let u=C(E.join(l,c));y(E.join(r,c),u)}let a=E.join(n,"templates","shared","rules");if(!i&&Oe.existsSync(a)){f(s);for(let c of Oe.readdirSync(a)){if(!c.endsWith(".md"))continue;let u=C(E.join(a,c));y(E.join(s,c),u)}}p(E.join(n,"skills"),E.join(t,"skills"))}import L from"node:path";import ce from"node:fs";async function ge(e){let{contentRoot:n,baseDir:t,dryRun:o}=e,i=L.join(t,"command");if(o){console.log(`[dry-run] opencode/kilo commands -> ${i}`);return}f(i);let r=L.join(n,"commands");for(let c of ce.readdirSync(r)){if(!c.endsWith(".md"))continue;let u=C(L.join(r,c));y(L.join(i,c),u)}let s=L.join(t,"skills");f(s);let l=L.join(n,"skills");for(let c of ce.readdirSync(l)){let u=L.join(l,c);if(!ce.statSync(u).isDirectory())continue;let g=L.join(u,"SKILL.md");if(ce.existsSync(g)){let b=L.join(s,c);p(u,b)}}let a=L.join(t,"opencode.jsonc");e.runtime==="opencode"&&!ce.existsSync(a)&&y(a,`{
19
19
  "$schema": "https://opencode.ai/config.json",
20
20
  "permissions": { "bash": "allow" }
21
21
  }
22
- `)}async function en(e){return ce(e)}async function nn(e){return ce(e)}import re from"node:path";import tn from"node:fs";async function on(e){let{pluginRoot:n,baseDir:t,cwd:o,dryRun:i,isGlobal:r}=e;if(i){console.log(`[dry-run] gemini -> ${t}`);return}f(t);let s=re.join(t,"extensions","frontend-craft");f(s),p(re.join(n,"skills"),re.join(s,"skills"));let a=re.join(n,"templates","claude","CLAUDE.md"),l=re.join(o,"GEMINI.md");if(!r&&!tn.existsSync(l)&&tn.existsSync(a)){let c=C(a).replaceAll(".claude/",".gemini/").replaceAll("CLAUDE.md","GEMINI.md");y(l,c)}}import L from"node:path";import Re from"node:fs";async function sn(e){let{pluginRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] copilot -> ${t}`);return}f(t);let r=L.join(t,"instructions"),s=L.join(t,"prompts");if(f(s),!i){f(r);let l=L.join(n,"templates","shared","rules"),c=[`# Frontend Craft - Copilot instructions
23
- `];if(Re.existsSync(l))for(let u of Re.readdirSync(l))u.endsWith(".md")&&c.push(`
22
+ `)}async function un(e){return ge(e)}async function fn(e){return ge(e)}import ue from"node:path";import dn from"node:fs";async function pn(e){let{contentRoot:n,baseDir:t,cwd:o,dryRun:i,isGlobal:r}=e;if(i){console.log(`[dry-run] gemini -> ${t}`);return}f(t);let s=ue.join(t,"extensions","frontend-craft");f(s),p(ue.join(n,"skills"),ue.join(s,"skills"));let l=ue.join(n,"templates","claude","CLAUDE.md"),a=ue.join(o,"GEMINI.md");if(!r&&!dn.existsSync(a)&&dn.existsSync(l)){let c=C(l).replaceAll(".claude/",".gemini/").replaceAll("CLAUDE.md","GEMINI.md");y(a,c)}}import W from"node:path";import Fe from"node:fs";async function mn(e){let{contentRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] copilot -> ${t}`);return}f(t);let r=W.join(t,"instructions"),s=W.join(t,"prompts");if(f(s),!i){f(r);let a=W.join(n,"templates","shared","rules"),c=[`# Frontend Craft - Copilot instructions
23
+ `];if(Fe.existsSync(a))for(let u of Fe.readdirSync(a))u.endsWith(".md")&&c.push(`
24
24
  ## ${u}
25
25
 
26
- `,C(L.join(l,u)));y(L.join(r,"frontend-craft.instructions.md"),c.join(""))}let a=L.join(n,"commands");for(let l of Re.readdirSync(a))l.endsWith(".md")&&y(L.join(s,l),C(L.join(a,l)))}import Q from"node:path";async function rn(e){let{pluginRoot:n,baseDir:t,dryRun:o}=e;if(o)return console.log(`[dry-run] antigravity -> ${t}`);f(t),p(Q.join(n,"skills"),Q.join(t,"skills"))}async function ln(e){let{pluginRoot:n,baseDir:t,dryRun:o}=e;if(o)return console.log(`[dry-run] augment -> ${t}`);f(t),p(Q.join(n,"skills"),Q.join(t,"skills"))}async function an(e){let{pluginRoot:n,baseDir:t,dryRun:o}=e;if(o)return console.log(`[dry-run] codebuddy -> ${t}`);f(t),p(Q.join(n,"skills"),Q.join(t,"skills"))}import ue from"node:path";import cn from"node:fs";async function un(e){let{pluginRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o)return console.log(`[dry-run] trae -> ${t}`);if(i)return;let r=ue.join(t,"rules");f(r);let s=ue.join(n,"templates","shared","rules"),a=[`# Frontend Craft - Trae rules bundle
27
- `];if(cn.existsSync(s))for(let l of cn.readdirSync(s))l.endsWith(".md")&&a.push(`
28
- ## ${l}
29
-
30
- `,C(ue.join(s,l)));y(ue.join(r,"frontend-craft.md"),a.join(""))}import fe from"node:path";import fn from"node:fs";async function dn(e){let{pluginRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o)return console.log(`[dry-run] cline -> ${fe.join(t,".clinerules")}`);if(i)return;let r=fe.join(n,"templates","shared","rules"),s=[`# Frontend Craft - Cline rules
31
- `];if(fn.existsSync(r))for(let a of fn.readdirSync(r))a.endsWith(".md")&&s.push(`
26
+ `,C(W.join(a,u)));y(W.join(r,"frontend-craft.instructions.md"),c.join(""))}let l=W.join(n,"commands");for(let a of Fe.readdirSync(l))a.endsWith(".md")&&y(W.join(s,a),C(W.join(l,a)))}import ee from"node:path";async function gn(e){let{contentRoot:n,baseDir:t,dryRun:o}=e;if(o)return console.log(`[dry-run] antigravity -> ${t}`);f(t),p(ee.join(n,"skills"),ee.join(t,"skills"))}async function hn(e){let{contentRoot:n,baseDir:t,dryRun:o}=e;if(o)return console.log(`[dry-run] augment -> ${t}`);f(t),p(ee.join(n,"skills"),ee.join(t,"skills"))}async function yn(e){let{contentRoot:n,baseDir:t,dryRun:o}=e;if(o)return console.log(`[dry-run] codebuddy -> ${t}`);f(t),p(ee.join(n,"skills"),ee.join(t,"skills"))}import he from"node:path";import Cn from"node:fs";async function Sn(e){let{contentRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o)return console.log(`[dry-run] trae -> ${t}`);if(i)return;let r=he.join(t,"rules");f(r);let s=he.join(n,"templates","shared","rules"),l=[`# Frontend Craft - Trae rules bundle
27
+ `];if(Cn.existsSync(s))for(let a of Cn.readdirSync(s))a.endsWith(".md")&&l.push(`
32
28
  ## ${a}
33
29
 
34
- `,C(fe.join(r,a)));y(fe.join(t,".clinerules"),s.join(""))}import H from"node:path";import De from"node:fs";async function pn(e){let{pluginRoot:n,baseDir:t,cwd:o,dryRun:i}=e;if(i)return console.log(`[dry-run] openclaw -> ${t}`);f(t),p(H.join(n,"skills"),H.join(t,"skills")),p(H.join(n,"commands"),H.join(t,"commands"));let r=H.join(n,"templates","openclaw");if(De.existsSync(r))for(let s of De.readdirSync(r)){if(!s.endsWith(".md"))continue;let a=H.join(o,s);De.existsSync(a)||D(H.join(r,s),a)}}import O from"node:path";import mn from"node:fs";var Jn=["fec-security-check.js","fec-format-changed-file.js","fec-run-tests.js","fec-notify.js"];async function gn(e){let{pluginRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o){console.log(`[dry-run] qoder -> ${t}`);return}f(t),p(O.join(n,"skills"),O.join(t,"skills")),p(O.join(n,"commands"),O.join(t,"commands")),p(O.join(n,"agents"),O.join(t,"agents")),i||p(O.join(n,"templates","shared","rules"),O.join(t,"rules")),Yn(n,O.join(t,"hooks")),y(O.join(t,"settings.json"),JSON.stringify(Qn(t),null,2)+`
35
- `)}function Yn(e,n){f(n);for(let t of Jn){let o=O.join(e,"dist","hooks",t);if(!mn.existsSync(o))throw new Error(`Missing built hook script: ${o}. Run "npm run build" before installing.`);D(o,O.join(n,t))}}function Qn(e){let n=O.join(e,"settings.json"),t=Xn(n);return{...t,hooks:{...X(t.hooks),PreToolUse:[...pe(X(t.hooks).PreToolUse),de("Bash|Shell",".qoder/hooks/fec-security-check.js","Checking command safety...")],PostToolUse:[...pe(X(t.hooks).PostToolUse),de("Write|Edit|MultiEdit",".qoder/hooks/fec-format-changed-file.js","Running formatter...")],Stop:[...pe(X(t.hooks).Stop),de(".*",".qoder/hooks/fec-run-tests.js","Running final validation...")],Notification:[...pe(X(t.hooks).Notification),de(".*",".qoder/hooks/fec-notify.js")]}}}function Xn(e){if(!mn.existsSync(e))return{};try{let n=JSON.parse(C(e));return X(n)}catch{return{}}}function de(e,n,t){return{matcher:e,hooks:[{type:"command",command:`node "${n}"`,...t?{statusMessage:t}:{}}]}}function X(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:{}}function pe(e){return Array.isArray(e)?e:[]}var F=["claude","codex","cursor","windsurf","opencode","kilo","gemini","copilot","antigravity","augment","trae","codebuddy","cline","openclaw","qoder"],me={claude:Ke,codex:Ye,cursor:Xe,windsurf:Ze,opencode:en,kilo:nn,gemini:on,copilot:sn,antigravity:rn,augment:ln,trae:un,codebuddy:an,cline:dn,openclaw:pn,qoder:gn};import Zn from"node:fs";import et from"node:os";import nt from"node:path";import he from"node:readline";import hn from"node:os";import b from"node:path";function x(e){return e&&(e.startsWith("~/")||e==="~"?b.join(hn.homedir(),e.slice(1)):e)}function ge(e){let n=hn.homedir(),t=process.env;switch(e){case"claude":return t.CLAUDE_CONFIG_DIR?x(t.CLAUDE_CONFIG_DIR):b.join(n,".claude");case"cursor":return t.CURSOR_CONFIG_DIR?x(t.CURSOR_CONFIG_DIR):b.join(n,".cursor");case"gemini":return t.GEMINI_CONFIG_DIR?x(t.GEMINI_CONFIG_DIR):b.join(n,".gemini");case"codex":return t.CODEX_HOME?x(t.CODEX_HOME):b.join(n,".codex");case"copilot":return t.COPILOT_CONFIG_DIR?x(t.COPILOT_CONFIG_DIR):b.join(n,".copilot");case"antigravity":return t.ANTIGRAVITY_CONFIG_DIR?x(t.ANTIGRAVITY_CONFIG_DIR):b.join(n,".gemini","antigravity");case"windsurf":return t.WINDSURF_CONFIG_DIR?x(t.WINDSURF_CONFIG_DIR):b.join(n,".codeium","windsurf");case"augment":return t.AUGMENT_CONFIG_DIR?x(t.AUGMENT_CONFIG_DIR):b.join(n,".augment");case"trae":return t.TRAE_CONFIG_DIR?x(t.TRAE_CONFIG_DIR):b.join(n,".trae");case"codebuddy":return t.CODEBUDDY_CONFIG_DIR?x(t.CODEBUDDY_CONFIG_DIR):b.join(n,".codebuddy");case"cline":return t.CLINE_CONFIG_DIR?x(t.CLINE_CONFIG_DIR):b.join(n,".cline");case"opencode":return t.OPENCODE_CONFIG_DIR?x(t.OPENCODE_CONFIG_DIR):t.XDG_CONFIG_HOME?b.join(x(t.XDG_CONFIG_HOME),"opencode"):b.join(n,".config","opencode");case"kilo":return t.KILO_CONFIG_DIR?x(t.KILO_CONFIG_DIR):t.XDG_CONFIG_HOME?b.join(x(t.XDG_CONFIG_HOME),"kilo"):b.join(n,".config","kilo");case"openclaw":return t.OPENCLAW_CONFIG_DIR?x(t.OPENCLAW_CONFIG_DIR):b.join(n,".openclaw");case"qoder":return t.QODER_CONFIG_DIR?x(t.QODER_CONFIG_DIR):b.join(n,".qoder");default:return t.CLAUDE_CONFIG_DIR?x(t.CLAUDE_CONFIG_DIR):b.join(n,".claude")}}var $e={claude:".claude",codex:".codex",cursor:".cursor",windsurf:".windsurf",opencode:".opencode",kilo:".kilo",gemini:".gemini",copilot:".github",antigravity:".agent",augment:".augment",trae:".trae",codebuddy:".codebuddy",cline:"",openclaw:".openclaw",qoder:".qoder"};function Z({runtime:e,isGlobal:n,cwd:t}){if(n)return ge(e);if(e==="cline")return t;let o=$e[e]??".claude";return b.join(t,o)}var tt={claude:"Claude Code",codex:"Codex",cursor:"Cursor",windsurf:"Windsurf",opencode:"OpenCode",kilo:"Kilo",gemini:"Gemini",copilot:"Copilot",antigravity:"Antigravity",augment:"Augment",trae:"Trae",codebuddy:"CodeBuddy",cline:"Cline",openclaw:"OpenClaw",qoder:"Qoder"};function Cn(e){let n=et.homedir();return e===n?"~":e.startsWith(`${n}${nt.sep}`)?`~${e.slice(n.length)}`:e}function ot(e){let n=$e[e];return n?`./${n}`:"./"}var Ce=F.map((e,n)=>({choice:String(n+1),runtime:e,label:tt[e]??e})),st=String(Ce.length+1);function yn(e){return e.filter((n,t)=>e.indexOf(n)===t)}function it(e,n,t){return Math.max(n,Math.min(t,e))}function rt(e){return!e||e.ctrl||e.meta?"":typeof e.sequence=="string"&&e.sequence.length===1&&e.sequence>=" "?e.sequence:typeof e.name=="string"&&e.name.length===1?e.name:""}function lt(){return Ce.map(e=>{let n=Cn(ge(e.runtime));return{value:e.runtime,label:e.label,description:n,selectedSuffix:"selected"}})}function at(e){let n=yn(e.map(o=>Cn(ge(o)))).join(", "),t=yn(e.map(o=>ot(o))).join(", ");return[{value:"global",label:"Global",description:`${n} - available in all projects`,selectedSuffix:"selected"},{value:"local",label:"Local",description:`${t} - this project only`,selectedSuffix:"selected"}]}function jn({message:e,options:n,selected:t=[],multiple:o=!0,pageSize:i=15,validate:r=a=>a.length>0,transform:s=(a=>a)}){return{message:e,options:n,selected:t.filter((l,c)=>t.indexOf(l)===c),multiple:o,pageSize:i,search:"",cursor:0,error:"",visibleOptions(){let l=this.search.trim().toLowerCase();return l?this.options.filter(c=>c.label.toLowerCase().includes(l)||c.value.toLowerCase().includes(l)):this.options},move(l){let c=this.visibleOptions();this.cursor=it(this.cursor+l,0,Math.max(0,c.length-1)),this.error=""},toggle(){let l=this.visibleOptions()[this.cursor];l&&(this.multiple?this.selected.includes(l.value)?this.selected=this.selected.filter(c=>c!==l.value):this.selected=[...this.selected,l.value]:this.selected=[l.value],this.error="")},backspace(){this.search.length>0?(this.search=this.search.slice(0,-1),this.cursor=0):this.selected.length>0&&(this.selected=this.selected.slice(0,-1)),this.error=""},type(l){this.search+=l,this.cursor=0,this.error=""},confirm(){let l=r(this.selected);if(l!==!0){this.error=typeof l=="string"?l:"Select at least one option";return}return s(this.selected)}}}function Sn(e={}){return jn({message:`Which runtime(s) would you like to install for? (${Ce.length} available)`,options:lt(),selected:["claude"],multiple:!0,pageSize:e.pageSize??15,transform:n=>n})}function bn(e,n={}){return jn({message:"Where would you like to install?",options:at(e),selected:["global"],multiple:!1,pageSize:n.pageSize??15,transform:t=>t[0]!=="local"})}function ye(e){let n=e.visibleOptions(),t=new Set(e.selected),o=new Map(e.options.map(s=>[s.value,s])),i=e.selected.length?e.selected.map(s=>o.get(s)?.label??s).join(", "):"(none selected)",r=[`? ${e.message}`,` Selected: ${i}`,` Search: [${e.search||"type to filter"}]`," Up/Down navigate - Space toggle - Backspace remove - Enter confirm"];if(n.length===0)r.push(" No matches");else{let s=Math.max(0,Math.min(e.cursor-Math.floor(e.pageSize/2),n.length-e.pageSize)),a=Math.min(s+e.pageSize,n.length),l=n.slice(s,a);for(let c=0;c<l.length;c++){let u=l[c],R=s+c===e.cursor,S=t.has(u.value),M=R?">":" ",I=S?"[x]":"[ ]",oe=u.description?` (${u.description})`:"",W=S?` (${u.selectedSuffix??"selected"})`:oe;r.push(` ${M} ${I} ${u.label}${W}`)}if(n.length>e.pageSize){let c=Math.floor(e.cursor/e.pageSize)+1,u=Math.ceil(n.length/e.pageSize);r.push(` (${c}/${u})`)}}return e.error&&r.push(` ${e.error}`),r.join(`
36
- `)}function ct(){return ye(Sn())}function ut(e){let t=((e==null?"":String(e)).trim()||"1").split(/[\s,]+/).filter(Boolean);if(t.includes(st))return F.slice();let o=[],i=new Set,r=new Map(Ce.map(s=>[s.choice,s.runtime]));for(let s of t){let a=r.get(s);!a||i.has(a)||(i.add(a),o.push(a))}return o.length?o:["claude"]}function ft(e){return ye(bn(e))}function dt(e){return((e==null?"":String(e)).trim()||"1")!=="2"}var Oe;function xn(e){return process.stdout.write(e),Oe||(Oe=Zn.readFileSync(0,"utf8").split(/\r?\n/)),Oe.shift()??""}function In(e){return process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1"&&!process.stdin.isTTY?Promise.resolve(xn(e)):new Promise(n=>{let t=he.createInterface({input:process.stdin,output:process.stdout});t.question(e,o=>{t.close(),n(o)}),t.on("close",()=>n(""))})}async function vn(e){return process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1"&&!process.stdin.isTTY?xn(`${ye(e)}
37
- `):new Promise(n=>{let t=process.stdin,o=process.stdout,i=t.isRaw,r=0;function s(){r>0&&(he.moveCursor(o,0,-r),he.clearScreenDown(o));let c=ye(e);o.write(c),o.write(`
30
+ `,C(he.join(s,a)));y(he.join(r,"frontend-craft.md"),l.join(""))}import ye from"node:path";import jn from"node:fs";async function xn(e){let{contentRoot:n,baseDir:t,dryRun:o,isGlobal:i}=e;if(o)return console.log(`[dry-run] cline -> ${ye.join(t,".clinerules")}`);if(i)return;let r=ye.join(n,"templates","shared","rules"),s=[`# Frontend Craft - Cline rules
31
+ `];if(jn.existsSync(r))for(let l of jn.readdirSync(r))l.endsWith(".md")&&s.push(`
32
+ ## ${l}
33
+
34
+ `,C(ye.join(r,l)));y(ye.join(t,".clinerules"),s.join(""))}import J from"node:path";import Me from"node:fs";async function In(e){let{contentRoot:n,baseDir:t,cwd:o,dryRun:i}=e;if(i)return console.log(`[dry-run] openclaw -> ${t}`);f(t),p(J.join(n,"skills"),J.join(t,"skills")),p(J.join(n,"commands"),J.join(t,"commands"));let r=J.join(n,"templates","openclaw");if(Me.existsSync(r))for(let s of Me.readdirSync(r)){if(!s.endsWith(".md"))continue;let l=J.join(o,s);Me.existsSync(l)||D(J.join(r,s),l)}}import N from"node:path";import bn from"node:fs";var it=["fec-security-check.js","fec-format-changed-file.js","fec-run-tests.js","fec-notify.js"];async function vn(e){let{pluginRoot:n,contentRoot:t,baseDir:o,dryRun:i,isGlobal:r}=e;if(i){console.log(`[dry-run] qoder -> ${o}`);return}f(o),p(N.join(t,"skills"),N.join(o,"skills")),p(N.join(t,"commands"),N.join(o,"commands")),p(N.join(t,"agents"),N.join(o,"agents")),r||p(N.join(t,"templates","shared","rules"),N.join(o,"rules")),rt(n,N.join(o,"hooks")),y(N.join(o,"settings.json"),JSON.stringify(lt(o),null,2)+`
35
+ `)}function rt(e,n){f(n);for(let t of it){let o=N.join(e,"dist","hooks",t);if(!bn.existsSync(o))throw new Error(`Missing built hook script: ${o}. Run "npm run build" before installing.`);D(o,N.join(n,t))}}function lt(e){let n=N.join(e,"settings.json"),t=at(n);return{...t,hooks:{...ne(t.hooks),PreToolUse:[...Se(ne(t.hooks).PreToolUse),Ce("Bash|Shell",".qoder/hooks/fec-security-check.js","Checking command safety...")],PostToolUse:[...Se(ne(t.hooks).PostToolUse),Ce("Write|Edit|MultiEdit",".qoder/hooks/fec-format-changed-file.js","Running formatter...")],Stop:[...Se(ne(t.hooks).Stop),Ce(".*",".qoder/hooks/fec-run-tests.js","Running final validation...")],Notification:[...Se(ne(t.hooks).Notification),Ce(".*",".qoder/hooks/fec-notify.js")]}}}function at(e){if(!bn.existsSync(e))return{};try{let n=JSON.parse(C(e));return ne(n)}catch{return{}}}function Ce(e,n,t){return{matcher:e,hooks:[{type:"command",command:`node "${n}"`,...t?{statusMessage:t}:{}}]}}function ne(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:{}}function Se(e){return Array.isArray(e)?e:[]}var F=["claude","codex","cursor","windsurf","opencode","kilo","gemini","copilot","antigravity","augment","trae","codebuddy","cline","openclaw","qoder"],je={claude:on,codex:rn,cursor:an,windsurf:cn,opencode:un,kilo:fn,gemini:pn,copilot:mn,antigravity:gn,augment:hn,trae:Sn,codebuddy:yn,cline:xn,openclaw:In,qoder:vn};import ct from"node:fs";import ut from"node:os";import ft from"node:path";import Ie from"node:readline";import kn from"node:os";import x from"node:path";function I(e){return e&&(e.startsWith("~/")||e==="~"?x.join(kn.homedir(),e.slice(1)):e)}function xe(e){let n=kn.homedir(),t=process.env;switch(e){case"claude":return t.CLAUDE_CONFIG_DIR?I(t.CLAUDE_CONFIG_DIR):x.join(n,".claude");case"cursor":return t.CURSOR_CONFIG_DIR?I(t.CURSOR_CONFIG_DIR):x.join(n,".cursor");case"gemini":return t.GEMINI_CONFIG_DIR?I(t.GEMINI_CONFIG_DIR):x.join(n,".gemini");case"codex":return t.CODEX_HOME?I(t.CODEX_HOME):x.join(n,".codex");case"copilot":return t.COPILOT_CONFIG_DIR?I(t.COPILOT_CONFIG_DIR):x.join(n,".copilot");case"antigravity":return t.ANTIGRAVITY_CONFIG_DIR?I(t.ANTIGRAVITY_CONFIG_DIR):x.join(n,".gemini","antigravity");case"windsurf":return t.WINDSURF_CONFIG_DIR?I(t.WINDSURF_CONFIG_DIR):x.join(n,".codeium","windsurf");case"augment":return t.AUGMENT_CONFIG_DIR?I(t.AUGMENT_CONFIG_DIR):x.join(n,".augment");case"trae":return t.TRAE_CONFIG_DIR?I(t.TRAE_CONFIG_DIR):x.join(n,".trae");case"codebuddy":return t.CODEBUDDY_CONFIG_DIR?I(t.CODEBUDDY_CONFIG_DIR):x.join(n,".codebuddy");case"cline":return t.CLINE_CONFIG_DIR?I(t.CLINE_CONFIG_DIR):x.join(n,".cline");case"opencode":return t.OPENCODE_CONFIG_DIR?I(t.OPENCODE_CONFIG_DIR):t.XDG_CONFIG_HOME?x.join(I(t.XDG_CONFIG_HOME),"opencode"):x.join(n,".config","opencode");case"kilo":return t.KILO_CONFIG_DIR?I(t.KILO_CONFIG_DIR):t.XDG_CONFIG_HOME?x.join(I(t.XDG_CONFIG_HOME),"kilo"):x.join(n,".config","kilo");case"openclaw":return t.OPENCLAW_CONFIG_DIR?I(t.OPENCLAW_CONFIG_DIR):x.join(n,".openclaw");case"qoder":return t.QODER_CONFIG_DIR?I(t.QODER_CONFIG_DIR):x.join(n,".qoder");default:return t.CLAUDE_CONFIG_DIR?I(t.CLAUDE_CONFIG_DIR):x.join(n,".claude")}}var _e={claude:".claude",codex:".codex",cursor:".cursor",windsurf:".windsurf",opencode:".opencode",kilo:".kilo",gemini:".gemini",copilot:".github",antigravity:".agent",augment:".augment",trae:".trae",codebuddy:".codebuddy",cline:"",openclaw:".openclaw",qoder:".qoder"};function Y({runtime:e,isGlobal:n,cwd:t}){if(n)return xe(e);if(e==="cline")return t;let o=_e[e]??".claude";return x.join(t,o)}var dt={claude:"Claude Code",codex:"Codex",cursor:"Cursor",windsurf:"Windsurf",opencode:"OpenCode",kilo:"Kilo",gemini:"Gemini",copilot:"Copilot",antigravity:"Antigravity",augment:"Augment",trae:"Trae",codebuddy:"CodeBuddy",cline:"Cline",openclaw:"OpenClaw",qoder:"Qoder"};function Rn(e){let n=ut.homedir();return e===n?"~":e.startsWith(`${n}${ft.sep}`)?`~${e.slice(n.length)}`:e}function pt(e){let n=_e[e];return n?`./${n}`:"./"}var be=F.map((e,n)=>({choice:String(n+1),runtime:e,label:dt[e]??e})),mt=String(be.length+1);function wn(e){return e.filter((n,t)=>e.indexOf(n)===t)}function gt(e,n,t){return Math.max(n,Math.min(t,e))}function ht(e){return!e||e.ctrl||e.meta?"":typeof e.sequence=="string"&&e.sequence.length===1&&e.sequence>=" "?e.sequence:typeof e.name=="string"&&e.name.length===1?e.name:""}function yt(){return be.map(e=>{let n=Rn(xe(e.runtime));return{value:e.runtime,label:e.label,description:n,selectedSuffix:"selected"}})}function Ct(e){let n=wn(e.map(o=>Rn(xe(o)))).join(", "),t=wn(e.map(o=>pt(o))).join(", ");return[{value:"global",label:"Global",description:`${n} - available in all projects`,selectedSuffix:"selected"},{value:"local",label:"Local",description:`${t} - this project only`,selectedSuffix:"selected"}]}function St(){return[{value:"en",label:"English",description:"canonical default content",selectedSuffix:"selected"},{value:"zh-CN",label:"简体中文",description:"localized AI-facing content",selectedSuffix:"已选择"}]}function Pe({message:e,options:n,selected:t=[],multiple:o=!0,pageSize:i=15,validate:r=l=>l.length>0,transform:s=(l=>l)}){return{message:e,options:n,selected:t.filter((a,c)=>t.indexOf(a)===c),multiple:o,pageSize:i,search:"",cursor:0,error:"",visibleOptions(){let a=this.search.trim().toLowerCase();return a?this.options.filter(c=>c.label.toLowerCase().includes(a)||c.value.toLowerCase().includes(a)):this.options},move(a){let c=this.visibleOptions();this.cursor=gt(this.cursor+a,0,Math.max(0,c.length-1)),this.error=""},toggle(){let a=this.visibleOptions()[this.cursor];a&&(this.multiple?this.selected.includes(a.value)?this.selected=this.selected.filter(c=>c!==a.value):this.selected=[...this.selected,a.value]:this.selected=[a.value],this.error="")},backspace(){this.search.length>0?(this.search=this.search.slice(0,-1),this.cursor=0):this.selected.length>0&&(this.selected=this.selected.slice(0,-1)),this.error=""},type(a){this.search+=a,this.cursor=0,this.error=""},confirm(){let a=r(this.selected);if(a!==!0){this.error=typeof a=="string"?a:"Select at least one option";return}return s(this.selected)}}}function Dn(e={}){return Pe({message:`Which runtime(s) would you like to install for? (${be.length} available)`,options:yt(),selected:["claude"],multiple:!0,pageSize:e.pageSize??15,transform:n=>n})}function $n(e,n={}){return Pe({message:"Where would you like to install?",options:Ct(e),selected:["global"],multiple:!1,pageSize:n.pageSize??15,transform:t=>t[0]!=="local"})}function Nn(e={}){return Pe({message:"Which language should frontend-craft install?",options:St(),selected:["en"],multiple:!1,pageSize:e.pageSize??15,transform:n=>n[0]==="zh-CN"?"zh-CN":"en"})}function fe(e){let n=e.visibleOptions(),t=new Set(e.selected),o=new Map(e.options.map(s=>[s.value,s])),i=e.selected.length?e.selected.map(s=>o.get(s)?.label??s).join(", "):"(none selected)",r=[`? ${e.message}`,` Selected: ${i}`,` Search: [${e.search||"type to filter"}]`," Up/Down navigate - Space toggle - Backspace remove - Enter confirm"];if(n.length===0)r.push(" No matches");else{let s=Math.max(0,Math.min(e.cursor-Math.floor(e.pageSize/2),n.length-e.pageSize)),l=Math.min(s+e.pageSize,n.length),a=n.slice(s,l);for(let c=0;c<a.length;c++){let u=a[c],b=s+c===e.cursor,j=t.has(u.value),R=b?">":" ",M=j?"[x]":"[ ]",pe=u.description?` (${u.description})`:"",A=j?` (${u.selectedSuffix??"selected"})`:pe;r.push(` ${R} ${M} ${u.label}${A}`)}if(n.length>e.pageSize){let c=Math.floor(e.cursor/e.pageSize)+1,u=Math.ceil(n.length/e.pageSize);r.push(` (${c}/${u})`)}}return e.error&&r.push(` ${e.error}`),r.join(`
36
+ `)}function jt(){return fe(Dn())}function xt(e){let t=((e==null?"":String(e)).trim()||"1").split(/[\s,]+/).filter(Boolean);if(t.includes(mt))return F.slice();let o=[],i=new Set,r=new Map(be.map(s=>[s.choice,s.runtime]));for(let s of t){let l=r.get(s);!l||i.has(l)||(i.add(l),o.push(l))}return o.length?o:["claude"]}function It(e){return fe($n(e))}function bt(e){return((e==null?"":String(e)).trim()||"1")!=="2"}function vt(){return fe(Nn())}function kt(e){let n=(e==null?"":String(e)).trim()||"1";return n==="2"||n==="zh-CN"?"zh-CN":"en"}var Te;function On(e){return process.stdout.write(e),Te||(Te=ct.readFileSync(0,"utf8").split(/\r?\n/)),Te.shift()??""}function Ee(e){return process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1"&&!process.stdin.isTTY?Promise.resolve(On(e)):new Promise(n=>{let t=Ie.createInterface({input:process.stdin,output:process.stdout});t.question(e,o=>{t.close(),n(o)}),t.on("close",()=>n(""))})}async function Le(e){return process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1"&&!process.stdin.isTTY?On(`${fe(e)}
37
+ `):new Promise(n=>{let t=process.stdin,o=process.stdout,i=t.isRaw,r=0;function s(){r>0&&(Ie.moveCursor(o,0,-r),Ie.clearScreenDown(o));let c=fe(e);o.write(c),o.write(`
38
38
  `),r=c.split(`
39
- `).length}function a(){t.off("keypress",l),t.isTTY&&t.setRawMode(!!i),t.pause()}function l(c,u){if(u?.ctrl&&u.name==="c"){a(),o.write(`
40
- `),process.exitCode=130,n(void 0);return}if(u?.name==="return"||u?.name==="enter"){let g=e.confirm();s(),g!==void 0&&(a(),n(g));return}if(u?.name==="up")e.move(-1);else if(u?.name==="down")e.move(1);else if(u?.name==="space")e.toggle();else if(u?.name==="backspace")e.backspace();else{let g=rt(u);g&&e.type(g)}s()}he.emitKeypressEvents(t),t.isTTY&&t.setRawMode(!0),t.resume(),t.on("keypress",l),s()})}async function kn(){if(process.stdin.isTTY){let e=await vn(Sn());return Array.isArray(e)?e:["claude"]}return console.log(`${ct()}
41
- `),ut(await In("Choice [1]: "))}async function wn(e){if(process.stdin.isTTY){let n=await vn(bn(e));return typeof n=="boolean"?n:!0}return console.log(`${ft(e)}
42
- `),dt(await In("Choice [1]: "))}var je={claude:{tier:"full",skills:!0,agents:!0,commands:!0,hooks:!0,rules:!0,templates:!0,mcp:!0,reports:!0,init:"native"},codex:{tier:"full",skills:!0,agents:!0,commands:!1,hooks:!1,rules:!0,templates:!0,mcp:!1,reports:!0,init:"native"},openclaw:{tier:"full",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!1,templates:!0,mcp:!1,reports:!0,init:"native"},qoder:{tier:"full",skills:!0,agents:!0,commands:!0,hooks:!0,rules:!0,templates:!0,mcp:!1,reports:!0,init:"native"},opencode:{tier:"medium",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!1,templates:!0,mcp:!1,reports:!0,init:"rules"},kilo:{tier:"medium",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"rules"},cursor:{tier:"medium",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"rules"},windsurf:{tier:"medium",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"rules"},gemini:{tier:"medium",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!0,mcp:!1,reports:!0,init:"rules"},copilot:{tier:"medium",skills:!1,agents:!1,commands:!0,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"rules"},antigravity:{tier:"skills-rules-only",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"none"},augment:{tier:"skills-rules-only",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"none"},trae:{tier:"skills-rules-only",skills:!1,agents:!1,commands:!1,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"none"},codebuddy:{tier:"skills-rules-only",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"none"},cline:{tier:"skills-rules-only",skills:!1,agents:!1,commands:!1,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"none"}};function Rn(e){let n=["Runtime","Tier","Skills","Agents","Commands","Hooks","Rules","Templates","MCP","Reports","Init"],t=e.map(r=>{let s=je[r];if(!s)throw new Error(`Missing capability declaration for runtime: ${r}`);return[r,s.tier,U(s.skills),U(s.agents),U(s.commands),U(s.hooks),U(s.rules),U(s.templates),U(s.mcp),U(s.reports),s.init]}),o=n.map((r,s)=>Math.max(r.length,...t.map(a=>a[s].length))),i=r=>r.map((s,a)=>s.padEnd(o[a])).join(" ").trimEnd();return[i(n),...t.map(i)].join(`
43
- `)}function U(e){return e?"yes":"no"}import Dn from"node:fs";import ee from"node:path";import{fileURLToPath as $n}from"node:url";function On(e=import.meta.url){let n=ee.dirname($n(e));for(;;){if(Dn.existsSync(ee.join(n,"package.json"))&&Dn.existsSync(ee.join(n,"skills")))return n;let t=ee.dirname(n);if(t===n)return ee.resolve(ee.dirname($n(e)),"../..");n=t}}import ne from"node:fs";import Nn from"node:os";import T from"node:path";function Se({cwd:e,runtimes:n=F,scopes:t=["local","global"]}){let o=[],i=new Set;for(let r of n)for(let s of t){let a=Z({runtime:r,isGlobal:s==="global",cwd:e}),l=ae(a),c=T.resolve(l);if(i.has(c))continue;i.add(c);let u=Ie(l);u&&(u.runtime!==r||u.scope!==s||o.push({runtime:r,scope:s,baseDir:a,manifestPath:l,manifest:u}))}return o}function Ne({install:e,cwd:n,dryRun:t,force:o}){let i={removed:[],skipped:[],missing:[]},r=new Set;for(let s of e.manifest.files){let a=pt({filePath:s.path,root:s.root??"baseDir",baseDir:e.baseDir,cwd:n});if(!a)continue;if(!ne.existsSync(a)){i.missing.push(s.path);continue}let l=ve(a)!==s.hash;if(l&&!o){i.skipped.push(s.path);continue}i.removed.push({path:s.path,modified:l}),r.add(T.dirname(a)),t||ne.rmSync(a,{force:!0})}return!t&&i.skipped.length===0&&(ne.rmSync(e.manifestPath,{force:!0}),mt([...r],[e.baseDir,n,Nn.homedir()])),i}function pt({filePath:e,root:n,baseDir:t,cwd:o}){let i=n==="baseDir"?t:n==="cwd"?o:Nn.homedir(),r=T.resolve(i),s=T.resolve(r,e),a=T.relative(r,s);if(!(a.startsWith("..")||T.isAbsolute(a)))return s}function mt(e,n){let t=n.map(o=>T.resolve(o));for(let o of e.sort((i,r)=>r.length-i.length)){let i=T.resolve(o);for(;gt(i,t)&&!t.includes(i)&&!(!ne.existsSync(i)||ne.readdirSync(i).length>0);)ne.rmdirSync(i),i=T.dirname(i)}}function gt(e,n){return n.some(t=>{let o=T.relative(t,e);return o!==""&&!o.startsWith("..")&&!T.isAbsolute(o)})}import N from"node:fs";import Fe from"node:os";import w from"node:path";function Me({claudeConfigDir:e=Te(),currentVersion:n}){let t=w.join(e,"plugins","cache","frontend-craft","frontend-craft"),o=yt(e),i=ht({cacheDir:t,currentInstallPaths:o.paths,currentVersion:n}),r=o.warning,s=!r&&o.paths.length>0;return{claudeConfigDir:e,cacheDir:t,currentInstallPaths:o.paths,entries:i.map(a=>({...a,shouldDelete:s&&a.shouldDelete,reasons:s?a.reasons:["metadata unavailable"]})),canDelete:s,warning:r}}function Tn({claudeConfigDir:e=Te(),currentVersion:n,dryRun:t=!1}){let o=Me({claudeConfigDir:e,currentVersion:n}),i=[];if(o.canDelete)for(let r of o.entries)r.shouldDelete&&(t||N.rmSync(r.path,{recursive:!0,force:!0}),t||i.push(r));return{...o,deleted:i}}function _e({claudeConfigDir:e=Te(),cwd:n=process.cwd()}={}){let t=Ct(e),o=[Fn(w.join(n,".claude","frontend-craft.manifest.json"),"local"),Fn(w.join(e,"frontend-craft.manifest.json"),"global")].filter(i=>i!==void 0);return{native:t,cli:o,hasMultipleActiveSources:t.length+o.length>1}}function le(e){let n=["install sources:"];if(e.native.length===0&&e.cli.length===0)return n.push(" none detected"),n.join(`
39
+ `).length}function l(){t.off("keypress",a),t.isTTY&&t.setRawMode(!!i),t.pause()}function a(c,u){if(u?.ctrl&&u.name==="c"){l(),o.write(`
40
+ `),process.exitCode=130,n(void 0);return}if(u?.name==="return"||u?.name==="enter"){let g=e.confirm();s(),g!==void 0&&(l(),n(g));return}if(u?.name==="up")e.move(-1);else if(u?.name==="down")e.move(1);else if(u?.name==="space")e.toggle();else if(u?.name==="backspace")e.backspace();else{let g=ht(u);g&&e.type(g)}s()}Ie.emitKeypressEvents(t),t.isTTY&&t.setRawMode(!0),t.resume(),t.on("keypress",a),s()})}async function Fn(){if(process.stdin.isTTY){let e=await Le(Dn());return Array.isArray(e)?e:["claude"]}return console.log(`${jt()}
41
+ `),xt(await Ee("Choice [1]: "))}async function Mn(e){if(process.stdin.isTTY){let n=await Le($n(e));return typeof n=="boolean"?n:!0}return console.log(`${It(e)}
42
+ `),bt(await Ee("Choice [1]: "))}async function _n(){return process.stdin.isTTY?await Le(Nn())==="zh-CN"?"zh-CN":"en":(console.log(`${vt()}
43
+ `),kt(await Ee("Choice [1]: ")))}import wt from"node:fs";import Rt from"node:path";var Q="en",ve=["en","zh-CN"];function Ae(e){return ve.includes(e)}function Dt(e){if(e!=null)return Ae(e)?e:void 0}function Tn(e){return Dt(e)??Q}function Pn(e,n){if(n===Q)return e;let t=Rt.join(e,"localized",n);if(!wt.existsSync(t))throw new Error(`Missing localized content pack for language "${n}": ${t}`);return t}var ke={claude:{tier:"full",skills:!0,agents:!0,commands:!0,hooks:!0,rules:!0,templates:!0,mcp:!0,reports:!0,init:"native"},codex:{tier:"full",skills:!0,agents:!0,commands:!1,hooks:!1,rules:!0,templates:!0,mcp:!1,reports:!0,init:"native"},openclaw:{tier:"full",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!1,templates:!0,mcp:!1,reports:!0,init:"native"},qoder:{tier:"full",skills:!0,agents:!0,commands:!0,hooks:!0,rules:!0,templates:!0,mcp:!1,reports:!0,init:"native"},opencode:{tier:"medium",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!1,templates:!0,mcp:!1,reports:!0,init:"rules"},kilo:{tier:"medium",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"rules"},cursor:{tier:"medium",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"rules"},windsurf:{tier:"medium",skills:!0,agents:!1,commands:!0,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"rules"},gemini:{tier:"medium",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!0,mcp:!1,reports:!0,init:"rules"},copilot:{tier:"medium",skills:!1,agents:!1,commands:!0,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"rules"},antigravity:{tier:"skills-rules-only",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"none"},augment:{tier:"skills-rules-only",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"none"},trae:{tier:"skills-rules-only",skills:!1,agents:!1,commands:!1,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"none"},codebuddy:{tier:"skills-rules-only",skills:!0,agents:!1,commands:!1,hooks:!1,rules:!1,templates:!1,mcp:!1,reports:!0,init:"none"},cline:{tier:"skills-rules-only",skills:!1,agents:!1,commands:!1,hooks:!1,rules:!0,templates:!1,mcp:!1,reports:!0,init:"none"}};function En(e){let n=["Runtime","Tier","Skills","Agents","Commands","Hooks","Rules","Templates","MCP","Reports","Init"],t=e.map(r=>{let s=ke[r];if(!s)throw new Error(`Missing capability declaration for runtime: ${r}`);return[r,s.tier,z(s.skills),z(s.agents),z(s.commands),z(s.hooks),z(s.rules),z(s.templates),z(s.mcp),z(s.reports),s.init]}),o=n.map((r,s)=>Math.max(r.length,...t.map(l=>l[s].length))),i=r=>r.map((s,l)=>s.padEnd(o[l])).join(" ").trimEnd();return[i(n),...t.map(i)].join(`
44
+ `)}function z(e){return e?"yes":"no"}import Ln from"node:fs";import te from"node:path";import{fileURLToPath as An}from"node:url";function Gn(e=import.meta.url){let n=te.dirname(An(e));for(;;){if(Ln.existsSync(te.join(n,"package.json"))&&Ln.existsSync(te.join(n,"skills")))return n;let t=te.dirname(n);if(t===n)return te.resolve(te.dirname(An(e)),"../..");n=t}}import oe from"node:fs";import Un from"node:os";import P from"node:path";function we({cwd:e,runtimes:n=F,scopes:t=["local","global"]}){let o=[],i=new Set;for(let r of n)for(let s of t){let l=Y({runtime:r,isGlobal:s==="global",cwd:e}),a=re(l),c=P.resolve(a);if(i.has(c))continue;i.add(c);let u=le(a);u&&(u.runtime!==r||u.scope!==s||o.push({runtime:r,scope:s,baseDir:l,manifestPath:a,manifest:u}))}return o}function Ge({install:e,cwd:n,dryRun:t,force:o}){let i={removed:[],skipped:[],missing:[]},r=new Set;for(let s of e.manifest.files){let l=$t({filePath:s.path,root:s.root??"baseDir",baseDir:e.baseDir,cwd:n});if(!l)continue;if(!oe.existsSync(l)){i.missing.push(s.path);continue}let a=$e(l)!==s.hash;if(a&&!o){i.skipped.push(s.path);continue}i.removed.push({path:s.path,modified:a}),r.add(P.dirname(l)),t||oe.rmSync(l,{force:!0})}return!t&&i.skipped.length===0&&(oe.rmSync(e.manifestPath,{force:!0}),Nt([...r],[e.baseDir,n,Un.homedir()])),i}function $t({filePath:e,root:n,baseDir:t,cwd:o}){let i=n==="baseDir"?t:n==="cwd"?o:Un.homedir(),r=P.resolve(i),s=P.resolve(r,e),l=P.relative(r,s);if(!(l.startsWith("..")||P.isAbsolute(l)))return s}function Nt(e,n){let t=n.map(o=>P.resolve(o));for(let o of e.sort((i,r)=>r.length-i.length)){let i=P.resolve(o);for(;Ot(i,t)&&!t.includes(i)&&!(!oe.existsSync(i)||oe.readdirSync(i).length>0);)oe.rmdirSync(i),i=P.dirname(i)}}function Ot(e,n){return n.some(t=>{let o=P.relative(t,e);return o!==""&&!o.startsWith("..")&&!P.isAbsolute(o)})}import O from"node:fs";import Ue from"node:os";import w from"node:path";function We({claudeConfigDir:e=Ve(),currentVersion:n}){let t=w.join(e,"plugins","cache","frontend-craft","frontend-craft"),o=Mt(e),i=Ft({cacheDir:t,currentInstallPaths:o.paths,currentVersion:n}),r=o.warning,s=!r&&o.paths.length>0;return{claudeConfigDir:e,cacheDir:t,currentInstallPaths:o.paths,entries:i.map(l=>({...l,shouldDelete:s&&l.shouldDelete,reasons:s?l.reasons:["metadata unavailable"]})),canDelete:s,warning:r}}function qn({claudeConfigDir:e=Ve(),currentVersion:n,dryRun:t=!1}){let o=We({claudeConfigDir:e,currentVersion:n}),i=[];if(o.canDelete)for(let r of o.entries)r.shouldDelete&&(t||O.rmSync(r.path,{recursive:!0,force:!0}),t||i.push(r));return{...o,deleted:i}}function ze({claudeConfigDir:e=Ve(),cwd:n=process.cwd()}={}){let t=_t(e),o=[Wn(w.join(n,".claude","frontend-craft.manifest.json"),"local"),Wn(w.join(e,"frontend-craft.manifest.json"),"global")].filter(i=>i!==void 0);return{native:t,cli:o,hasMultipleActiveSources:t.length+o.length>1}}function de(e){let n=["install sources:"];if(e.native.length===0&&e.cli.length===0)return n.push(" none detected"),n.join(`
44
45
  `);for(let t of e.native){let o=[t.version,t.scope].filter(Boolean).join(", ");n.push(` native plugin: ${o||"installed"}${t.installPath?` (${t.installPath})`:""}`)}for(let t of e.cli)n.push(` ${t.scope} CLI: ${t.packageVersion??"unknown"} (${t.manifestPath})`);return e.hasMultipleActiveSources&&n.push(" warning: multiple active sources detected; keep one Claude loader as the source of truth"),n.join(`
45
- `)}function be(e,n="report"){let t=["native cache:"];if(t.push(` current installs: ${e.currentInstallPaths.length?e.currentInstallPaths.join(", "):"unknown"}`),e.warning&&t.push(` warning: ${e.warning}`),e.entries.length===0)return t.push(" entries: none"),t.join(`
46
+ `)}function Re(e,n="report"){let t=["native cache:"];if(t.push(` current installs: ${e.currentInstallPaths.length?e.currentInstallPaths.join(", "):"unknown"}`),e.warning&&t.push(` warning: ${e.warning}`),e.entries.length===0)return t.push(" entries: none"),t.join(`
46
47
  `);for(let o of e.entries){let i=o.isCurrent?"current install":o.reasons.length?o.reasons.join(", "):"healthy",r=n==="dry-run"&&o.shouldDelete?"would delete":n==="fix"&&o.shouldDelete?"delete":"keep";t.push(` ${r} ${o.version}: ${i}`)}return t.join(`
47
- `)}function Pn(e,n){if(n)return be(e,"dry-run");let t=[be(e,"fix")];for(let o of e.deleted)t.push(` deleted ${o.version}: ${o.path}`);return e.deleted.length===0&&t.push(" deleted: none"),t.join(`
48
- `)}function Te(){return xt(process.env.CLAUDE_CONFIG_DIR??w.join(Fe.homedir(),".claude"))}function ht({cacheDir:e,currentInstallPaths:n,currentVersion:t}){if(!N.existsSync(e))return[];let o=new Set(n.map(_n));return N.readdirSync(e,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>{let r=w.join(e,i.name),s=St(r),a=N.existsSync(w.join(r,"dist")),l=N.existsSync(w.join(r,".orphaned_at")),c=o.has(_n(r)),u=[];return l&&u.push("orphaned"),a||u.push("missing dist"),s&&bt(s,t)<0&&u.push(`package ${s} < ${t}`),{version:i.name,path:r,isCurrent:c,hasDist:a,orphaned:l,packageVersion:s,reasons:u,shouldDelete:!c&&u.length>0}}).sort((i,r)=>i.version.localeCompare(r.version,void 0,{numeric:!0}))}function yt(e){let n=w.join(e,"plugins","installed_plugins.json");if(!N.existsSync(n))return{paths:[],warning:`missing ${n}; refusing to delete cache entries`};try{let t=JSON.parse(N.readFileSync(n,"utf8")),o=(t.plugins?.["frontend-craft@bovinphang/frontend-craft"]??t.plugins?.["frontend-craft@frontend-craft"]??[]).map(i=>i.installPath).filter(i=>typeof i=="string"&&i.length>0).map(i=>w.resolve(i));return o.length===0?{paths:o,warning:`missing frontend-craft plugin entry in ${n}; refusing to delete cache entries`}:{paths:o}}catch{return{paths:[],warning:`invalid ${n}; refusing to delete cache entries`}}}function Ct(e){let n=w.join(e,"plugins","installed_plugins.json");if(!N.existsSync(n))return[];try{let t=JSON.parse(N.readFileSync(n,"utf8"));return Object.entries(t.plugins??{}).flatMap(([o,i])=>jt(o)?i.map(r=>({key:o,installPath:typeof r.installPath=="string"?w.resolve(r.installPath):void 0,scope:typeof r.scope=="string"?r.scope:void 0,version:typeof r.version=="string"?r.version:void 0})):[])}catch{return[]}}function jt(e){return e==="frontend-craft@bovinphang/frontend-craft"||e==="frontend-craft@frontend-craft"||e.startsWith("frontend-craft@")}function Fn(e,n){if(N.existsSync(e))try{let t=JSON.parse(N.readFileSync(e,"utf8"));return t.runtime!=="claude"?void 0:{scope:n,manifestPath:e,packageVersion:typeof t.packageVersion=="string"?t.packageVersion:void 0}}catch{return{scope:n,manifestPath:e}}}function St(e){let n=w.join(e,"package.json");if(N.existsSync(n))try{let t=JSON.parse(N.readFileSync(n,"utf8"));return typeof t.version=="string"?t.version:void 0}catch{return}}function bt(e,n){let t=Mn(e),o=Mn(n);for(let i=0;i<3;i+=1)if(t[i]!==o[i])return t[i]-o[i];return 0}function Mn(e){let n=e.match(/^(\d+)\.(\d+)\.(\d+)/);return n?[Number(n[1]),Number(n[2]),Number(n[3])]:[0,0,0]}function xt(e){return e==="~"?Fe.homedir():e.startsWith("~/")||e.startsWith("~\\")?w.join(Fe.homedir(),e.slice(2)):e}function _n(e){let n=w.resolve(e);return process.platform==="win32"?n.toLowerCase():n}function Ae(e){try{let n=d.join(e,"package.json");return JSON.parse(m.readFileSync(n,"utf8")).version??"0.0.0"}catch{return"0.0.0"}}function vt(e){let n=null,t=!1,o=!1,i=!1,r=!1,s=!1,a=[];for(let l of e)l==="--global"||l==="-g"?(t=!0,n="global"):l==="--local"||l==="-l"?(o=!0,n="local"):l==="--dry-run"?i=!0:l==="--force"?r=!0:l==="--all"?s=!0:l.startsWith("-")||a.push(l);return{runtime:a[0],installLocation:n,dryRun:i,force:r,all:s,hasGlobal:t,hasLocal:o}}function Pe(){console.log(`frontend-craft - universal installer
48
+ `)}function Bn(e,n){if(n)return Re(e,"dry-run");let t=[Re(e,"fix")];for(let o of e.deleted)t.push(` deleted ${o.version}: ${o.path}`);return e.deleted.length===0&&t.push(" deleted: none"),t.join(`
49
+ `)}function Ve(){return Lt(process.env.CLAUDE_CONFIG_DIR??w.join(Ue.homedir(),".claude"))}function Ft({cacheDir:e,currentInstallPaths:n,currentVersion:t}){if(!O.existsSync(e))return[];let o=new Set(n.map(Vn));return O.readdirSync(e,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>{let r=w.join(e,i.name),s=Pt(r),l=O.existsSync(w.join(r,"dist")),a=O.existsSync(w.join(r,".orphaned_at")),c=o.has(Vn(r)),u=[];return a&&u.push("orphaned"),l||u.push("missing dist"),s&&Et(s,t)<0&&u.push(`package ${s} < ${t}`),{version:i.name,path:r,isCurrent:c,hasDist:l,orphaned:a,packageVersion:s,reasons:u,shouldDelete:!c&&u.length>0}}).sort((i,r)=>i.version.localeCompare(r.version,void 0,{numeric:!0}))}function Mt(e){let n=w.join(e,"plugins","installed_plugins.json");if(!O.existsSync(n))return{paths:[],warning:`missing ${n}; refusing to delete cache entries`};try{let t=JSON.parse(O.readFileSync(n,"utf8")),o=(t.plugins?.["frontend-craft@bovinphang/frontend-craft"]??t.plugins?.["frontend-craft@frontend-craft"]??[]).map(i=>i.installPath).filter(i=>typeof i=="string"&&i.length>0).map(i=>w.resolve(i));return o.length===0?{paths:o,warning:`missing frontend-craft plugin entry in ${n}; refusing to delete cache entries`}:{paths:o}}catch{return{paths:[],warning:`invalid ${n}; refusing to delete cache entries`}}}function _t(e){let n=w.join(e,"plugins","installed_plugins.json");if(!O.existsSync(n))return[];try{let t=JSON.parse(O.readFileSync(n,"utf8"));return Object.entries(t.plugins??{}).flatMap(([o,i])=>Tt(o)?i.map(r=>({key:o,installPath:typeof r.installPath=="string"?w.resolve(r.installPath):void 0,scope:typeof r.scope=="string"?r.scope:void 0,version:typeof r.version=="string"?r.version:void 0})):[])}catch{return[]}}function Tt(e){return e==="frontend-craft@bovinphang/frontend-craft"||e==="frontend-craft@frontend-craft"||e.startsWith("frontend-craft@")}function Wn(e,n){if(O.existsSync(e))try{let t=JSON.parse(O.readFileSync(e,"utf8"));return t.runtime!=="claude"?void 0:{scope:n,manifestPath:e,packageVersion:typeof t.packageVersion=="string"?t.packageVersion:void 0}}catch{return{scope:n,manifestPath:e}}}function Pt(e){let n=w.join(e,"package.json");if(O.existsSync(n))try{let t=JSON.parse(O.readFileSync(n,"utf8"));return typeof t.version=="string"?t.version:void 0}catch{return}}function Et(e,n){let t=zn(e),o=zn(n);for(let i=0;i<3;i+=1)if(t[i]!==o[i])return t[i]-o[i];return 0}function zn(e){let n=e.match(/^(\d+)\.(\d+)\.(\d+)/);return n?[Number(n[1]),Number(n[2]),Number(n[3])]:[0,0,0]}function Lt(e){return e==="~"?Ue.homedir():e.startsWith("~/")||e.startsWith("~\\")?w.join(Ue.homedir(),e.slice(2)):e}function Vn(e){let n=w.resolve(e);return process.platform==="win32"?n.toLowerCase():n}function He(e){try{let n=d.join(e,"package.json");return JSON.parse(m.readFileSync(n,"utf8")).version??"0.0.0"}catch{return"0.0.0"}}function Gt(e){let n=null,t=!1,o=!1,i=!1,r=!1,s=!1,l,a=[];for(let c=0;c<e.length;c++){let u=e[c];u==="--global"||u==="-g"?(t=!0,n="global"):u==="--local"||u==="-l"?(o=!0,n="local"):u==="--dry-run"?i=!0:u==="--force"?r=!0:u==="--all"?s=!0:u==="--lang"?l=e[++c]??"":u.startsWith("--lang=")?l=u.slice(7):u.startsWith("-")||a.push(u)}return{runtime:a[0],installLocation:n,dryRun:i,force:r,all:s,hasGlobal:t,hasLocal:o,language:l}}function qe(){console.log(`frontend-craft - universal installer
49
50
 
50
51
  Usage:
51
52
  frontend-craft install <runtime> [options]
@@ -68,6 +69,7 @@ Usage:
68
69
  Options:
69
70
  --global, -g Install to tool global config directory
70
71
  --local, -l Install to this project only
72
+ --lang <lang> Install content language: ${ve.join(", ")} (default: ${Q})
71
73
  --dry-run Show actions without writing files
72
74
  --force Uninstall: remove modified managed files (does not override Claude Marketplace)
73
75
  --all Install for every supported runtime
@@ -81,5 +83,5 @@ Notes:
81
83
 
82
84
  Runtimes:
83
85
  ${F.join(", ")}
84
- `)}function En(e){let n=e[0];return n==null||["--dry-run","--all","--global","-g","--local","-l"].includes(n)}async function Wn(e){let n=En(e)?"install":e[0],t=En(e)?e:e.slice(1),o=n==="setup",i=On(import.meta.url);if(n==="version"||n==="-v"||n==="--version"){console.log(Ae(i));return}if(n==="list"){F.forEach(h=>console.log(h));return}if(n==="matrix"){console.log(Rn(F));return}if(n==="doctor"){let h=t[0]??"claude",_=t.includes("--global")||t.includes("-g"),P=t.includes("--fix-cache"),V=t.includes("--dry-run"),q=process.cwd(),G=Z({runtime:h,isGlobal:_,cwd:q}),xe=je[h];if(!xe){console.error(`Unknown runtime: ${h}`),process.exitCode=1;return}console.log(Ot({runtime:h,baseDir:G,cwd:q,cap:xe,pluginRoot:i,fixCache:P,dryRun:V,isGlobal:_}));return}if(n==="sync-metadata"){let h=t.includes("--check"),_=Pt(i);if(_.length>0){for(let P of _)console.error(P);process.exitCode=1;return}console.log(h?"metadata is synchronized":"metadata is synchronized; no changes needed");return}if(n==="help"||n==="-h"||n==="--help"){Pe();return}let r=n==="update"||n==="upgrade"?"update":"install";if(n!=="install"&&n!=="setup"&&n!=="update"&&n!=="upgrade"&&n!=="uninstall"&&n!=="remove"){console.error(`Unknown command: ${n}`),Pe(),process.exitCode=1;return}if(t.some(h=>h==="help"||h==="--help"||h==="-h")){Pe();return}let s=vt(t),a=s.runtime,l=s.all,{installLocation:c,dryRun:u,force:g,hasGlobal:R,hasLocal:S}=s;o&&a==="all"&&(a=void 0,l=!0);let M=c??(o?"local":null);if(R&&S){console.error("--global and --local cannot be used together."),process.exitCode=1;return}let I=process.cwd();if(n==="uninstall"||n==="remove"){let h=Ln(S,R),P=Se({cwd:I,runtimes:a?[a]:l?F:void 0,scopes:h});if(a&&!me[a]){console.error(`Unknown runtime: ${a}`),process.exitCode=1;return}if(P.length===0){console.log(Un("uninstall",a,h));return}for(let V of P){console.log(`Uninstalling frontend-craft for "${V.runtime}" -> ${V.baseDir}${V.scope==="global"?" (global)":""}`);let q=Ne({install:V,cwd:I,dryRun:u,force:g});for(let G of q.removed)console.log(`${u?"[dry-run] would remove":"Removed"}${G.modified?" modified file":" file"}: ${G.path}`);for(let G of q.skipped)console.log(`Skipped modified file: ${G}`);for(let G of q.missing)console.log(`Missing file: ${G}`);u&&q.skipped.length===0&&console.log(`[dry-run] would remove manifest: ${V.manifestPath}`)}return}let oe=!!process.stdin.isTTY||process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1";if(r==="update"&&!a){let h=Ln(S,R),_=Se({cwd:I,runtimes:l?F:void 0,scopes:h});if(_.length===0){console.log(Un("update",void 0,h));return}for(let P of _)await An({rt:P.runtime,mode:r,isGlobal:P.scope==="global",baseDir:P.baseDir,pluginRoot:i,cwd:I,dryRun:u});return}let W=l?F:a?[a]:[];W.length||(oe?W=await kn():(console.log("Non-interactive terminal detected, defaulting to claude runtime."),W=["claude"]));let J;M==="global"?J=!0:M==="local"?J=!1:oe?J=await wn(W):(console.log("Non-interactive terminal detected, defaulting to global install."),J=!0);for(let h of W){if(!me[h]){console.error(`Unknown runtime: ${h}`),process.exitCode=1;continue}let _=Z({runtime:h,isGlobal:J,cwd:I});await An({rt:h,mode:r,isGlobal:J,baseDir:_,pluginRoot:i,cwd:I,dryRun:u,force:g,canPrompt:oe})}}async function An({rt:e,mode:n,isGlobal:t,baseDir:o,pluginRoot:i,cwd:r,dryRun:s,force:a,canPrompt:l}){let c=await kt({rt:e,mode:n,isGlobal:t,cwd:r,dryRun:s,force:!!a,canPrompt:!!l});if(!c)return;c.redirect&&(t=c.redirect.isGlobal,o=c.redirect.baseDir,n="update");let u={pluginRoot:i,cwd:r,runtime:e,isGlobal:t,baseDir:o,dryRun:s,mode:n,capabilities:je[e]};n==="install"?(console.log(`Installing frontend-craft for "${e}" -> ${o}${t?" (global)":""}`),!s&&m.existsSync(ae(o))&&console.log(`Existing frontend-craft manifest found; use "frontend-craft update ${e}" to refresh managed files.`)):console.log(`Updating frontend-craft for "${e}" -> ${o}${t?" (global)":""}`),s||Ge({baseDir:o,cwd:r,mode:n,packageVersion:Ae(i),runtime:e,isGlobal:t});try{await me[e](u),s||Le()}catch(g){throw s||Ue(),g}}async function kt({rt:e,mode:n,isGlobal:t,cwd:o,dryRun:i,force:r,canPrompt:s}){if(e!=="claude")return{};let a=_e({cwd:o});if(a.native.length>0){console.log("Claude Code Marketplace install detected for frontend-craft."),console.log(le(a)),console.log("Update frontend-craft through Claude Code Marketplace. CLI install/update is disabled while Marketplace is active."),process.exitCode=1;return}let l=t?"cli-global":"cli-local",c=a.cli.filter(M=>Ee(M)!==l);if(c.length===0)return a.hasMultipleActiveSources&&console.log(le(a)),{};let u=c[0],g=Ee(u);if(console.log(`${K(g)} install detected for frontend-craft.`),console.log(le(a)),i){console.log(`[dry-run] resolve the existing ${K(g)} source before using ${K(l)}.`),process.exitCode=1;return}if(!s){Rt(g,l),process.exitCode=1;return}if(await Dt(g,l)==="switch"){if(!wt({installs:c,cwd:o,dryRun:i,force:r})){process.exitCode=1;return}return{}}let S=g==="cli-global";return{redirect:{isGlobal:S,baseDir:Z({runtime:"claude",isGlobal:S,cwd:o})}}}function wt({installs:e,cwd:n,dryRun:t,force:o}){for(let i of e){let r=Se({cwd:n,runtimes:["claude"],scopes:[i.scope]})[0];if(!r)continue;console.log(`Uninstalling existing ${K(Ee(i))} install before switching source.`);let s=Ne({install:r,cwd:n,dryRun:t,force:o});for(let a of s.removed)console.log(`${t?"[dry-run] would remove":"Removed"}${a.modified?" modified file":" file"}: ${a.path}`);for(let a of s.skipped)console.log(`Skipped modified file: ${a}`);for(let a of s.missing)console.log(`Missing file: ${a}`);if(s.skipped.length>0)return console.log("Resolve skipped modified files or rerun with --force before switching Claude CLI install source."),!1}return!0}function Rt(e,n){let t=Gn(e),o=Gn(n);console.log(`Keep the existing source updated with: frontend-craft update claude ${t}`),console.log(`Or switch sources with: frontend-craft uninstall claude ${t} && frontend-craft install claude ${o}`)}async function Dt(e,n){return console.log("Choose how to resolve the Claude CLI install source conflict:"),console.log(` 1. Keep ${K(e)} and update it`),console.log(` 2. Uninstall ${K(e)} and install ${K(n)}`),(await $t("Choice [1]: ")).trim()==="2"?"switch":"keep"}function $t(e){return process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1"&&!process.stdin.isTTY?(process.stdout.write(e),Promise.resolve(m.readFileSync(0,"utf8").split(/\r?\n/)[0]??"")):new Promise(n=>{let t=It.createInterface({input:process.stdin,output:process.stdout});t.question(e,o=>{t.close(),n(o)}),t.on("close",()=>n(""))})}function Ee(e){return e.scope==="global"?"cli-global":"cli-local"}function K(e){return e==="marketplace"?"Claude Code Marketplace":e==="cli-global"?"Claude CLI global":"Claude CLI local"}function Gn(e){return e==="cli-global"?"--global":"--local"}function Ln(e,n){return e?["local"]:n?["global"]:["local","global"]}function Un(e,n,t){return`No frontend-craft installs found${n?` for "${n}"`:""} to ${e} (${t.join(", ")}).`}function Ot({runtime:e,baseDir:n,cwd:t,cap:o,pluginRoot:i,fixCache:r,dryRun:s,isGlobal:a}){let l=[`frontend-craft doctor: ${e}`,`baseDir: ${n}`,`tier: ${o.tier}`];if(l.push(`skills: ${te(Nt(e,n,t),o.skills)}`),l.push(`agents: ${te(m.existsSync(d.join(n,"agents")),o.agents)}`),l.push(`commands: ${te(Ft(e,n),o.commands)}`),l.push(`hooks: ${te(Mt(e,n),o.hooks)}`),l.push(`rules: ${te(_t(e,n),o.rules&&!a)}`),l.push(`templates: ${te(Tt(e,n,t),o.templates)}`),e==="claude"){let c=Ae(i);l.push(le(_e({cwd:t}))),r?l.push(Pn(Tn({currentVersion:c,dryRun:s}),s)):l.push(be(Me({currentVersion:c})))}return l.join(`
85
- `)}function te(e,n){return n?e?"ok":"missing":"not expected"}function Nt(e,n,t){return e==="codex"?m.existsSync(d.join(t,".agents","skills","fec-react-project-standard")):e==="gemini"?m.existsSync(d.join(n,"extensions","frontend-craft","skills","fec-react-project-standard")):m.existsSync(d.join(n,"skills","fec-react-project-standard"))}function Ft(e,n){let t=e==="windsurf"?d.join(n,"workflows"):e==="opencode"||e==="kilo"?d.join(n,"command"):e==="copilot"?d.join(n,"prompts"):d.join(n,"commands");return m.existsSync(d.join(t,"fec-init.md"))}function Mt(e,n){return e==="qoder"?m.existsSync(d.join(n,"settings.json"))&&m.existsSync(d.join(n,"hooks","fec-security-check.js")):m.existsSync(d.join(n,"hooks.json"))}function _t(e,n){return e==="copilot"?m.existsSync(d.join(n,"instructions","frontend-craft.instructions.md")):e==="cline"?m.existsSync(d.join(n,".clinerules")):m.existsSync(d.join(n,"rules"))}function Tt(e,n,t){return e==="claude"?m.existsSync(d.join(t,".claude-plugin","plugin.json")):e==="codex"?m.existsSync(d.join(t,"AGENTS.md"))||m.existsSync(d.join(n,"config.toml")):e==="gemini"?m.existsSync(d.join(t,"GEMINI.md")):e==="openclaw"?m.existsSync(d.join(t,"AGENTS.md")):e==="qoder"?m.existsSync(d.join(n,"settings.json")):e==="opencode"?m.existsSync(d.join(n,"opencode.jsonc")):!1}function Pt(e){let n=[],t=JSON.parse(m.readFileSync(d.join(e,"package.json"),"utf8")),o=[[".claude-plugin/plugin.json","version"],[".claude-plugin/marketplace.json","plugins.0.version"],["openclaw.plugin.json","version"]];for(let[c,u]of o){let g=d.join(e,c),R=JSON.parse(m.readFileSync(g,"utf8")),S=u.split(".").reduce((M,I)=>M?.[Number.isNaN(Number(I))?I:Number(I)],R);S!==t.version&&n.push(`${c} ${u} is ${S}, expected ${t.version}`)}let i=JSON.parse(m.readFileSync(d.join(e,"skills","metadata.json"),"utf8"));for(let c of i)c.version!==t.version&&n.push(`skills/metadata.json ${c.id}.version is ${c.version}, expected ${t.version}`);let r=m.readdirSync(d.join(e,"commands")).filter(c=>c.endsWith(".md")).length,s=m.readdirSync(d.join(e,"skills"),{withFileTypes:!0}).filter(c=>c.isDirectory()).length,a=m.readdirSync(d.join(e,"agents")).filter(c=>c.endsWith(".md")).length,l=m.readFileSync(d.join(e,".claude-plugin","marketplace.json"),"utf8");return l.includes(`${a} agents`)||n.push(`marketplace description must mention ${a} agents`),l.includes(`${s} skills`)||n.push(`marketplace description must mention ${s} skills`),l.includes(`${r} commands`)||n.push(`marketplace description must mention ${r} commands`),n}Wn(process.argv.slice(2)).catch(e=>{console.error(e),process.exit(1)});
86
+ `)}function Hn(e){let n=e[0];return n==null||["--dry-run","--all","--global","-g","--local","-l","--lang"].includes(n)||n.startsWith("--lang=")}async function Xn(e){let n=Hn(e)?"install":e[0],t=Hn(e)?e:e.slice(1),o=n==="setup",i=Gn(import.meta.url);if(n==="version"||n==="-v"||n==="--version"){console.log(He(i));return}if(n==="list"){F.forEach(h=>console.log(h));return}if(n==="matrix"){console.log(En(F));return}if(n==="doctor"){let h=t[0]??"claude",_=t.includes("--global")||t.includes("-g"),T=t.includes("--fix-cache"),G=t.includes("--dry-run"),B=process.cwd(),U=Y({runtime:h,isGlobal:_,cwd:B}),De=ke[h];if(!De){console.error(`Unknown runtime: ${h}`),process.exitCode=1;return}console.log(Bt({runtime:h,baseDir:U,cwd:B,cap:De,pluginRoot:i,fixCache:T,dryRun:G,isGlobal:_}));return}if(n==="sync-metadata"){let h=t.includes("--check"),_=Xt(i);if(_.length>0){for(let T of _)console.error(T);process.exitCode=1;return}console.log(h?"metadata is synchronized":"metadata is synchronized; no changes needed");return}if(n==="help"||n==="-h"||n==="--help"){qe();return}let r=n==="update"||n==="upgrade"?"update":"install";if(n!=="install"&&n!=="setup"&&n!=="update"&&n!=="upgrade"&&n!=="uninstall"&&n!=="remove"){console.error(`Unknown command: ${n}`),qe(),process.exitCode=1;return}if(t.some(h=>h==="help"||h==="--help"||h==="-h")){qe();return}let s=Gt(t),l=s.runtime,a=s.all,{installLocation:c,dryRun:u,force:g,hasGlobal:b,hasLocal:j}=s,R=s.language;if(R!==void 0&&!Ae(R)){console.error(`Unsupported language: ${R||"(missing)"}. Supported languages: ${ve.join(", ")}`),process.exitCode=1;return}let M=R;o&&l==="all"&&(l=void 0,a=!0);let pe=c??(o?"local":null);if(b&&j){console.error("--global and --local cannot be used together."),process.exitCode=1;return}let A=process.cwd();if(n==="uninstall"||n==="remove"){let h=Yn(j,b),T=we({cwd:A,runtimes:l?[l]:a?F:void 0,scopes:h});if(l&&!je[l]){console.error(`Unknown runtime: ${l}`),process.exitCode=1;return}if(T.length===0){console.log(Qn("uninstall",l,h));return}for(let G of T){console.log(`Uninstalling frontend-craft for "${G.runtime}" -> ${G.baseDir}${G.scope==="global"?" (global)":""}`);let B=Ge({install:G,cwd:A,dryRun:u,force:g});for(let U of B.removed)console.log(`${u?"[dry-run] would remove":"Removed"}${U.modified?" modified file":" file"}: ${U.path}`);for(let U of B.skipped)console.log(`Skipped modified file: ${U}`);for(let U of B.missing)console.log(`Missing file: ${U}`);u&&B.skipped.length===0&&console.log(`[dry-run] would remove manifest: ${G.manifestPath}`)}return}let me=!!process.stdin.isTTY||process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1";if(r==="update"&&!l){let h=Yn(j,b),_=we({cwd:A,runtimes:a?F:void 0,scopes:h});if(_.length===0){console.log(Qn("update",void 0,h));return}for(let T of _){let G=M??T.manifest.language??Q;await Kn({rt:T.runtime,mode:r,isGlobal:T.scope==="global",baseDir:T.baseDir,pluginRoot:i,cwd:A,dryRun:u,language:G})}return}let ie=a?F:l?[l]:[];ie.length||(me?ie=await Fn():(console.log("Non-interactive terminal detected, defaulting to claude runtime."),ie=["claude"]));let V=M;!V&&r==="install"&&(me?V=await _n():V=Q);let q;if(pe==="global"?q=!0:pe==="local"?q=!1:me?q=await Mn(ie):(console.log("Non-interactive terminal detected, defaulting to global install."),q=!0),!V&&r==="update"&&l){let h=Y({runtime:l,isGlobal:q,cwd:A});V=le(re(h))?.language??Q}V??=Tn(M);for(let h of ie){if(!je[h]){console.error(`Unknown runtime: ${h}`),process.exitCode=1;continue}let _=Y({runtime:h,isGlobal:q,cwd:A});await Kn({rt:h,mode:r,isGlobal:q,baseDir:_,pluginRoot:i,cwd:A,dryRun:u,force:g,canPrompt:me,language:V})}}async function Kn({rt:e,mode:n,isGlobal:t,baseDir:o,pluginRoot:i,cwd:r,dryRun:s,force:l,canPrompt:a,language:c}){let u=await Ut({rt:e,mode:n,isGlobal:t,cwd:r,dryRun:s,force:!!l,canPrompt:!!a});if(!u)return;u.redirect&&(t=u.redirect.isGlobal,o=u.redirect.baseDir,n="update");let g={pluginRoot:i,contentRoot:Pn(i,c),cwd:r,runtime:e,isGlobal:t,baseDir:o,dryRun:s,mode:n,language:c,capabilities:ke[e]};n==="install"?(console.log(`Installing frontend-craft for "${e}" -> ${o}${t?" (global)":""}`),!s&&m.existsSync(re(o))&&console.log(`Existing frontend-craft manifest found; use "frontend-craft update ${e}" to refresh managed files.`)):console.log(`Updating frontend-craft for "${e}" -> ${o}${t?" (global)":""}`),s||Ke({baseDir:o,cwd:r,mode:n,packageVersion:He(i),runtime:e,isGlobal:t,language:c});try{await je[e](g),s||Je()}catch(b){throw s||Ye(),b}}async function Ut({rt:e,mode:n,isGlobal:t,cwd:o,dryRun:i,force:r,canPrompt:s}){if(e!=="claude")return{};let l=ze({cwd:o});if(l.native.length>0){console.log("Claude Code Marketplace install detected for frontend-craft."),console.log(de(l)),console.log("Update frontend-craft through Claude Code Marketplace. CLI install/update is disabled while Marketplace is active."),process.exitCode=1;return}let a=t?"cli-global":"cli-local",c=l.cli.filter(R=>Be(R)!==a);if(c.length===0)return l.hasMultipleActiveSources&&console.log(de(l)),{};let u=c[0],g=Be(u);if(console.log(`${X(g)} install detected for frontend-craft.`),console.log(de(l)),i){console.log(`[dry-run] resolve the existing ${X(g)} source before using ${X(a)}.`),process.exitCode=1;return}if(!s){zt(g,a),process.exitCode=1;return}if(await Vt(g,a)==="switch"){if(!Wt({installs:c,cwd:o,dryRun:i,force:r})){process.exitCode=1;return}return{}}let j=g==="cli-global";return{redirect:{isGlobal:j,baseDir:Y({runtime:"claude",isGlobal:j,cwd:o})}}}function Wt({installs:e,cwd:n,dryRun:t,force:o}){for(let i of e){let r=we({cwd:n,runtimes:["claude"],scopes:[i.scope]})[0];if(!r)continue;console.log(`Uninstalling existing ${X(Be(i))} install before switching source.`);let s=Ge({install:r,cwd:n,dryRun:t,force:o});for(let l of s.removed)console.log(`${t?"[dry-run] would remove":"Removed"}${l.modified?" modified file":" file"}: ${l.path}`);for(let l of s.skipped)console.log(`Skipped modified file: ${l}`);for(let l of s.missing)console.log(`Missing file: ${l}`);if(s.skipped.length>0)return console.log("Resolve skipped modified files or rerun with --force before switching Claude CLI install source."),!1}return!0}function zt(e,n){let t=Jn(e),o=Jn(n);console.log(`Keep the existing source updated with: frontend-craft update claude ${t}`),console.log(`Or switch sources with: frontend-craft uninstall claude ${t} && frontend-craft install claude ${o}`)}async function Vt(e,n){return console.log("Choose how to resolve the Claude CLI install source conflict:"),console.log(` 1. Keep ${X(e)} and update it`),console.log(` 2. Uninstall ${X(e)} and install ${X(n)}`),(await qt("Choice [1]: ")).trim()==="2"?"switch":"keep"}function qt(e){return process.env.FRONTEND_CRAFT_FORCE_INTERACTIVE==="1"&&!process.stdin.isTTY?(process.stdout.write(e),Promise.resolve(m.readFileSync(0,"utf8").split(/\r?\n/)[0]??"")):new Promise(n=>{let t=At.createInterface({input:process.stdin,output:process.stdout});t.question(e,o=>{t.close(),n(o)}),t.on("close",()=>n(""))})}function Be(e){return e.scope==="global"?"cli-global":"cli-local"}function X(e){return e==="marketplace"?"Claude Code Marketplace":e==="cli-global"?"Claude CLI global":"Claude CLI local"}function Jn(e){return e==="cli-global"?"--global":"--local"}function Yn(e,n){return e?["local"]:n?["global"]:["local","global"]}function Qn(e,n,t){return`No frontend-craft installs found${n?` for "${n}"`:""} to ${e} (${t.join(", ")}).`}function Bt({runtime:e,baseDir:n,cwd:t,cap:o,pluginRoot:i,fixCache:r,dryRun:s,isGlobal:l}){let a=[`frontend-craft doctor: ${e}`,`baseDir: ${n}`,`tier: ${o.tier}`];if(a.push(`skills: ${se(Ht(e,n,t),o.skills)}`),a.push(`agents: ${se(m.existsSync(d.join(n,"agents")),o.agents)}`),a.push(`commands: ${se(Kt(e,n),o.commands)}`),a.push(`hooks: ${se(Jt(e,n),o.hooks)}`),a.push(`rules: ${se(Yt(e,n),o.rules&&!l)}`),a.push(`templates: ${se(Qt(e,n,t),o.templates)}`),e==="claude"){let c=He(i);a.push(de(ze({cwd:t}))),r?a.push(Bn(qn({currentVersion:c,dryRun:s}),s)):a.push(Re(We({currentVersion:c})))}return a.join(`
87
+ `)}function se(e,n){return n?e?"ok":"missing":"not expected"}function Ht(e,n,t){return e==="codex"?m.existsSync(d.join(t,".agents","skills","fec-react-project-standard")):e==="gemini"?m.existsSync(d.join(n,"extensions","frontend-craft","skills","fec-react-project-standard")):m.existsSync(d.join(n,"skills","fec-react-project-standard"))}function Kt(e,n){let t=e==="windsurf"?d.join(n,"workflows"):e==="opencode"||e==="kilo"?d.join(n,"command"):e==="copilot"?d.join(n,"prompts"):d.join(n,"commands");return m.existsSync(d.join(t,"fec-init.md"))}function Jt(e,n){return e==="qoder"?m.existsSync(d.join(n,"settings.json"))&&m.existsSync(d.join(n,"hooks","fec-security-check.js")):m.existsSync(d.join(n,"hooks.json"))}function Yt(e,n){return e==="copilot"?m.existsSync(d.join(n,"instructions","frontend-craft.instructions.md")):e==="cline"?m.existsSync(d.join(n,".clinerules")):m.existsSync(d.join(n,"rules"))}function Qt(e,n,t){return e==="claude"?m.existsSync(d.join(t,".claude-plugin","plugin.json")):e==="codex"?m.existsSync(d.join(t,"AGENTS.md"))||m.existsSync(d.join(n,"config.toml")):e==="gemini"?m.existsSync(d.join(t,"GEMINI.md")):e==="openclaw"?m.existsSync(d.join(t,"AGENTS.md")):e==="qoder"?m.existsSync(d.join(n,"settings.json")):e==="opencode"?m.existsSync(d.join(n,"opencode.jsonc")):!1}function Xt(e){let n=[],t=JSON.parse(m.readFileSync(d.join(e,"package.json"),"utf8")),o=[[".claude-plugin/plugin.json","version"],[".claude-plugin/marketplace.json","plugins.0.version"],["openclaw.plugin.json","version"]];for(let[c,u]of o){let g=d.join(e,c),b=JSON.parse(m.readFileSync(g,"utf8")),j=u.split(".").reduce((R,M)=>R?.[Number.isNaN(Number(M))?M:Number(M)],b);j!==t.version&&n.push(`${c} ${u} is ${j}, expected ${t.version}`)}let i=JSON.parse(m.readFileSync(d.join(e,"skills","metadata.json"),"utf8"));for(let c of i)c.version!==t.version&&n.push(`skills/metadata.json ${c.id}.version is ${c.version}, expected ${t.version}`);let r=m.readdirSync(d.join(e,"commands")).filter(c=>c.endsWith(".md")).length,s=m.readdirSync(d.join(e,"skills"),{withFileTypes:!0}).filter(c=>c.isDirectory()).length,l=m.readdirSync(d.join(e,"agents")).filter(c=>c.endsWith(".md")).length,a=m.readFileSync(d.join(e,".claude-plugin","marketplace.json"),"utf8");return a.includes(`${l} agents`)||n.push(`marketplace description must mention ${l} agents`),a.includes(`${s} skills`)||n.push(`marketplace description must mention ${s} skills`),a.includes(`${r} commands`)||n.push(`marketplace description must mention ${r} commands`),n}Xn(process.argv.slice(2)).catch(e=>{console.error(e),process.exit(1)});
@@ -76,6 +76,9 @@ Each example follows the same shape:
76
76
  | Design-to-code | "Implement the UI from Figma node `123:456`. Use existing design tokens and components, match spacing and responsive states, and document assumptions." | skill: `fec-implement-from-design` · agent: `fec-figma-implementer` | UI code plus design implementation notes/report. | Works best with MCP credentials configured. |
77
77
  | Screenshot-to-polish | "Polish this dashboard UI so it feels like a production SaaS tool: density, hierarchy, empty/loading/error states, responsive layout, and interaction states." | skill: `fec-ui-design` | UI improvements and visual QA notes. | Provide screenshot or local URL if possible. |
78
78
  | Image and diagram generation | "Generate an editable architecture diagram and PNG, then run PNG QA for overlap, clipped labels, and stacked connectors; repair the source for up to two rounds." | skill: `fec-image-generation` · skill: `fec-ui-design` | Editable source, exported PNG, QA report, and repair notes. | Use manifest coordinates when the renderer can expose layout boxes. |
79
+ | System blueprint diagram | "Create a presentation-ready system blueprint for our checkout platform. Keep the JSON and generated HTML as source, then export SVG and PNG delivery artifacts." | skill: `fec-image-generation` | JSON/HTML source, exported SVG/PNG, and source/asset handoff notes. | Best for architecture, deployment topology, agent runtime, memory, and before/after system maps. |
80
+ | Process workflow diagram | "Turn this approval and automation flow into a readable process workflow diagram with lanes, ordered steps, decisions, exception paths, loop-backs, and waypoint-routed edges." | skill: `fec-image-generation` | Workflow JSON/HTML source, exported image, and notes about lanes, nodes, edges, and waypoints. | Use when ownership and branching matter more than exact infrastructure topology. |
81
+ | Interactive live diagram | "Start a local interactive diagram session for the onboarding flow. Add nodes and edges incrementally, let me drag, relabel, remove, zoom, and then export the final deliverables." | skill: `fec-image-generation` | Live browser preview plus saved JSON/SVG/PNG or a handoff to HTML/draw.io source. | Good for collaborative sketching; switch to HTML technical diagrams or draw.io for long-term source ownership. |
79
82
  | Web video presentation | "Turn this article into a recordable 16:9 web video presentation: create script and outline, scaffold a Vite/React stage, and define chapter steps for screen recording." | skill: `fec-web-video-presentation` · skill: `fec-ui-design` | Script/outline, step-driven presentation scaffold, theme notes, and recording checklist. | Best for talks, lessons, product demos, and narrated explainers. |
80
83
  | Responsive layout | "Fix this admin table for 375px, 768px, and 1440px: decide mobile column priority, container-query behavior, touch targets, safe-area handling, and overflow rules." | skill: `fec-responsive-layout` · agent: `fec-ui-checker` | Responsive strategy, layout changes, viewport checks, and remaining risks. | Include screenshots or a local route when possible. |
81
84
  | Tailwind design system | "Refactor these Tailwind components into semantic tokens and variants: theme extension, dark mode, class composition, dynamic class safety, and Storybook state coverage." | skill: `fec-tailwind-design-system` · skill: `fec-ui-design` | Token/variant plan or implementation with class governance and dark-mode checks. | Useful before a shared UI package grows too large. |
@@ -232,7 +232,7 @@ Marketplace が既にインストールされている場合、CLI は `--force`
232
232
  | スキル | 範囲 |
233
233
  | ----------------------------- | ---------------------------------------------------------------------------------------------------------------- |
234
234
  | `fec-ui-design` | プロダクト文脈に沿った UI 方向性、反テンプレート設計ダイヤル、メディア戦略、状態、ビジュアル QA |
235
- | `fec-image-generation` | 図表、画像生成/編集、ビジュアルアセット、PNG QA と修復ループ |
235
+ | `fec-image-generation` | システムブループリント、プロセスワークフロー、インタラクティブなライブ図、HTML/SVG/PNG エクスポート、画像生成/編集、ビジュアルアセット、PNG QA |
236
236
  | `fec-drawio-studio` | 編集可能な draw.io / diagrams.net 技術図、XML/Mermaid/CSV URL 受け渡し、shape 検索、自動レイアウト、コード構造図 |
237
237
  | `fec-web-video-presentation` | 記事、台本、レッスン、demo から録画可能な 16:9 step-driven Web プレゼンを作成 |
238
238
  | `fec-tailwind-design-system` | Tailwind token、テーマ拡張、variants、class 管理、ダークモード |
@@ -232,7 +232,7 @@ Marketplace가 이미 설치된 경우, `--force`를 사용해도 CLI는 두 번
232
232
  | 스킬 | 범위 |
233
233
  | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
234
234
  | `fec-ui-design` | 제품 맥락 UI 방향, 반템플릿 디자인 다이얼, 미디어 전략, 상태, visual QA |
235
- | `fec-image-generation` | 다이어그램, 이미지 생성/편집, 비주얼 에셋, PNG QA 및 수정 루프 |
235
+ | `fec-image-generation` | 시스템 블루프린트, 프로세스 워크플로, 인터랙티브 라이브 다이어그램, HTML/SVG/PNG 내보내기, 이미지 생성/편집, 비주얼 에셋, PNG QA |
236
236
  | `fec-drawio-studio` | 편집 가능한 draw.io / diagrams.net 기술 다이어그램, XML/Mermaid/CSV URL 핸드오프, shape 검색, 자동 레이아웃, 코드 구조도 |
237
237
  | `fec-web-video-presentation` | 글, 스크립트, 레슨, demo를 녹화 가능한 16:9 step-driven 웹 프레젠테이션으로 변환 |
238
238
  | `fec-tailwind-design-system` | Tailwind token, 테마 확장, variants, class 관리, dark mode |
@@ -29,6 +29,9 @@ frontend-craft/
29
29
  | |-- fec-code-review/ # Architecture, types, rendering, styles, a11y
30
30
  | |-- fec-security-review/ # XSS, CSRF, sensitive data, input validation
31
31
  | |-- fec-accessibility-check/ # WCAG 2.2 accessibility, keyboard, focus, screen readers
32
+ | |-- fec-code-review/ # Architecture, types, rendering, styles, a11y
33
+ | |-- fec-security-review/ # XSS, CSRF, sensitive data, input validation
34
+ | |-- fec-accessibility-check/ # WCAG 2.2 accessibility, keyboard, focus, screen readers
32
35
  | |-- fec-react-project-standard/ # React + TypeScript project standards
33
36
  | |-- fec-vue3-project-standard/ # Vue 3 + TypeScript project standards
34
37
  | |-- fec-implement-from-design/ # Implement UI from design tools, screenshots, and visual references
@@ -47,15 +50,17 @@ frontend-craft/
47
50
  | |-- fec-legacy-to-modern-migration/ # jQuery/MPA migration to React/Vue strategy and workflow
48
51
  | |-- fec-testing-strategy/ # Testing layer selection and coverage matrix
49
52
  | |-- fec-e2e-testing/ # Playwright/Cypress E2E testing standards
53
+ | |-- fec-component-testing/ # RTL / Vue Test Utils component tests
54
+ | |-- fec-debug-framework/ # Unified 5-step diagnostic framework for build/runtime/UI/API failures
50
55
  | |-- fec-nextjs-project-standard/ # Next.js 14+ App Router, SSR/SSG standards
51
56
  | |-- fec-nuxt-project-standard/ # Nuxt 3 SSR/SSG, composables standards
52
57
  | |-- fec-monorepo-project-standard/ # pnpm workspace, Turborepo, Nx standards
58
+ | |-- fec-vite-project-standard/ # Vite config, env safety, HMR, proxy, build and library mode
53
59
  | |-- fec-data-fetching/ # TanStack Query and server-state workflows
54
60
  | |-- fec-api-integration/ # Typed API clients, auth refresh, uploads, realtime integration
55
61
  | |-- fec-backend-requirements-handoff/ # Frontend-to-backend UI data and state needs
56
62
  | |-- fec-form-handling/ # React Hook Form + Zod form workflows
57
63
  | |-- fec-route-protection/ # Authenticated and permissioned routes
58
- | |-- fec-component-testing/ # RTL / Vue Test Utils component tests
59
64
  | |-- fec-pwa-implementation/ # PWA manifest, service worker, offline
60
65
  | |-- fec-web-workers/ # Worker integration and background compute
61
66
  | |-- fec-canvas-threejs/ # Canvas, Three.js, React Three Fiber
@@ -65,10 +70,10 @@ frontend-craft/
65
70
  | |-- fec-storybook-component-doc/ # Storybook component docs, addons, MDX, interaction and visual test integration
66
71
  | |-- fec-ui-design/ # Product-context UI direction, design dials, media strategy, visual QA
67
72
  | |-- fec-image-generation/ # Diagram/image generation, editing workflows, PNG QA and repair loops
68
- | |-- fec-drawio-studio/ # Editable draw.io diagrams, shape lookup, auto-layout, code structure maps
69
- | |-- fec-web-video-presentation/ # Recordable 16:9 step-driven web video presentations
73
+ | |-- fec-drawio-studio/ # Editable draw.io diagrams, shape lookup, auto-layout, code structure maps
74
+ | |-- fec-web-video-presentation/ # Recordable 16:9 step-driven web video presentations
70
75
  | |-- fec-motion-interaction/ # Context-aware motion intensity, transitions, scroll animation, reduced motion
71
- | |-- fec-vite-project-standard/ # Vite config, env safety, HMR, proxy, build and library mode
76
+ | |-- fec-alchemy/ # Project absorption workflow — extract reference ideas and redesign natively
72
77
  |
73
78
  |-- commands/ # Slash commands for quick execution
74
79
  | |-- fec-init.md # /fec-init - Initialize project templates
@@ -98,7 +103,10 @@ frontend-craft/
98
103
  |-- templates/ # Runtime-specific project templates
99
104
  | |-- claude/ # CLAUDE.md and settings.json
100
105
  | |-- codex/ # AGENTS.md and config.toml
106
+ | |-- cursor/ # Cursor runtime project stubs
107
+ | |-- gemini/ # Gemini CLI runtime project stubs
101
108
  | |-- openclaw/ # AGENTS.md and OPENCLAW-CONFIG.md
109
+ | |-- windsurf/ # Windsurf runtime project stubs
102
110
  | |-- shared/rules/ # 20 rule files: vue, react, rendering patterns, responsive design, testing, source-driven development, etc.
103
111
  |
104
112
  |-- .mcp.json # MCP server config (Figma, Figma Desktop, Sketch, MasterGo, Pixso, 墨刀)
@@ -119,5 +127,5 @@ frontend-craft/
119
127
  | `src/hooks/` | Runtime hook source bundled into `dist/hooks/` for Claude/Qoder execution |
120
128
  | `src/install/` | Installer core (CLI, interactive wizard, runtime converters) |
121
129
  | `src/openclaw/` | OpenClaw runtime TypeScript source |
122
- | `templates/` | Runtime-specific project templates (Claude/Codex/OpenClaw configs + shared rules) |
130
+ | `templates/` | Runtime-specific project templates (Claude/Codex/Cursor/Gemini/OpenClaw/Windsurf configs + shared rules) |
123
131
  | `tests/` | Test suite (converter tests, installer tests) |
@@ -76,6 +76,9 @@
76
76
  | 设计稿实现 | 「请按 Figma 节点 `123:456` 实现 UI。复用现有 design token 和组件,匹配间距与响应式状态,并说明假设。」 | skill: `fec-implement-from-design` · agent: `fec-figma-implementer` | UI 代码和设计实现说明/报告。 | 配好 MCP 凭据效果最好。 |
77
77
  | 截图到 UI 打磨 | 「请打磨这个 dashboard,让它像生产级 SaaS 工具:信息密度、层级、空/加载/错误状态、响应式布局和交互状态。」 | skill: `fec-ui-design` | UI 改进和视觉 QA 说明。 | 可提供截图或本地 URL。 |
78
78
  | 图片与图表生成 | 「请生成可编辑技术架构图和 PNG,然后自检重叠、标签截断、连线堆叠,并最多修复两轮源文件。」 | skill: `fec-image-generation` · skill: `fec-ui-design` | 可编辑源、导出 PNG、QA 报告和修复说明。 | 渲染器能暴露布局框时附带 manifest 坐标。 |
79
+ | 系统蓝图图表 | 「请为我们的 checkout 平台创建适合演示的系统蓝图。保留 JSON 和生成的 HTML 作为源文件,然后导出 SVG 和 PNG 交付物。」 | skill: `fec-image-generation` | JSON/HTML 源文件、导出的 SVG/PNG,以及源文件/资产交接说明。 | 适合架构、部署拓扑、agent runtime、memory 和 before/after 系统图。 |
80
+ | 流程工作流图 | 「请把这个审批和自动化流程转成清晰的流程工作流图:包含 lanes、顺序步骤、决策、异常路径、循环回退和 waypoint 路由连线。」 | skill: `fec-image-generation` | Workflow JSON/HTML 源文件、导出图片,以及 lanes、nodes、edges、waypoints 说明。 | 当归属和分支比精确基础设施拓扑更重要时使用。 |
81
+ | 交互式实时图 | 「请为 onboarding flow 启动本地交互式图表会话。逐步添加节点和连线,让我可以拖拽、改名、删除、缩放,最后导出交付物。」 | skill: `fec-image-generation` | 浏览器实时预览,以及保存的 JSON/SVG/PNG,或切换到 HTML/draw.io 源文件交付。 | 适合协作草图;需要长期维护源文件时切换到 HTML 技术图或 draw.io。 |
79
82
  | 网页视频演示 | 「把这篇文章转成可录屏的 16:9 网页视频演示:生成口播稿和 outline,创建 Vite/React 舞台,并定义章节 step 方便录屏。」 | skill: `fec-web-video-presentation` · skill: `fec-ui-design` | 口播稿/outline、步进演示脚手架、主题说明和录屏清单。 | 适合技术分享、课程、产品 demo 和口播讲解。 |
80
83
  | 响应式布局 | 「修复这个后台表格在 375px、768px、1440px 下的问题:决定移动端列优先级、容器查询、触摸目标、安全区域和溢出规则。」 | skill: `fec-responsive-layout` · agent: `fec-ui-checker` | 响应式策略、布局修改、视口检查和剩余风险。 | 最好提供截图或本地路由。 |
81
84
  | Tailwind 设计系统 | 「把这些 Tailwind 组件重构成语义 token 和 variants:theme 扩展、暗色模式、class 组合、动态 class 安全和 Storybook 状态覆盖。」 | skill: `fec-tailwind-design-system` · skill: `fec-ui-design` | token/variant 方案或实现、class 治理和暗色模式检查。 | 适合共享 UI 包变复杂前使用。 |
@@ -47,6 +47,7 @@ frontend-craft/
47
47
  | |-- fec-legacy-to-modern-migration/ # jQuery/MPA 迁移到 React/Vue 的策略和工作流
48
48
  | |-- fec-testing-strategy/ # 测试分层选择和覆盖矩阵
49
49
  | |-- fec-e2e-testing/ # Playwright/Cypress E2E 测试规范
50
+ | |-- fec-debug-framework/ # 统一 5 步诊断框架:构建/运行时/UI/API 失败
50
51
  | |-- fec-nextjs-project-standard/ # Next.js 14+ App Router、SSR/SSG 规范
51
52
  | |-- fec-nuxt-project-standard/ # Nuxt 3 SSR/SSG、composables 规范
52
53
  | |-- fec-monorepo-project-standard/ # pnpm workspace、Turborepo、Nx 规范
@@ -69,6 +70,7 @@ frontend-craft/
69
70
  | |-- fec-web-video-presentation/ # 可录屏的 16:9 步进网页视频演示
70
71
  | |-- fec-motion-interaction/ # 场景化动效强度、页面转场、滚动动画、reduced motion
71
72
  | |-- fec-vite-project-standard/ # Vite 配置、环境变量安全、HMR、代理、构建与 library mode
73
+ | |-- fec-alchemy/ # 项目吸收工作流——抽取参考系统能力并原创化重写
72
74
  |
73
75
  |-- commands/ # 快速执行的斜杠命令
74
76
  | |-- fec-init.md # /fec-init - 初始化项目模板
@@ -98,7 +100,10 @@ frontend-craft/
98
100
  |-- templates/ # 运行时专用项目模板
99
101
  | |-- claude/ # CLAUDE.md 和 settings.json
100
102
  | |-- codex/ # AGENTS.md 和 config.toml
103
+ | |-- cursor/ # Cursor 运行时项目存根
104
+ | |-- gemini/ # Gemini CLI 运行时项目存根
101
105
  | |-- openclaw/ # AGENTS.md 和 OPENCLAW-CONFIG.md
106
+ | |-- windsurf/ # Windsurf 运行时项目存根
102
107
  | |-- shared/rules/ # 20 个规则文件:vue、react、rendering patterns、responsive design、testing、source-driven development 等
103
108
  |
104
109
  |-- .mcp.json # MCP server 配置(Figma、Figma Desktop、Sketch、MasterGo、Pixso、墨刀)
@@ -119,5 +124,5 @@ frontend-craft/
119
124
  | `src/hooks/` | 打包到 `dist/hooks/` 的运行时 hook 源码,供 Claude/Qoder 执行 |
120
125
  | `src/install/` | 安装器核心(CLI、交互向导、运行时转换器) |
121
126
  | `src/openclaw/` | OpenClaw 运行时 TypeScript 源码 |
122
- | `templates/` | 运行时专用项目模板(Claude/Codex/OpenClaw 配置 + shared rules) |
127
+ | `templates/` | 运行时专用项目模板(Claude/Codex/Cursor/Gemini/OpenClaw/Windsurf 配置 + shared rules) |
123
128
  | `tests/` | 测试套件(转换器测试、安装器测试) |
@@ -232,7 +232,7 @@ npx @bovinphang/frontend-craft@latest list
232
232
  | 技能 | 範圍 |
233
233
  | ----------------------------- | ------------------------------------------------------------------------------------------------ |
234
234
  | `fec-ui-design` | 產品語境 UI 方向、反模板設計撥盤、媒體策略、狀態、視覺 QA |
235
- | `fec-image-generation` | 圖表、圖片生成/編輯、視覺資產、PNG 自檢和修復循環 |
235
+ | `fec-image-generation` | 系統藍圖、流程工作流、互動式即時圖、HTML/SVG/PNG 匯出、圖片生成/編輯、視覺資產和 PNG 自檢 |
236
236
  | `fec-drawio-studio` | 可編輯 draw.io / diagrams.net 技術圖、XML/Mermaid/CSV URL 交付、形狀檢索、自動布局和程式碼結構圖 |
237
237
  | `fec-web-video-presentation` | 將文章、口播稿、課程和 demo 轉成可錄屏的 16:9 步進網頁演示 |
238
238
  | `fec-tailwind-design-system` | Tailwind token、主題擴展、元件變體、class 治理和暗色模式 |