@bovinphang/frontend-craft 2.6.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 (414) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +72 -1
  4. package/CHANGELOG.zh-CN.md +71 -1
  5. package/README.md +10 -6
  6. package/README.openclaw.md +100 -42
  7. package/README.openclaw.zh-CN.md +100 -42
  8. package/README.zh-CN.md +10 -6
  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 +88 -88
  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 +84 -69
  32. package/docs/ja-JP/README.md +56 -52
  33. package/docs/ko-KR/README.md +45 -41
  34. package/docs/project-structure.md +19 -7
  35. package/docs/superpowers/plans/2026-05-29-fec-debug.md +491 -0
  36. package/docs/superpowers/specs/2026-05-29-fec-debug-design.md +340 -0
  37. package/docs/zh-CN/example-prompts.md +84 -69
  38. package/docs/zh-CN/project-structure.md +14 -5
  39. package/docs/zh-TW/README.md +33 -29
  40. package/localized/zh-CN/agents/fec-architect.md +125 -0
  41. package/localized/zh-CN/agents/fec-code-reviewer.md +152 -0
  42. package/localized/zh-CN/agents/fec-debugger.md +44 -0
  43. package/localized/zh-CN/agents/fec-design-token-mapper.md +75 -0
  44. package/localized/zh-CN/agents/fec-doc-updater.md +30 -0
  45. package/localized/zh-CN/agents/fec-e2e-runner.md +107 -0
  46. package/localized/zh-CN/agents/fec-figma-implementer.md +104 -0
  47. package/localized/zh-CN/agents/fec-performance-optimizer.md +293 -0
  48. package/localized/zh-CN/agents/fec-refactor-cleaner.md +32 -0
  49. package/localized/zh-CN/agents/fec-security-reviewer.md +116 -0
  50. package/localized/zh-CN/agents/fec-test-planner.md +50 -0
  51. package/localized/zh-CN/agents/fec-typescript-reviewer.md +142 -0
  52. package/localized/zh-CN/agents/fec-ui-checker.md +120 -0
  53. package/localized/zh-CN/commands/fec-debug.md +30 -0
  54. package/localized/zh-CN/commands/fec-doc-sync.md +19 -0
  55. package/localized/zh-CN/commands/fec-init.md +70 -0
  56. package/localized/zh-CN/commands/fec-plan.md +94 -0
  57. package/localized/zh-CN/commands/fec-refactor-clean.md +19 -0
  58. package/localized/zh-CN/commands/fec-review.md +66 -0
  59. package/localized/zh-CN/commands/fec-scaffold.md +205 -0
  60. package/localized/zh-CN/commands/fec-tdd.md +21 -0
  61. package/localized/zh-CN/skills/TEMPLATE.md +155 -0
  62. package/localized/zh-CN/skills/eval_queries.json +1013 -0
  63. package/localized/zh-CN/skills/fec-accessibility-check/SKILL.md +39 -0
  64. package/localized/zh-CN/skills/fec-accessibility-check/references/report-template.md +23 -0
  65. package/localized/zh-CN/skills/fec-accessibility-check/references/screen-reader-testing.md +33 -0
  66. package/localized/zh-CN/skills/fec-alchemy/SKILL.md +74 -0
  67. package/localized/zh-CN/skills/fec-alchemy/assets/absorption-plan-template.md +47 -0
  68. package/localized/zh-CN/skills/fec-alchemy/assets/intake-template.md +55 -0
  69. package/localized/zh-CN/skills/fec-alchemy/assets/review-checklist.md +31 -0
  70. package/localized/zh-CN/skills/fec-alchemy/references/methodology.md +94 -0
  71. package/localized/zh-CN/skills/fec-alchemy/references/originality-and-licensing.md +57 -0
  72. package/localized/zh-CN/skills/fec-api-integration/SKILL.md +78 -0
  73. package/localized/zh-CN/skills/fec-api-integration/references/integration-patterns.md +80 -0
  74. package/localized/zh-CN/skills/fec-backend-requirements-handoff/SKILL.md +45 -0
  75. package/localized/zh-CN/skills/fec-browser-storage/SKILL.md +34 -0
  76. package/localized/zh-CN/skills/fec-browser-storage/references/storage-patterns.md +65 -0
  77. package/localized/zh-CN/skills/fec-canvas-threejs/SKILL.md +66 -0
  78. package/localized/zh-CN/skills/fec-canvas-threejs/references/rendering-patterns.md +67 -0
  79. package/localized/zh-CN/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +67 -0
  80. package/localized/zh-CN/skills/fec-code-review/SKILL.md +143 -0
  81. package/localized/zh-CN/skills/fec-code-review/references/report-template.md +29 -0
  82. package/localized/zh-CN/skills/fec-component-testing/SKILL.md +119 -0
  83. package/localized/zh-CN/skills/fec-data-fetching/SKILL.md +62 -0
  84. package/localized/zh-CN/skills/fec-data-fetching/references/query-patterns.md +103 -0
  85. package/localized/zh-CN/skills/fec-debug-framework/SKILL.md +157 -0
  86. package/localized/zh-CN/skills/fec-debug-framework/references/report-template.md +58 -0
  87. package/localized/zh-CN/skills/fec-dependency-upgrade/SKILL.md +34 -0
  88. package/localized/zh-CN/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +56 -0
  89. package/localized/zh-CN/skills/fec-doc-sync/SKILL.md +39 -0
  90. package/localized/zh-CN/skills/fec-drawio-studio/SKILL.md +73 -0
  91. package/localized/zh-CN/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
  92. package/localized/zh-CN/skills/fec-drawio-studio/data/brand-icons.json +878 -0
  93. package/localized/zh-CN/skills/fec-drawio-studio/data/shape-index.json +83570 -0
  94. package/localized/zh-CN/skills/fec-drawio-studio/references/data-residency.md +27 -0
  95. package/localized/zh-CN/skills/fec-drawio-studio/references/diagram-patterns.md +60 -0
  96. package/localized/zh-CN/skills/fec-drawio-studio/references/flowchart-quality.md +49 -0
  97. package/localized/zh-CN/skills/fec-drawio-studio/references/layout-and-export.md +72 -0
  98. package/localized/zh-CN/skills/fec-drawio-studio/references/troubleshooting.md +29 -0
  99. package/localized/zh-CN/skills/fec-drawio-studio/references/xml-and-mermaid.md +58 -0
  100. package/localized/zh-CN/skills/fec-drawio-studio/scripts/brand-symbols.mjs +99 -0
  101. package/localized/zh-CN/skills/fec-drawio-studio/scripts/diagram-lint.mjs +205 -0
  102. package/localized/zh-CN/skills/fec-drawio-studio/scripts/diagram-url.mjs +102 -0
  103. package/localized/zh-CN/skills/fec-drawio-studio/scripts/drawio-export.mjs +134 -0
  104. package/localized/zh-CN/skills/fec-drawio-studio/scripts/layout-graph.mjs +107 -0
  105. package/localized/zh-CN/skills/fec-drawio-studio/scripts/png-embed-fix.mjs +26 -0
  106. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-go-packages.mjs +36 -0
  107. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-js-modules.mjs +52 -0
  108. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-python-classes.mjs +30 -0
  109. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-python-modules.mjs +55 -0
  110. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
  111. package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
  112. package/localized/zh-CN/skills/fec-drawio-studio/scripts/shape-query.mjs +121 -0
  113. package/localized/zh-CN/skills/fec-drawio-studio/scripts/studio-core.mjs +139 -0
  114. package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/corporate.json +49 -0
  115. package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/default.json +49 -0
  116. package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/handdrawn.json +49 -0
  117. package/localized/zh-CN/skills/fec-drawio-studio/styles/schema.json +112 -0
  118. package/localized/zh-CN/skills/fec-e2e-testing/SKILL.md +42 -0
  119. package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-ci-reporting.md +62 -0
  120. package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-special-scenarios.md +52 -0
  121. package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-visual-regression.md +60 -0
  122. package/localized/zh-CN/skills/fec-e2e-testing/references/playwright-patterns.md +95 -0
  123. package/localized/zh-CN/skills/fec-form-handling/SKILL.md +76 -0
  124. package/localized/zh-CN/skills/fec-form-handling/references/advanced-form-patterns.md +101 -0
  125. package/localized/zh-CN/skills/fec-image-generation/SKILL.md +80 -0
  126. package/localized/zh-CN/skills/fec-image-generation/assets/interactive-diagram.html +371 -0
  127. package/localized/zh-CN/skills/fec-image-generation/references/artifact-routing.md +80 -0
  128. package/localized/zh-CN/skills/fec-image-generation/references/diagram-workflows.md +74 -0
  129. package/localized/zh-CN/skills/fec-image-generation/references/html-technical-diagrams.md +236 -0
  130. package/localized/zh-CN/skills/fec-image-generation/references/png-qa-autofix.md +30 -0
  131. package/localized/zh-CN/skills/fec-image-generation/scripts/export-diagram.mjs +364 -0
  132. package/localized/zh-CN/skills/fec-image-generation/scripts/interactive-diagram-server.mjs +654 -0
  133. package/localized/zh-CN/skills/fec-image-generation/scripts/png-qa.mjs +431 -0
  134. package/localized/zh-CN/skills/fec-image-generation/scripts/tech-diagram-render.mjs +1397 -0
  135. package/localized/zh-CN/skills/fec-implement-from-design/SKILL.md +129 -0
  136. package/localized/zh-CN/skills/fec-implement-from-design/references/design-plan-template.md +36 -0
  137. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/SKILL.md +46 -0
  138. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +110 -0
  139. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +41 -0
  140. package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +48 -0
  141. package/localized/zh-CN/skills/fec-legacy-web-standard/SKILL.md +35 -0
  142. package/localized/zh-CN/skills/fec-legacy-web-standard/references/legacy-patterns.md +85 -0
  143. package/localized/zh-CN/skills/fec-list-virtualization/SKILL.md +34 -0
  144. package/localized/zh-CN/skills/fec-list-virtualization/references/virtualization-patterns.md +80 -0
  145. package/localized/zh-CN/skills/fec-monorepo-project-standard/SKILL.md +142 -0
  146. package/localized/zh-CN/skills/fec-motion-interaction/SKILL.md +73 -0
  147. package/localized/zh-CN/skills/fec-motion-interaction/references/motion-patterns.md +112 -0
  148. package/localized/zh-CN/skills/fec-nextjs-project-standard/SKILL.md +123 -0
  149. package/localized/zh-CN/skills/fec-nuxt-project-standard/SKILL.md +122 -0
  150. package/localized/zh-CN/skills/fec-performance-optimization/SKILL.md +80 -0
  151. package/localized/zh-CN/skills/fec-performance-optimization/references/framework-performance-patterns.md +38 -0
  152. package/localized/zh-CN/skills/fec-performance-optimization/references/report-template.md +59 -0
  153. package/localized/zh-CN/skills/fec-pwa-implementation/SKILL.md +35 -0
  154. package/localized/zh-CN/skills/fec-pwa-implementation/references/manifest-and-icons.md +53 -0
  155. package/localized/zh-CN/skills/fec-pwa-implementation/references/service-worker-workbox.md +68 -0
  156. package/localized/zh-CN/skills/fec-react-project-standard/SKILL.md +91 -0
  157. package/localized/zh-CN/skills/fec-react-project-standard/references/react-performance-patterns.md +35 -0
  158. package/localized/zh-CN/skills/fec-react-project-standard/references/react-project-structure.md +197 -0
  159. package/localized/zh-CN/skills/fec-react-project-standard/references/react-quality-patterns.md +131 -0
  160. package/localized/zh-CN/skills/fec-react-project-standard/references/react-runtime-patterns.md +293 -0
  161. package/localized/zh-CN/skills/fec-refactor-clean/SKILL.md +51 -0
  162. package/localized/zh-CN/skills/fec-refactor-clean/references/report-template.md +42 -0
  163. package/localized/zh-CN/skills/fec-responsive-layout/SKILL.md +34 -0
  164. package/localized/zh-CN/skills/fec-responsive-layout/references/responsive-layout-patterns.md +70 -0
  165. package/localized/zh-CN/skills/fec-route-protection/SKILL.md +135 -0
  166. package/localized/zh-CN/skills/fec-security-review/SKILL.md +38 -0
  167. package/localized/zh-CN/skills/fec-security-review/references/report-template.md +27 -0
  168. package/localized/zh-CN/skills/fec-security-review/references/security-checklist.md +64 -0
  169. package/localized/zh-CN/skills/fec-source-driven-development/SKILL.md +87 -0
  170. package/localized/zh-CN/skills/fec-state-management/SKILL.md +140 -0
  171. package/localized/zh-CN/skills/fec-state-management/references/state-patterns.md +109 -0
  172. package/localized/zh-CN/skills/fec-storybook-component-doc/SKILL.md +37 -0
  173. package/localized/zh-CN/skills/fec-storybook-component-doc/references/story-patterns.md +118 -0
  174. package/localized/zh-CN/skills/fec-svg-animation/SKILL.md +148 -0
  175. package/localized/zh-CN/skills/fec-tailwind-design-system/SKILL.md +34 -0
  176. package/localized/zh-CN/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +59 -0
  177. package/localized/zh-CN/skills/fec-tdd-workflow/SKILL.md +52 -0
  178. package/localized/zh-CN/skills/fec-testing-strategy/SKILL.md +45 -0
  179. package/localized/zh-CN/skills/fec-typescript-project-standard/SKILL.md +54 -0
  180. package/{skills/fec-typescript-type-safety → localized/zh-CN/skills/fec-typescript-project-standard}/references/type-safety-patterns.md +1 -1
  181. package/{skills/fec-typescript-type-safety/SKILL.md → localized/zh-CN/skills/fec-typescript-project-standard/references/type-safety.md} +5 -14
  182. package/localized/zh-CN/skills/fec-ui-design/SKILL.md +108 -0
  183. package/localized/zh-CN/skills/fec-ui-design/data/product-rules.json +231 -0
  184. package/localized/zh-CN/skills/fec-ui-design/data/stack-ui-rules.json +146 -0
  185. package/localized/zh-CN/skills/fec-ui-design/data/style-archetypes.json +373 -0
  186. package/localized/zh-CN/skills/fec-ui-design/data/ux-quality-rules.json +203 -0
  187. package/localized/zh-CN/skills/fec-ui-design/references/design-intelligence.md +97 -0
  188. package/localized/zh-CN/skills/fec-ui-design/references/master-page-overrides.md +30 -0
  189. package/localized/zh-CN/skills/fec-ui-design/references/pre-delivery-checklist.md +39 -0
  190. package/localized/zh-CN/skills/fec-ui-design/scripts/design-system.mjs +648 -0
  191. package/localized/zh-CN/skills/fec-validation-fix/SKILL.md +51 -0
  192. package/localized/zh-CN/skills/fec-validation-fix/references/report-template.md +43 -0
  193. package/localized/zh-CN/skills/fec-vite-project-standard/SKILL.md +83 -0
  194. package/localized/zh-CN/skills/fec-vue3-project-standard/SKILL.md +58 -0
  195. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +162 -0
  196. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +13 -0
  197. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-project-structure.md +176 -0
  198. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +216 -0
  199. package/localized/zh-CN/skills/fec-web-video-presentation/SKILL.md +61 -0
  200. package/localized/zh-CN/skills/fec-web-video-presentation/data/starter-themes.json +59 -0
  201. package/localized/zh-CN/skills/fec-web-video-presentation/references/chapter-craft.md +37 -0
  202. package/localized/zh-CN/skills/fec-web-video-presentation/references/content-plan.md +38 -0
  203. package/localized/zh-CN/skills/fec-web-video-presentation/references/recording-and-audio.md +33 -0
  204. package/localized/zh-CN/skills/fec-web-video-presentation/references/theme-system.md +36 -0
  205. package/localized/zh-CN/skills/fec-web-video-presentation/scripts/create-video-presentation.mjs +430 -0
  206. package/localized/zh-CN/skills/fec-web-workers/SKILL.md +35 -0
  207. package/localized/zh-CN/skills/fec-web-workers/references/advanced-workers.md +54 -0
  208. package/localized/zh-CN/skills/fec-web-workers/references/basic-worker.md +67 -0
  209. package/localized/zh-CN/skills/metadata.json +1646 -0
  210. package/localized/zh-CN/skills/relations.json +755 -0
  211. package/localized/zh-CN/templates/claude/CLAUDE.md +106 -0
  212. package/localized/zh-CN/templates/claude/settings.json +62 -0
  213. package/localized/zh-CN/templates/codex/AGENTS.md +105 -0
  214. package/localized/zh-CN/templates/codex/config.toml +32 -0
  215. package/localized/zh-CN/templates/openclaw/AGENTS.md +101 -0
  216. package/localized/zh-CN/templates/openclaw/OPENCLAW-CONFIG.md +12 -0
  217. package/localized/zh-CN/templates/shared/rules/fec-agent-workflow.md +54 -0
  218. package/localized/zh-CN/templates/shared/rules/fec-api-layer.md +99 -0
  219. package/localized/zh-CN/templates/shared/rules/fec-ci-cd.md +40 -0
  220. package/localized/zh-CN/templates/shared/rules/fec-code-comments.md +33 -0
  221. package/localized/zh-CN/templates/shared/rules/fec-design-system.md +72 -0
  222. package/localized/zh-CN/templates/shared/rules/fec-error-handling.md +56 -0
  223. package/localized/zh-CN/templates/shared/rules/fec-git-conventions.md +73 -0
  224. package/localized/zh-CN/templates/shared/rules/fec-i18n.md +64 -0
  225. package/localized/zh-CN/templates/shared/rules/fec-naming-conventions.md +120 -0
  226. package/localized/zh-CN/templates/shared/rules/fec-performance.md +101 -0
  227. package/localized/zh-CN/templates/shared/rules/fec-react.md +82 -0
  228. package/localized/zh-CN/templates/shared/rules/fec-refactoring.md +47 -0
  229. package/localized/zh-CN/templates/shared/rules/fec-rendering-patterns.md +40 -0
  230. package/localized/zh-CN/templates/shared/rules/fec-responsive-design.md +50 -0
  231. package/localized/zh-CN/templates/shared/rules/fec-source-driven-development.md +31 -0
  232. package/localized/zh-CN/templates/shared/rules/fec-state-management.md +60 -0
  233. package/localized/zh-CN/templates/shared/rules/fec-testing.md +98 -0
  234. package/localized/zh-CN/templates/shared/rules/fec-typescript.md +112 -0
  235. package/localized/zh-CN/templates/shared/rules/fec-vue.md +64 -0
  236. package/localized/zh-CN/templates/shared/rules/fec-working-modes.md +50 -0
  237. package/openclaw.plugin.json +1 -1
  238. package/package.json +4 -3
  239. package/skills/TEMPLATE.md +74 -74
  240. package/skills/eval_queries.json +717 -619
  241. package/skills/fec-accessibility-check/SKILL.md +21 -21
  242. package/skills/fec-accessibility-check/references/report-template.md +12 -12
  243. package/skills/fec-accessibility-check/references/screen-reader-testing.md +24 -24
  244. package/skills/fec-alchemy/SKILL.md +50 -50
  245. package/skills/fec-alchemy/assets/absorption-plan-template.md +32 -32
  246. package/skills/fec-alchemy/assets/intake-template.md +55 -55
  247. package/skills/fec-alchemy/assets/review-checklist.md +23 -23
  248. package/skills/fec-alchemy/references/methodology.md +66 -66
  249. package/skills/fec-alchemy/references/originality-and-licensing.md +42 -42
  250. package/skills/fec-api-integration/SKILL.md +61 -61
  251. package/skills/fec-api-integration/references/integration-patterns.md +30 -30
  252. package/skills/fec-backend-requirements-handoff/SKILL.md +45 -0
  253. package/skills/fec-browser-storage/SKILL.md +16 -16
  254. package/skills/fec-browser-storage/references/storage-patterns.md +16 -16
  255. package/skills/fec-canvas-threejs/SKILL.md +21 -21
  256. package/skills/fec-canvas-threejs/references/rendering-patterns.md +10 -10
  257. package/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +37 -37
  258. package/skills/fec-code-review/SKILL.md +94 -94
  259. package/skills/fec-code-review/references/report-template.md +13 -13
  260. package/skills/fec-component-testing/SKILL.md +39 -39
  261. package/skills/fec-data-fetching/SKILL.md +16 -16
  262. package/skills/fec-data-fetching/references/query-patterns.md +27 -27
  263. package/skills/fec-debug-framework/SKILL.md +95 -95
  264. package/skills/fec-debug-framework/references/report-template.md +34 -34
  265. package/skills/fec-dependency-upgrade/SKILL.md +17 -17
  266. package/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +31 -31
  267. package/skills/fec-doc-sync/SKILL.md +23 -23
  268. package/skills/fec-drawio-studio/SKILL.md +73 -0
  269. package/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
  270. package/skills/fec-drawio-studio/data/brand-icons.json +878 -0
  271. package/skills/fec-drawio-studio/data/shape-index.json +83570 -0
  272. package/skills/fec-drawio-studio/references/data-residency.md +27 -0
  273. package/skills/fec-drawio-studio/references/diagram-patterns.md +60 -0
  274. package/skills/fec-drawio-studio/references/flowchart-quality.md +49 -0
  275. package/skills/fec-drawio-studio/references/layout-and-export.md +72 -0
  276. package/skills/fec-drawio-studio/references/troubleshooting.md +29 -0
  277. package/skills/fec-drawio-studio/references/xml-and-mermaid.md +58 -0
  278. package/skills/fec-drawio-studio/scripts/brand-symbols.mjs +99 -0
  279. package/skills/fec-drawio-studio/scripts/diagram-lint.mjs +205 -0
  280. package/skills/fec-drawio-studio/scripts/diagram-url.mjs +102 -0
  281. package/skills/fec-drawio-studio/scripts/drawio-export.mjs +134 -0
  282. package/skills/fec-drawio-studio/scripts/layout-graph.mjs +107 -0
  283. package/skills/fec-drawio-studio/scripts/png-embed-fix.mjs +26 -0
  284. package/skills/fec-drawio-studio/scripts/scan-go-packages.mjs +36 -0
  285. package/skills/fec-drawio-studio/scripts/scan-js-modules.mjs +52 -0
  286. package/skills/fec-drawio-studio/scripts/scan-python-classes.mjs +30 -0
  287. package/skills/fec-drawio-studio/scripts/scan-python-modules.mjs +55 -0
  288. package/skills/fec-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
  289. package/skills/fec-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
  290. package/skills/fec-drawio-studio/scripts/shape-query.mjs +121 -0
  291. package/skills/fec-drawio-studio/scripts/studio-core.mjs +139 -0
  292. package/skills/fec-drawio-studio/styles/built-in/corporate.json +49 -0
  293. package/skills/fec-drawio-studio/styles/built-in/default.json +49 -0
  294. package/skills/fec-drawio-studio/styles/built-in/handdrawn.json +49 -0
  295. package/skills/fec-drawio-studio/styles/schema.json +112 -0
  296. package/skills/fec-e2e-testing/SKILL.md +24 -22
  297. package/skills/fec-e2e-testing/references/e2e-ci-reporting.md +62 -0
  298. package/skills/fec-e2e-testing/references/e2e-special-scenarios.md +52 -0
  299. package/skills/fec-e2e-testing/references/e2e-visual-regression.md +60 -0
  300. package/skills/fec-e2e-testing/references/playwright-patterns.md +6 -6
  301. package/skills/fec-form-handling/SKILL.md +21 -21
  302. package/skills/fec-form-handling/references/advanced-form-patterns.md +41 -41
  303. package/skills/fec-image-generation/SKILL.md +81 -0
  304. package/skills/fec-image-generation/assets/interactive-diagram.html +371 -0
  305. package/skills/fec-image-generation/references/artifact-routing.md +80 -0
  306. package/skills/fec-image-generation/references/diagram-workflows.md +74 -0
  307. package/skills/fec-image-generation/references/html-technical-diagrams.md +236 -0
  308. package/skills/fec-image-generation/references/png-qa-autofix.md +30 -0
  309. package/skills/fec-image-generation/scripts/export-diagram.mjs +364 -0
  310. package/skills/fec-image-generation/scripts/interactive-diagram-server.mjs +654 -0
  311. package/skills/fec-image-generation/scripts/png-qa.mjs +431 -0
  312. package/skills/fec-image-generation/scripts/tech-diagram-render.mjs +1397 -0
  313. package/skills/fec-implement-from-design/SKILL.md +81 -74
  314. package/skills/fec-implement-from-design/references/design-plan-template.md +16 -16
  315. package/skills/fec-legacy-to-modern-migration/SKILL.md +29 -173
  316. package/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +110 -0
  317. package/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +37 -37
  318. package/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +48 -0
  319. package/skills/fec-legacy-web-standard/SKILL.md +17 -17
  320. package/skills/fec-legacy-web-standard/references/legacy-patterns.md +16 -16
  321. package/skills/fec-list-virtualization/SKILL.md +16 -16
  322. package/skills/fec-list-virtualization/references/virtualization-patterns.md +31 -31
  323. package/skills/fec-monorepo-project-standard/SKILL.md +52 -52
  324. package/skills/fec-motion-interaction/SKILL.md +51 -44
  325. package/skills/fec-motion-interaction/references/motion-patterns.md +11 -11
  326. package/skills/fec-nextjs-project-standard/SKILL.md +64 -58
  327. package/skills/fec-nuxt-project-standard/SKILL.md +57 -57
  328. package/skills/fec-performance-optimization/SKILL.md +54 -50
  329. package/skills/fec-performance-optimization/references/framework-performance-patterns.md +38 -0
  330. package/skills/fec-performance-optimization/references/report-template.md +34 -28
  331. package/skills/fec-pwa-implementation/SKILL.md +17 -17
  332. package/skills/fec-pwa-implementation/references/manifest-and-icons.md +12 -12
  333. package/skills/fec-pwa-implementation/references/service-worker-workbox.md +13 -13
  334. package/skills/fec-react-project-standard/SKILL.md +72 -64
  335. package/skills/fec-react-project-standard/references/react-performance-patterns.md +35 -0
  336. package/skills/fec-react-project-standard/references/react-project-structure.md +197 -0
  337. package/skills/fec-react-project-standard/references/react-quality-patterns.md +131 -0
  338. package/skills/fec-react-project-standard/references/react-runtime-patterns.md +293 -0
  339. package/skills/fec-refactor-clean/SKILL.md +30 -30
  340. package/skills/fec-refactor-clean/references/report-template.md +23 -23
  341. package/skills/fec-responsive-layout/SKILL.md +17 -17
  342. package/skills/fec-responsive-layout/references/responsive-layout-patterns.md +39 -28
  343. package/skills/fec-route-protection/SKILL.md +26 -26
  344. package/skills/fec-security-review/SKILL.md +20 -20
  345. package/skills/fec-security-review/references/report-template.md +12 -12
  346. package/skills/fec-security-review/references/security-checklist.md +27 -27
  347. package/skills/fec-source-driven-development/SKILL.md +66 -40
  348. package/skills/fec-state-management/SKILL.md +34 -34
  349. package/skills/fec-state-management/references/state-patterns.md +19 -19
  350. package/skills/fec-storybook-component-doc/SKILL.md +19 -19
  351. package/skills/fec-storybook-component-doc/references/story-patterns.md +12 -12
  352. package/skills/fec-svg-animation/SKILL.md +32 -32
  353. package/skills/fec-tailwind-design-system/SKILL.md +17 -17
  354. package/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +36 -32
  355. package/skills/fec-tdd-workflow/SKILL.md +28 -28
  356. package/skills/fec-testing-strategy/SKILL.md +29 -29
  357. package/skills/fec-typescript-project-standard/SKILL.md +54 -0
  358. package/skills/fec-typescript-project-standard/references/type-safety-patterns.md +102 -0
  359. package/skills/fec-typescript-project-standard/references/type-safety.md +148 -0
  360. package/skills/fec-ui-design/SKILL.md +90 -72
  361. package/skills/fec-ui-design/data/style-archetypes.json +40 -0
  362. package/skills/fec-ui-design/data/ux-quality-rules.json +35 -0
  363. package/skills/fec-ui-design/references/design-intelligence.md +81 -21
  364. package/skills/fec-ui-design/references/master-page-overrides.md +15 -15
  365. package/skills/fec-ui-design/references/pre-delivery-checklist.md +38 -32
  366. package/skills/fec-ui-design/scripts/design-system.mjs +119 -1
  367. package/skills/fec-validation-fix/SKILL.md +26 -26
  368. package/skills/fec-validation-fix/references/report-template.md +25 -25
  369. package/skills/fec-vite-project-standard/SKILL.md +39 -39
  370. package/skills/fec-vue3-project-standard/SKILL.md +39 -30
  371. package/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +163 -0
  372. package/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +13 -0
  373. package/skills/fec-vue3-project-standard/references/vue3-project-structure.md +177 -0
  374. package/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +216 -0
  375. package/skills/fec-web-video-presentation/SKILL.md +61 -0
  376. package/skills/fec-web-video-presentation/data/starter-themes.json +59 -0
  377. package/skills/fec-web-video-presentation/references/chapter-craft.md +37 -0
  378. package/skills/fec-web-video-presentation/references/content-plan.md +38 -0
  379. package/skills/fec-web-video-presentation/references/recording-and-audio.md +33 -0
  380. package/skills/fec-web-video-presentation/references/theme-system.md +36 -0
  381. package/skills/fec-web-video-presentation/scripts/create-video-presentation.mjs +430 -0
  382. package/skills/fec-web-workers/SKILL.md +16 -16
  383. package/skills/fec-web-workers/references/advanced-workers.md +13 -13
  384. package/skills/fec-web-workers/references/basic-worker.md +8 -8
  385. package/skills/metadata.json +402 -220
  386. package/skills/relations.json +120 -25
  387. package/templates/claude/CLAUDE.md +60 -60
  388. package/templates/codex/AGENTS.md +76 -76
  389. package/templates/codex/config.toml +4 -4
  390. package/templates/openclaw/AGENTS.md +68 -68
  391. package/templates/openclaw/OPENCLAW-CONFIG.md +8 -8
  392. package/templates/shared/rules/fec-agent-workflow.md +40 -40
  393. package/templates/shared/rules/fec-api-layer.md +52 -52
  394. package/templates/shared/rules/fec-ci-cd.md +29 -117
  395. package/templates/shared/rules/fec-code-comments.md +22 -22
  396. package/templates/shared/rules/fec-design-system.md +65 -241
  397. package/templates/shared/rules/fec-error-handling.md +41 -185
  398. package/templates/shared/rules/fec-git-conventions.md +42 -42
  399. package/templates/shared/rules/fec-i18n.md +48 -96
  400. package/templates/shared/rules/fec-naming-conventions.md +91 -91
  401. package/templates/shared/rules/fec-performance.md +78 -78
  402. package/templates/shared/rules/fec-react.md +58 -58
  403. package/templates/shared/rules/fec-refactoring.md +34 -30
  404. package/templates/shared/rules/fec-rendering-patterns.md +40 -183
  405. package/templates/shared/rules/fec-responsive-design.md +37 -214
  406. package/templates/shared/rules/fec-source-driven-development.md +22 -22
  407. package/templates/shared/rules/fec-state-management.md +45 -148
  408. package/templates/shared/rules/fec-testing.md +64 -64
  409. package/templates/shared/rules/fec-typescript.md +98 -341
  410. package/templates/shared/rules/fec-vue.md +42 -42
  411. package/templates/shared/rules/fec-working-modes.md +34 -34
  412. package/skills/fec-e2e-testing/references/e2e-advanced.md +0 -176
  413. package/skills/fec-react-project-standard/references/react-project-details.md +0 -642
  414. package/skills/fec-vue3-project-standard/references/vue3-project-details.md +0 -547
@@ -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)});