@djm204/agent-skills 1.0.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 (392) hide show
  1. package/README.md +597 -0
  2. package/bin/cli.js +8 -0
  3. package/package.json +55 -0
  4. package/src/index.js +1817 -0
  5. package/src/index.test.js +1264 -0
  6. package/templates/_shared/code-quality.mdc +52 -0
  7. package/templates/_shared/communication.mdc +43 -0
  8. package/templates/_shared/core-principles.mdc +67 -0
  9. package/templates/_shared/git-workflow.mdc +48 -0
  10. package/templates/_shared/security-fundamentals.mdc +41 -0
  11. package/templates/agents/utility-agent/.cursor/rules/action-control.mdc +71 -0
  12. package/templates/agents/utility-agent/.cursor/rules/context-management.mdc +61 -0
  13. package/templates/agents/utility-agent/.cursor/rules/hallucination-prevention.mdc +58 -0
  14. package/templates/agents/utility-agent/.cursor/rules/overview.mdc +34 -0
  15. package/templates/agents/utility-agent/.cursor/rules/token-optimization.mdc +71 -0
  16. package/templates/agents/utility-agent/CLAUDE.md +513 -0
  17. package/templates/business/market-intelligence/.cursor/rules/data-sources.mdc +62 -0
  18. package/templates/business/market-intelligence/.cursor/rules/overview.mdc +55 -0
  19. package/templates/business/market-intelligence/.cursor/rules/reporting.mdc +59 -0
  20. package/templates/business/market-intelligence/.cursor/rules/risk-signals.mdc +63 -0
  21. package/templates/business/market-intelligence/.cursor/rules/sentiment-analysis.mdc +70 -0
  22. package/templates/business/market-intelligence/.cursor/rules/trend-detection.mdc +72 -0
  23. package/templates/business/market-intelligence/CLAUDE.md +371 -0
  24. package/templates/business/marketing-expert/.cursor/rules/brand-strategy.mdc +74 -0
  25. package/templates/business/marketing-expert/.cursor/rules/campaign-planning.mdc +60 -0
  26. package/templates/business/marketing-expert/.cursor/rules/growth-frameworks.mdc +69 -0
  27. package/templates/business/marketing-expert/.cursor/rules/market-analysis.mdc +70 -0
  28. package/templates/business/marketing-expert/.cursor/rules/marketing-analytics.mdc +71 -0
  29. package/templates/business/marketing-expert/.cursor/rules/overview.mdc +56 -0
  30. package/templates/business/marketing-expert/CLAUDE.md +567 -0
  31. package/templates/business/predictive-maintenance/.cursor/rules/alerting.mdc +56 -0
  32. package/templates/business/predictive-maintenance/.cursor/rules/asset-lifecycle.mdc +71 -0
  33. package/templates/business/predictive-maintenance/.cursor/rules/failure-prediction.mdc +65 -0
  34. package/templates/business/predictive-maintenance/.cursor/rules/maintenance-scheduling.mdc +61 -0
  35. package/templates/business/predictive-maintenance/.cursor/rules/overview.mdc +55 -0
  36. package/templates/business/predictive-maintenance/.cursor/rules/sensor-analytics.mdc +66 -0
  37. package/templates/business/predictive-maintenance/CLAUDE.md +529 -0
  38. package/templates/business/product-manager/.cursor/rules/communication.mdc +77 -0
  39. package/templates/business/product-manager/.cursor/rules/discovery.mdc +79 -0
  40. package/templates/business/product-manager/.cursor/rules/metrics.mdc +75 -0
  41. package/templates/business/product-manager/.cursor/rules/overview.mdc +47 -0
  42. package/templates/business/product-manager/.cursor/rules/prioritization.mdc +66 -0
  43. package/templates/business/product-manager/.cursor/rules/requirements.mdc +79 -0
  44. package/templates/business/product-manager/CLAUDE.md +593 -0
  45. package/templates/business/project-manager/.cursor/rules/overview.mdc +53 -0
  46. package/templates/business/project-manager/.cursor/rules/reporting.mdc +68 -0
  47. package/templates/business/project-manager/.cursor/rules/risk-management.mdc +71 -0
  48. package/templates/business/project-manager/.cursor/rules/scheduling.mdc +67 -0
  49. package/templates/business/project-manager/.cursor/rules/scope-management.mdc +66 -0
  50. package/templates/business/project-manager/.cursor/rules/stakeholder-management.mdc +70 -0
  51. package/templates/business/project-manager/CLAUDE.md +540 -0
  52. package/templates/business/regulatory-sentinel/.cursor/rules/compliance-tracking.mdc +74 -0
  53. package/templates/business/regulatory-sentinel/.cursor/rules/impact-assessment.mdc +62 -0
  54. package/templates/business/regulatory-sentinel/.cursor/rules/monitoring.mdc +67 -0
  55. package/templates/business/regulatory-sentinel/.cursor/rules/overview.mdc +55 -0
  56. package/templates/business/regulatory-sentinel/.cursor/rules/reporting.mdc +61 -0
  57. package/templates/business/regulatory-sentinel/.cursor/rules/risk-classification.mdc +73 -0
  58. package/templates/business/regulatory-sentinel/CLAUDE.md +572 -0
  59. package/templates/business/resource-allocator/.cursor/rules/capacity-modeling.mdc +65 -0
  60. package/templates/business/resource-allocator/.cursor/rules/coordination.mdc +67 -0
  61. package/templates/business/resource-allocator/.cursor/rules/crisis-management.mdc +64 -0
  62. package/templates/business/resource-allocator/.cursor/rules/demand-prediction.mdc +52 -0
  63. package/templates/business/resource-allocator/.cursor/rules/overview.mdc +76 -0
  64. package/templates/business/resource-allocator/.cursor/rules/scheduling.mdc +63 -0
  65. package/templates/business/resource-allocator/CLAUDE.md +525 -0
  66. package/templates/business/strategic-negotiator/.cursor/rules/contract-analysis.mdc +60 -0
  67. package/templates/business/strategic-negotiator/.cursor/rules/deal-structuring.mdc +66 -0
  68. package/templates/business/strategic-negotiator/.cursor/rules/game-theory.mdc +64 -0
  69. package/templates/business/strategic-negotiator/.cursor/rules/overview.mdc +55 -0
  70. package/templates/business/strategic-negotiator/.cursor/rules/preparation.mdc +79 -0
  71. package/templates/business/strategic-negotiator/.cursor/rules/scenario-modeling.mdc +66 -0
  72. package/templates/business/strategic-negotiator/CLAUDE.md +640 -0
  73. package/templates/business/supply-chain/.cursor/rules/cost-modeling.mdc +67 -0
  74. package/templates/business/supply-chain/.cursor/rules/demand-forecasting.mdc +67 -0
  75. package/templates/business/supply-chain/.cursor/rules/inventory-management.mdc +69 -0
  76. package/templates/business/supply-chain/.cursor/rules/logistics.mdc +61 -0
  77. package/templates/business/supply-chain/.cursor/rules/overview.mdc +64 -0
  78. package/templates/business/supply-chain/.cursor/rules/supplier-evaluation.mdc +66 -0
  79. package/templates/business/supply-chain/CLAUDE.md +590 -0
  80. package/templates/business/supply-chain-harmonizer/.cursor/rules/disruption-response.mdc +67 -0
  81. package/templates/business/supply-chain-harmonizer/.cursor/rules/inventory-rebalancing.mdc +63 -0
  82. package/templates/business/supply-chain-harmonizer/.cursor/rules/overview.mdc +65 -0
  83. package/templates/business/supply-chain-harmonizer/.cursor/rules/rerouting.mdc +64 -0
  84. package/templates/business/supply-chain-harmonizer/.cursor/rules/scenario-simulation.mdc +68 -0
  85. package/templates/business/supply-chain-harmonizer/.cursor/rules/stakeholder-notifications.mdc +61 -0
  86. package/templates/business/supply-chain-harmonizer/CLAUDE.md +600 -0
  87. package/templates/creative/brand-guardian/.cursor/rules/brand-voice.mdc +64 -0
  88. package/templates/creative/brand-guardian/.cursor/rules/content-review.mdc +47 -0
  89. package/templates/creative/brand-guardian/.cursor/rules/ethical-guidelines.mdc +47 -0
  90. package/templates/creative/brand-guardian/.cursor/rules/multi-channel.mdc +49 -0
  91. package/templates/creative/brand-guardian/.cursor/rules/overview.mdc +58 -0
  92. package/templates/creative/brand-guardian/.cursor/rules/visual-identity.mdc +64 -0
  93. package/templates/creative/brand-guardian/CLAUDE.md +634 -0
  94. package/templates/creative/content-creation-expert/.cursor/rules/content-strategy.mdc +65 -0
  95. package/templates/creative/content-creation-expert/.cursor/rules/copywriting.mdc +59 -0
  96. package/templates/creative/content-creation-expert/.cursor/rules/editorial-operations.mdc +65 -0
  97. package/templates/creative/content-creation-expert/.cursor/rules/multimedia-production.mdc +64 -0
  98. package/templates/creative/content-creation-expert/.cursor/rules/overview.mdc +58 -0
  99. package/templates/creative/content-creation-expert/.cursor/rules/seo-content.mdc +75 -0
  100. package/templates/creative/content-creation-expert/CLAUDE.md +568 -0
  101. package/templates/creative/narrative-architect/.cursor/rules/collaboration.mdc +62 -0
  102. package/templates/creative/narrative-architect/.cursor/rules/continuity-tracking.mdc +56 -0
  103. package/templates/creative/narrative-architect/.cursor/rules/overview.mdc +68 -0
  104. package/templates/creative/narrative-architect/.cursor/rules/story-bible.mdc +77 -0
  105. package/templates/creative/narrative-architect/.cursor/rules/timeline-management.mdc +60 -0
  106. package/templates/creative/narrative-architect/.cursor/rules/world-building.mdc +78 -0
  107. package/templates/creative/narrative-architect/CLAUDE.md +737 -0
  108. package/templates/creative/social-media-expert/.cursor/rules/audience-growth.mdc +62 -0
  109. package/templates/creative/social-media-expert/.cursor/rules/community-management.mdc +67 -0
  110. package/templates/creative/social-media-expert/.cursor/rules/content-strategy.mdc +60 -0
  111. package/templates/creative/social-media-expert/.cursor/rules/overview.mdc +48 -0
  112. package/templates/creative/social-media-expert/.cursor/rules/platform-strategy.mdc +64 -0
  113. package/templates/creative/social-media-expert/.cursor/rules/social-analytics.mdc +64 -0
  114. package/templates/creative/social-media-expert/CLAUDE.md +624 -0
  115. package/templates/creative/trend-forecaster/.cursor/rules/cultural-analysis.mdc +59 -0
  116. package/templates/creative/trend-forecaster/.cursor/rules/forecasting-methods.mdc +63 -0
  117. package/templates/creative/trend-forecaster/.cursor/rules/overview.mdc +58 -0
  118. package/templates/creative/trend-forecaster/.cursor/rules/reporting.mdc +61 -0
  119. package/templates/creative/trend-forecaster/.cursor/rules/signal-analysis.mdc +74 -0
  120. package/templates/creative/trend-forecaster/.cursor/rules/trend-lifecycle.mdc +75 -0
  121. package/templates/creative/trend-forecaster/CLAUDE.md +717 -0
  122. package/templates/creative/ux-designer/.cursor/rules/accessibility.mdc +69 -0
  123. package/templates/creative/ux-designer/.cursor/rules/emotional-design.mdc +59 -0
  124. package/templates/creative/ux-designer/.cursor/rules/handoff.mdc +73 -0
  125. package/templates/creative/ux-designer/.cursor/rules/information-architecture.mdc +62 -0
  126. package/templates/creative/ux-designer/.cursor/rules/interaction-design.mdc +66 -0
  127. package/templates/creative/ux-designer/.cursor/rules/overview.mdc +61 -0
  128. package/templates/creative/ux-designer/.cursor/rules/research.mdc +61 -0
  129. package/templates/creative/ux-designer/.cursor/rules/visual-design.mdc +68 -0
  130. package/templates/creative/ux-designer/CLAUDE.md +124 -0
  131. package/templates/dogfood/project-overview.mdc +12 -0
  132. package/templates/dogfood/project-structure.mdc +82 -0
  133. package/templates/dogfood/rules-creation-best-practices.mdc +45 -0
  134. package/templates/education/educator/.cursor/rules/accessibility.mdc +67 -0
  135. package/templates/education/educator/.cursor/rules/assessment.mdc +68 -0
  136. package/templates/education/educator/.cursor/rules/curriculum.mdc +57 -0
  137. package/templates/education/educator/.cursor/rules/engagement.mdc +65 -0
  138. package/templates/education/educator/.cursor/rules/instructional-design.mdc +69 -0
  139. package/templates/education/educator/.cursor/rules/overview.mdc +57 -0
  140. package/templates/education/educator/.cursor/rules/retention.mdc +64 -0
  141. package/templates/education/educator/CLAUDE.md +338 -0
  142. package/templates/engineering/blockchain/.cursor/rules/defi-patterns.mdc +48 -0
  143. package/templates/engineering/blockchain/.cursor/rules/gas-optimization.mdc +77 -0
  144. package/templates/engineering/blockchain/.cursor/rules/overview.mdc +41 -0
  145. package/templates/engineering/blockchain/.cursor/rules/security.mdc +61 -0
  146. package/templates/engineering/blockchain/.cursor/rules/smart-contracts.mdc +64 -0
  147. package/templates/engineering/blockchain/.cursor/rules/testing.mdc +77 -0
  148. package/templates/engineering/blockchain/.cursor/rules/web3-integration.mdc +47 -0
  149. package/templates/engineering/blockchain/CLAUDE.md +389 -0
  150. package/templates/engineering/cli-tools/.cursor/rules/architecture.mdc +76 -0
  151. package/templates/engineering/cli-tools/.cursor/rules/arguments.mdc +65 -0
  152. package/templates/engineering/cli-tools/.cursor/rules/distribution.mdc +40 -0
  153. package/templates/engineering/cli-tools/.cursor/rules/error-handling.mdc +67 -0
  154. package/templates/engineering/cli-tools/.cursor/rules/overview.mdc +58 -0
  155. package/templates/engineering/cli-tools/.cursor/rules/testing.mdc +42 -0
  156. package/templates/engineering/cli-tools/.cursor/rules/user-experience.mdc +43 -0
  157. package/templates/engineering/cli-tools/CLAUDE.md +356 -0
  158. package/templates/engineering/data-engineering/.cursor/rules/data-modeling.mdc +71 -0
  159. package/templates/engineering/data-engineering/.cursor/rules/data-quality.mdc +78 -0
  160. package/templates/engineering/data-engineering/.cursor/rules/overview.mdc +49 -0
  161. package/templates/engineering/data-engineering/.cursor/rules/performance.mdc +71 -0
  162. package/templates/engineering/data-engineering/.cursor/rules/pipeline-design.mdc +79 -0
  163. package/templates/engineering/data-engineering/.cursor/rules/security.mdc +79 -0
  164. package/templates/engineering/data-engineering/.cursor/rules/testing.mdc +75 -0
  165. package/templates/engineering/data-engineering/CLAUDE.md +974 -0
  166. package/templates/engineering/devops-sre/.cursor/rules/capacity-planning.mdc +49 -0
  167. package/templates/engineering/devops-sre/.cursor/rules/change-management.mdc +51 -0
  168. package/templates/engineering/devops-sre/.cursor/rules/chaos-engineering.mdc +50 -0
  169. package/templates/engineering/devops-sre/.cursor/rules/disaster-recovery.mdc +54 -0
  170. package/templates/engineering/devops-sre/.cursor/rules/incident-management.mdc +56 -0
  171. package/templates/engineering/devops-sre/.cursor/rules/observability.mdc +50 -0
  172. package/templates/engineering/devops-sre/.cursor/rules/overview.mdc +76 -0
  173. package/templates/engineering/devops-sre/.cursor/rules/postmortems.mdc +49 -0
  174. package/templates/engineering/devops-sre/.cursor/rules/runbooks.mdc +49 -0
  175. package/templates/engineering/devops-sre/.cursor/rules/slo-sli.mdc +46 -0
  176. package/templates/engineering/devops-sre/.cursor/rules/toil-reduction.mdc +52 -0
  177. package/templates/engineering/devops-sre/CLAUDE.md +1007 -0
  178. package/templates/engineering/fullstack/.cursor/rules/api-contracts.mdc +79 -0
  179. package/templates/engineering/fullstack/.cursor/rules/architecture.mdc +79 -0
  180. package/templates/engineering/fullstack/.cursor/rules/overview.mdc +61 -0
  181. package/templates/engineering/fullstack/.cursor/rules/shared-types.mdc +77 -0
  182. package/templates/engineering/fullstack/.cursor/rules/testing.mdc +72 -0
  183. package/templates/engineering/fullstack/CLAUDE.md +349 -0
  184. package/templates/engineering/ml-ai/.cursor/rules/data-engineering.mdc +71 -0
  185. package/templates/engineering/ml-ai/.cursor/rules/deployment.mdc +43 -0
  186. package/templates/engineering/ml-ai/.cursor/rules/model-development.mdc +44 -0
  187. package/templates/engineering/ml-ai/.cursor/rules/monitoring.mdc +45 -0
  188. package/templates/engineering/ml-ai/.cursor/rules/overview.mdc +42 -0
  189. package/templates/engineering/ml-ai/.cursor/rules/security.mdc +51 -0
  190. package/templates/engineering/ml-ai/.cursor/rules/testing.mdc +44 -0
  191. package/templates/engineering/ml-ai/CLAUDE.md +1136 -0
  192. package/templates/engineering/mobile/.cursor/rules/navigation.mdc +75 -0
  193. package/templates/engineering/mobile/.cursor/rules/offline-first.mdc +68 -0
  194. package/templates/engineering/mobile/.cursor/rules/overview.mdc +76 -0
  195. package/templates/engineering/mobile/.cursor/rules/performance.mdc +78 -0
  196. package/templates/engineering/mobile/.cursor/rules/testing.mdc +77 -0
  197. package/templates/engineering/mobile/CLAUDE.md +233 -0
  198. package/templates/engineering/platform-engineering/.cursor/rules/ci-cd.mdc +51 -0
  199. package/templates/engineering/platform-engineering/.cursor/rules/developer-experience.mdc +48 -0
  200. package/templates/engineering/platform-engineering/.cursor/rules/infrastructure-as-code.mdc +62 -0
  201. package/templates/engineering/platform-engineering/.cursor/rules/kubernetes.mdc +51 -0
  202. package/templates/engineering/platform-engineering/.cursor/rules/observability.mdc +52 -0
  203. package/templates/engineering/platform-engineering/.cursor/rules/overview.mdc +44 -0
  204. package/templates/engineering/platform-engineering/.cursor/rules/security.mdc +74 -0
  205. package/templates/engineering/platform-engineering/.cursor/rules/testing.mdc +59 -0
  206. package/templates/engineering/platform-engineering/CLAUDE.md +850 -0
  207. package/templates/engineering/qa-engineering/.cursor/rules/automation.mdc +71 -0
  208. package/templates/engineering/qa-engineering/.cursor/rules/metrics.mdc +68 -0
  209. package/templates/engineering/qa-engineering/.cursor/rules/overview.mdc +45 -0
  210. package/templates/engineering/qa-engineering/.cursor/rules/quality-gates.mdc +54 -0
  211. package/templates/engineering/qa-engineering/.cursor/rules/test-design.mdc +59 -0
  212. package/templates/engineering/qa-engineering/.cursor/rules/test-strategy.mdc +62 -0
  213. package/templates/engineering/qa-engineering/CLAUDE.md +726 -0
  214. package/templates/engineering/testing/.cursor/rules/advanced-techniques.mdc +44 -0
  215. package/templates/engineering/testing/.cursor/rules/ci-cd-integration.mdc +43 -0
  216. package/templates/engineering/testing/.cursor/rules/overview.mdc +61 -0
  217. package/templates/engineering/testing/.cursor/rules/performance-testing.mdc +39 -0
  218. package/templates/engineering/testing/.cursor/rules/quality-metrics.mdc +74 -0
  219. package/templates/engineering/testing/.cursor/rules/reliability.mdc +39 -0
  220. package/templates/engineering/testing/.cursor/rules/tdd-methodology.mdc +52 -0
  221. package/templates/engineering/testing/.cursor/rules/test-data.mdc +46 -0
  222. package/templates/engineering/testing/.cursor/rules/test-design.mdc +45 -0
  223. package/templates/engineering/testing/.cursor/rules/test-types.mdc +71 -0
  224. package/templates/engineering/testing/CLAUDE.md +1134 -0
  225. package/templates/engineering/unity-dev-expert/.cursor/rules/csharp-architecture.mdc +61 -0
  226. package/templates/engineering/unity-dev-expert/.cursor/rules/multiplayer-networking.mdc +67 -0
  227. package/templates/engineering/unity-dev-expert/.cursor/rules/overview.mdc +56 -0
  228. package/templates/engineering/unity-dev-expert/.cursor/rules/performance-optimization.mdc +76 -0
  229. package/templates/engineering/unity-dev-expert/.cursor/rules/physics-rendering.mdc +59 -0
  230. package/templates/engineering/unity-dev-expert/.cursor/rules/ui-systems.mdc +59 -0
  231. package/templates/engineering/unity-dev-expert/CLAUDE.md +534 -0
  232. package/templates/engineering/web-backend/.cursor/rules/api-design.mdc +64 -0
  233. package/templates/engineering/web-backend/.cursor/rules/authentication.mdc +69 -0
  234. package/templates/engineering/web-backend/.cursor/rules/database-patterns.mdc +73 -0
  235. package/templates/engineering/web-backend/.cursor/rules/error-handling.mdc +66 -0
  236. package/templates/engineering/web-backend/.cursor/rules/overview.mdc +74 -0
  237. package/templates/engineering/web-backend/.cursor/rules/security.mdc +60 -0
  238. package/templates/engineering/web-backend/.cursor/rules/testing.mdc +74 -0
  239. package/templates/engineering/web-backend/CLAUDE.md +366 -0
  240. package/templates/engineering/web-frontend/.cursor/rules/accessibility.mdc +75 -0
  241. package/templates/engineering/web-frontend/.cursor/rules/component-patterns.mdc +76 -0
  242. package/templates/engineering/web-frontend/.cursor/rules/overview.mdc +77 -0
  243. package/templates/engineering/web-frontend/.cursor/rules/performance.mdc +73 -0
  244. package/templates/engineering/web-frontend/.cursor/rules/state-management.mdc +71 -0
  245. package/templates/engineering/web-frontend/.cursor/rules/styling.mdc +69 -0
  246. package/templates/engineering/web-frontend/.cursor/rules/testing.mdc +75 -0
  247. package/templates/engineering/web-frontend/CLAUDE.md +399 -0
  248. package/templates/languages/cpp-expert/.cursor/rules/concurrency.mdc +68 -0
  249. package/templates/languages/cpp-expert/.cursor/rules/error-handling.mdc +65 -0
  250. package/templates/languages/cpp-expert/.cursor/rules/memory-and-ownership.mdc +68 -0
  251. package/templates/languages/cpp-expert/.cursor/rules/modern-cpp.mdc +75 -0
  252. package/templates/languages/cpp-expert/.cursor/rules/overview.mdc +37 -0
  253. package/templates/languages/cpp-expert/.cursor/rules/performance.mdc +74 -0
  254. package/templates/languages/cpp-expert/.cursor/rules/testing.mdc +70 -0
  255. package/templates/languages/cpp-expert/.cursor/rules/tooling.mdc +77 -0
  256. package/templates/languages/cpp-expert/CLAUDE.md +242 -0
  257. package/templates/languages/csharp-expert/.cursor/rules/aspnet-core.mdc +78 -0
  258. package/templates/languages/csharp-expert/.cursor/rules/async-patterns.mdc +71 -0
  259. package/templates/languages/csharp-expert/.cursor/rules/dependency-injection.mdc +76 -0
  260. package/templates/languages/csharp-expert/.cursor/rules/error-handling.mdc +65 -0
  261. package/templates/languages/csharp-expert/.cursor/rules/language-features.mdc +74 -0
  262. package/templates/languages/csharp-expert/.cursor/rules/overview.mdc +47 -0
  263. package/templates/languages/csharp-expert/.cursor/rules/performance.mdc +66 -0
  264. package/templates/languages/csharp-expert/.cursor/rules/testing.mdc +78 -0
  265. package/templates/languages/csharp-expert/.cursor/rules/tooling.mdc +78 -0
  266. package/templates/languages/csharp-expert/CLAUDE.md +360 -0
  267. package/templates/languages/golang-expert/.cursor/rules/concurrency.mdc +79 -0
  268. package/templates/languages/golang-expert/.cursor/rules/error-handling.mdc +77 -0
  269. package/templates/languages/golang-expert/.cursor/rules/interfaces-and-types.mdc +77 -0
  270. package/templates/languages/golang-expert/.cursor/rules/overview.mdc +74 -0
  271. package/templates/languages/golang-expert/.cursor/rules/performance.mdc +76 -0
  272. package/templates/languages/golang-expert/.cursor/rules/production-patterns.mdc +76 -0
  273. package/templates/languages/golang-expert/.cursor/rules/stdlib-and-tooling.mdc +68 -0
  274. package/templates/languages/golang-expert/.cursor/rules/testing.mdc +77 -0
  275. package/templates/languages/golang-expert/CLAUDE.md +361 -0
  276. package/templates/languages/java-expert/.cursor/rules/concurrency.mdc +69 -0
  277. package/templates/languages/java-expert/.cursor/rules/error-handling.mdc +70 -0
  278. package/templates/languages/java-expert/.cursor/rules/modern-java.mdc +74 -0
  279. package/templates/languages/java-expert/.cursor/rules/overview.mdc +42 -0
  280. package/templates/languages/java-expert/.cursor/rules/performance.mdc +69 -0
  281. package/templates/languages/java-expert/.cursor/rules/persistence.mdc +74 -0
  282. package/templates/languages/java-expert/.cursor/rules/spring-boot.mdc +73 -0
  283. package/templates/languages/java-expert/.cursor/rules/testing.mdc +79 -0
  284. package/templates/languages/java-expert/.cursor/rules/tooling.mdc +76 -0
  285. package/templates/languages/java-expert/CLAUDE.md +325 -0
  286. package/templates/languages/javascript-expert/.cursor/rules/language-deep-dive.mdc +74 -0
  287. package/templates/languages/javascript-expert/.cursor/rules/node-patterns.mdc +77 -0
  288. package/templates/languages/javascript-expert/.cursor/rules/overview.mdc +66 -0
  289. package/templates/languages/javascript-expert/.cursor/rules/performance.mdc +64 -0
  290. package/templates/languages/javascript-expert/.cursor/rules/react-patterns.mdc +70 -0
  291. package/templates/languages/javascript-expert/.cursor/rules/testing.mdc +76 -0
  292. package/templates/languages/javascript-expert/.cursor/rules/tooling.mdc +72 -0
  293. package/templates/languages/javascript-expert/.cursor/rules/typescript-deep-dive.mdc +77 -0
  294. package/templates/languages/javascript-expert/CLAUDE.md +479 -0
  295. package/templates/languages/kotlin-expert/.cursor/rules/coroutines.mdc +75 -0
  296. package/templates/languages/kotlin-expert/.cursor/rules/error-handling.mdc +69 -0
  297. package/templates/languages/kotlin-expert/.cursor/rules/frameworks.mdc +76 -0
  298. package/templates/languages/kotlin-expert/.cursor/rules/language-features.mdc +78 -0
  299. package/templates/languages/kotlin-expert/.cursor/rules/overview.mdc +38 -0
  300. package/templates/languages/kotlin-expert/.cursor/rules/performance.mdc +73 -0
  301. package/templates/languages/kotlin-expert/.cursor/rules/testing.mdc +70 -0
  302. package/templates/languages/kotlin-expert/.cursor/rules/tooling.mdc +67 -0
  303. package/templates/languages/kotlin-expert/CLAUDE.md +276 -0
  304. package/templates/languages/python-expert/.cursor/rules/async-python.mdc +71 -0
  305. package/templates/languages/python-expert/.cursor/rules/overview.mdc +76 -0
  306. package/templates/languages/python-expert/.cursor/rules/patterns-and-idioms.mdc +77 -0
  307. package/templates/languages/python-expert/.cursor/rules/performance.mdc +74 -0
  308. package/templates/languages/python-expert/.cursor/rules/testing.mdc +77 -0
  309. package/templates/languages/python-expert/.cursor/rules/tooling.mdc +77 -0
  310. package/templates/languages/python-expert/.cursor/rules/type-system.mdc +77 -0
  311. package/templates/languages/python-expert/.cursor/rules/web-and-apis.mdc +76 -0
  312. package/templates/languages/python-expert/CLAUDE.md +264 -0
  313. package/templates/languages/ruby-expert/.cursor/rules/concurrency-and-threading.mdc +65 -0
  314. package/templates/languages/ruby-expert/.cursor/rules/error-handling.mdc +69 -0
  315. package/templates/languages/ruby-expert/.cursor/rules/idioms-and-style.mdc +76 -0
  316. package/templates/languages/ruby-expert/.cursor/rules/overview.mdc +60 -0
  317. package/templates/languages/ruby-expert/.cursor/rules/performance.mdc +68 -0
  318. package/templates/languages/ruby-expert/.cursor/rules/rails-and-frameworks.mdc +60 -0
  319. package/templates/languages/ruby-expert/.cursor/rules/testing.mdc +56 -0
  320. package/templates/languages/ruby-expert/.cursor/rules/tooling.mdc +52 -0
  321. package/templates/languages/ruby-expert/CLAUDE.md +102 -0
  322. package/templates/languages/rust-expert/.cursor/rules/concurrency.mdc +69 -0
  323. package/templates/languages/rust-expert/.cursor/rules/ecosystem-and-tooling.mdc +76 -0
  324. package/templates/languages/rust-expert/.cursor/rules/error-handling.mdc +76 -0
  325. package/templates/languages/rust-expert/.cursor/rules/overview.mdc +62 -0
  326. package/templates/languages/rust-expert/.cursor/rules/ownership-and-borrowing.mdc +70 -0
  327. package/templates/languages/rust-expert/.cursor/rules/performance-and-unsafe.mdc +70 -0
  328. package/templates/languages/rust-expert/.cursor/rules/testing.mdc +73 -0
  329. package/templates/languages/rust-expert/.cursor/rules/traits-and-generics.mdc +76 -0
  330. package/templates/languages/rust-expert/CLAUDE.md +283 -0
  331. package/templates/languages/swift-expert/.cursor/rules/concurrency.mdc +77 -0
  332. package/templates/languages/swift-expert/.cursor/rules/error-handling.mdc +76 -0
  333. package/templates/languages/swift-expert/.cursor/rules/language-features.mdc +78 -0
  334. package/templates/languages/swift-expert/.cursor/rules/overview.mdc +46 -0
  335. package/templates/languages/swift-expert/.cursor/rules/performance.mdc +69 -0
  336. package/templates/languages/swift-expert/.cursor/rules/swiftui.mdc +77 -0
  337. package/templates/languages/swift-expert/.cursor/rules/testing.mdc +75 -0
  338. package/templates/languages/swift-expert/.cursor/rules/tooling.mdc +77 -0
  339. package/templates/languages/swift-expert/CLAUDE.md +275 -0
  340. package/templates/professional/documentation/.cursor/rules/adr.mdc +65 -0
  341. package/templates/professional/documentation/.cursor/rules/api-documentation.mdc +64 -0
  342. package/templates/professional/documentation/.cursor/rules/code-comments.mdc +75 -0
  343. package/templates/professional/documentation/.cursor/rules/maintenance.mdc +58 -0
  344. package/templates/professional/documentation/.cursor/rules/overview.mdc +48 -0
  345. package/templates/professional/documentation/.cursor/rules/readme-standards.mdc +70 -0
  346. package/templates/professional/documentation/CLAUDE.md +120 -0
  347. package/templates/professional/executive-assistant/.cursor/rules/calendar.mdc +51 -0
  348. package/templates/professional/executive-assistant/.cursor/rules/confidentiality.mdc +53 -0
  349. package/templates/professional/executive-assistant/.cursor/rules/email.mdc +49 -0
  350. package/templates/professional/executive-assistant/.cursor/rules/meetings.mdc +39 -0
  351. package/templates/professional/executive-assistant/.cursor/rules/overview.mdc +42 -0
  352. package/templates/professional/executive-assistant/.cursor/rules/prioritization.mdc +48 -0
  353. package/templates/professional/executive-assistant/.cursor/rules/stakeholder-management.mdc +50 -0
  354. package/templates/professional/executive-assistant/.cursor/rules/travel.mdc +43 -0
  355. package/templates/professional/executive-assistant/CLAUDE.md +620 -0
  356. package/templates/professional/grant-writer/.cursor/rules/budgets.mdc +55 -0
  357. package/templates/professional/grant-writer/.cursor/rules/compliance.mdc +47 -0
  358. package/templates/professional/grant-writer/.cursor/rules/funding-research.mdc +47 -0
  359. package/templates/professional/grant-writer/.cursor/rules/narrative.mdc +58 -0
  360. package/templates/professional/grant-writer/.cursor/rules/overview.mdc +68 -0
  361. package/templates/professional/grant-writer/.cursor/rules/post-award.mdc +59 -0
  362. package/templates/professional/grant-writer/.cursor/rules/review-criteria.mdc +51 -0
  363. package/templates/professional/grant-writer/.cursor/rules/sustainability.mdc +48 -0
  364. package/templates/professional/grant-writer/CLAUDE.md +577 -0
  365. package/templates/professional/knowledge-synthesis/.cursor/rules/document-management.mdc +51 -0
  366. package/templates/professional/knowledge-synthesis/.cursor/rules/knowledge-graphs.mdc +63 -0
  367. package/templates/professional/knowledge-synthesis/.cursor/rules/overview.mdc +74 -0
  368. package/templates/professional/knowledge-synthesis/.cursor/rules/research-workflow.mdc +50 -0
  369. package/templates/professional/knowledge-synthesis/.cursor/rules/search-retrieval.mdc +62 -0
  370. package/templates/professional/knowledge-synthesis/.cursor/rules/summarization.mdc +61 -0
  371. package/templates/professional/knowledge-synthesis/CLAUDE.md +593 -0
  372. package/templates/professional/life-logistics/.cursor/rules/financial-optimization.mdc +78 -0
  373. package/templates/professional/life-logistics/.cursor/rules/negotiation.mdc +68 -0
  374. package/templates/professional/life-logistics/.cursor/rules/overview.mdc +75 -0
  375. package/templates/professional/life-logistics/.cursor/rules/research-methodology.mdc +76 -0
  376. package/templates/professional/life-logistics/.cursor/rules/scheduling.mdc +68 -0
  377. package/templates/professional/life-logistics/.cursor/rules/task-management.mdc +47 -0
  378. package/templates/professional/life-logistics/CLAUDE.md +601 -0
  379. package/templates/professional/research-assistant/.cursor/rules/citation-attribution.mdc +61 -0
  380. package/templates/professional/research-assistant/.cursor/rules/information-synthesis.mdc +65 -0
  381. package/templates/professional/research-assistant/.cursor/rules/overview.mdc +56 -0
  382. package/templates/professional/research-assistant/.cursor/rules/research-methodologies.mdc +54 -0
  383. package/templates/professional/research-assistant/.cursor/rules/search-strategies.mdc +57 -0
  384. package/templates/professional/research-assistant/.cursor/rules/source-evaluation.mdc +59 -0
  385. package/templates/professional/research-assistant/CLAUDE.md +318 -0
  386. package/templates/professional/wellness-orchestrator/.cursor/rules/adaptive-planning.mdc +69 -0
  387. package/templates/professional/wellness-orchestrator/.cursor/rules/data-integration.mdc +60 -0
  388. package/templates/professional/wellness-orchestrator/.cursor/rules/fitness-programming.mdc +66 -0
  389. package/templates/professional/wellness-orchestrator/.cursor/rules/nutrition-planning.mdc +57 -0
  390. package/templates/professional/wellness-orchestrator/.cursor/rules/overview.mdc +76 -0
  391. package/templates/professional/wellness-orchestrator/.cursor/rules/sleep-optimization.mdc +68 -0
  392. package/templates/professional/wellness-orchestrator/CLAUDE.md +573 -0
package/src/index.js ADDED
@@ -0,0 +1,1817 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { exec } from 'child_process';
5
+ import { promisify } from 'util';
6
+
7
+ const execAsync = promisify(exec);
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+ const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
12
+
13
+ // Cursor rules directory paths
14
+ const CURSOR_RULES_DIR = '.cursor/rules'; // New path (Cursor IDE)
15
+ const LEGACY_CURSORRULES_DIR = '.cursorrules'; // Deprecated path
16
+
17
+ // Read package.json for version info
18
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
19
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
20
+ const PACKAGE_NAME = packageJson.name;
21
+ const CURRENT_VERSION = packageJson.version;
22
+ const REPO_URL = 'https://github.com/djm204/agent-skills';
23
+ const CHANGELOG_URL = `${REPO_URL}/releases/tag/${PACKAGE_NAME}-v${CURRENT_VERSION}`;
24
+
25
+ // Template categories (storage-only, not exposed to CLI users)
26
+ const CATEGORIES = [
27
+ 'engineering',
28
+ 'languages',
29
+ 'creative',
30
+ 'business',
31
+ 'professional',
32
+ 'education',
33
+ 'agents',
34
+ ];
35
+
36
+ // Available templates
37
+ const TEMPLATES = {
38
+ 'brand-guardian': {
39
+ category: 'creative',
40
+ description: 'Brand voice enforcement, visual identity compliance, content review workflows, and multi-channel consistency',
41
+ rules: ['brand-voice.mdc', 'content-review.mdc', 'ethical-guidelines.mdc', 'multi-channel.mdc', 'overview.mdc', 'visual-identity.mdc']
42
+ },
43
+ 'blockchain': {
44
+ category: 'engineering',
45
+ description: 'Smart contracts, DeFi protocols, and Web3 applications (Solidity, Foundry, Viem)',
46
+ rules: ['defi-patterns.mdc', 'gas-optimization.mdc', 'overview.mdc', 'security.mdc', 'smart-contracts.mdc', 'testing.mdc', 'web3-integration.mdc']
47
+ },
48
+ 'cpp-expert': {
49
+ category: 'languages',
50
+ description: 'Principal-level C++ engineering (modern C++, RAII, concurrency, templates, performance)',
51
+ rules: ['concurrency.mdc', 'error-handling.mdc', 'memory-and-ownership.mdc', 'modern-cpp.mdc', 'overview.mdc', 'performance.mdc', 'testing.mdc', 'tooling.mdc']
52
+ },
53
+ 'csharp-expert': {
54
+ category: 'languages',
55
+ description: 'Principal-level C# engineering (async, DI, EF Core, ASP.NET Core, testing)',
56
+ rules: ['aspnet-core.mdc', 'async-patterns.mdc', 'dependency-injection.mdc', 'error-handling.mdc', 'language-features.mdc', 'overview.mdc', 'performance.mdc', 'testing.mdc', 'tooling.mdc']
57
+ },
58
+ 'content-creation-expert': {
59
+ category: 'creative',
60
+ description: 'Content strategy, long-form writing, copywriting, SEO content, multimedia production, and editorial operations',
61
+ rules: ['content-strategy.mdc', 'copywriting.mdc', 'editorial-operations.mdc', 'multimedia-production.mdc', 'overview.mdc', 'seo-content.mdc']
62
+ },
63
+ 'cli-tools': {
64
+ category: 'engineering',
65
+ description: 'Command-line applications and developer tools (Cobra, Commander, Click)',
66
+ rules: ['architecture.mdc', 'arguments.mdc', 'distribution.mdc', 'error-handling.mdc', 'overview.mdc', 'testing.mdc', 'user-experience.mdc']
67
+ },
68
+ 'data-engineering': {
69
+ category: 'engineering',
70
+ description: 'Data platforms and pipelines (ETL, data modeling, data quality)',
71
+ rules: ['data-modeling.mdc', 'data-quality.mdc', 'overview.mdc', 'performance.mdc', 'pipeline-design.mdc', 'security.mdc', 'testing.mdc']
72
+ },
73
+ 'devops-sre': {
74
+ category: 'engineering',
75
+ description: 'DevOps and SRE practices (incident management, observability, SLOs, chaos engineering)',
76
+ rules: ['capacity-planning.mdc', 'change-management.mdc', 'chaos-engineering.mdc', 'disaster-recovery.mdc', 'incident-management.mdc', 'observability.mdc', 'overview.mdc', 'postmortems.mdc', 'runbooks.mdc', 'slo-sli.mdc', 'toil-reduction.mdc']
77
+ },
78
+ 'documentation': {
79
+ category: 'professional',
80
+ description: 'Technical documentation standards (READMEs, API docs, ADRs, code comments)',
81
+ rules: ['adr.mdc', 'api-documentation.mdc', 'code-comments.mdc', 'maintenance.mdc', 'overview.mdc', 'readme-standards.mdc']
82
+ },
83
+ 'educator': {
84
+ category: 'education',
85
+ description: 'World-class pedagogy with evidence-based teaching, learning retention, gamification, and assessment design',
86
+ rules: ['accessibility.mdc', 'assessment.mdc', 'curriculum.mdc', 'engagement.mdc', 'instructional-design.mdc', 'overview.mdc', 'retention.mdc']
87
+ },
88
+ 'executive-assistant': {
89
+ category: 'professional',
90
+ description: 'Executive support with calendar optimization, communication management, meeting coordination, and priority triage',
91
+ rules: ['calendar.mdc', 'confidentiality.mdc', 'email.mdc', 'meetings.mdc', 'overview.mdc', 'prioritization.mdc', 'stakeholder-management.mdc', 'travel.mdc']
92
+ },
93
+ 'fullstack': {
94
+ category: 'engineering',
95
+ description: 'Full-stack web applications (Next.js, Nuxt, SvelteKit, Remix)',
96
+ rules: ['api-contracts.mdc', 'architecture.mdc', 'overview.mdc', 'shared-types.mdc', 'testing.mdc']
97
+ },
98
+ 'grant-writer': {
99
+ category: 'professional',
100
+ description: 'Grant writing with proposal development, budget justification, compliance management, and post-award stewardship',
101
+ rules: ['budgets.mdc', 'compliance.mdc', 'funding-research.mdc', 'narrative.mdc', 'overview.mdc', 'post-award.mdc', 'review-criteria.mdc', 'sustainability.mdc']
102
+ },
103
+ 'golang-expert': {
104
+ category: 'languages',
105
+ description: 'Principal-level Go engineering (concurrency, stdlib, production patterns, testing)',
106
+ rules: ['concurrency.mdc', 'error-handling.mdc', 'interfaces-and-types.mdc', 'overview.mdc', 'performance.mdc', 'production-patterns.mdc', 'stdlib-and-tooling.mdc', 'testing.mdc']
107
+ },
108
+ 'java-expert': {
109
+ category: 'languages',
110
+ description: 'Principal-level Java engineering (JVM, Spring Boot, concurrency, JPA, testing)',
111
+ rules: ['concurrency.mdc', 'error-handling.mdc', 'modern-java.mdc', 'overview.mdc', 'performance.mdc', 'persistence.mdc', 'spring-boot.mdc', 'testing.mdc', 'tooling.mdc']
112
+ },
113
+ 'javascript-expert': {
114
+ category: 'languages',
115
+ description: 'Principal-level JavaScript & TypeScript engineering (Node.js, React, type system, testing)',
116
+ rules: ['language-deep-dive.mdc', 'node-patterns.mdc', 'overview.mdc', 'performance.mdc', 'react-patterns.mdc', 'testing.mdc', 'tooling.mdc', 'typescript-deep-dive.mdc']
117
+ },
118
+ 'knowledge-synthesis': {
119
+ category: 'professional',
120
+ description: 'Knowledge management with document ingestion, knowledge graphs, search/retrieval, summarization, and research workflows',
121
+ rules: ['document-management.mdc', 'knowledge-graphs.mdc', 'overview.mdc', 'research-workflow.mdc', 'search-retrieval.mdc', 'summarization.mdc']
122
+ },
123
+ 'kotlin-expert': {
124
+ category: 'languages',
125
+ description: 'Principal-level Kotlin engineering (coroutines, multiplatform, Ktor, Spring Boot, testing)',
126
+ rules: ['coroutines.mdc', 'error-handling.mdc', 'frameworks.mdc', 'language-features.mdc', 'overview.mdc', 'performance.mdc', 'testing.mdc', 'tooling.mdc']
127
+ },
128
+ 'life-logistics': {
129
+ category: 'professional',
130
+ description: 'Personal logistics optimization including scheduling, bill negotiation, insurance comparison, and vendor research',
131
+ rules: ['financial-optimization.mdc', 'negotiation.mdc', 'overview.mdc', 'research-methodology.mdc', 'scheduling.mdc', 'task-management.mdc']
132
+ },
133
+ 'market-intelligence': {
134
+ category: 'business',
135
+ description: 'Market intelligence with data source aggregation, sentiment analysis, trend detection, and risk signal monitoring',
136
+ rules: ['data-sources.mdc', 'overview.mdc', 'reporting.mdc', 'risk-signals.mdc', 'sentiment-analysis.mdc', 'trend-detection.mdc']
137
+ },
138
+ 'marketing-expert': {
139
+ category: 'business',
140
+ description: 'Principal marketing strategy covering brand positioning, campaign planning, market analysis, analytics, and growth frameworks',
141
+ rules: ['brand-strategy.mdc', 'campaign-planning.mdc', 'growth-frameworks.mdc', 'market-analysis.mdc', 'marketing-analytics.mdc', 'overview.mdc']
142
+ },
143
+ 'ml-ai': {
144
+ category: 'engineering',
145
+ description: 'Machine learning and AI systems (model development, deployment, monitoring)',
146
+ rules: ['data-engineering.mdc', 'deployment.mdc', 'model-development.mdc', 'monitoring.mdc', 'overview.mdc', 'security.mdc', 'testing.mdc']
147
+ },
148
+ 'narrative-architect': {
149
+ category: 'creative',
150
+ description: 'World-building, continuity tracking, timeline management, story bible creation, and collaborative storytelling',
151
+ rules: ['collaboration.mdc', 'continuity-tracking.mdc', 'overview.mdc', 'story-bible.mdc', 'timeline-management.mdc', 'world-building.mdc']
152
+ },
153
+ 'mobile': {
154
+ category: 'engineering',
155
+ description: 'Mobile applications (React Native, Flutter, native iOS/Android)',
156
+ rules: ['navigation.mdc', 'offline-first.mdc', 'overview.mdc', 'performance.mdc', 'testing.mdc']
157
+ },
158
+ 'predictive-maintenance': {
159
+ category: 'business',
160
+ description: 'Industrial sensor monitoring, failure prediction, maintenance scheduling, asset lifecycle management, and alerting',
161
+ rules: ['alerting.mdc', 'asset-lifecycle.mdc', 'failure-prediction.mdc', 'maintenance-scheduling.mdc', 'overview.mdc', 'sensor-analytics.mdc']
162
+ },
163
+ 'platform-engineering': {
164
+ category: 'engineering',
165
+ description: 'Internal developer platforms, infrastructure automation, and reliability engineering',
166
+ rules: ['ci-cd.mdc', 'developer-experience.mdc', 'infrastructure-as-code.mdc', 'kubernetes.mdc', 'observability.mdc', 'overview.mdc', 'security.mdc', 'testing.mdc']
167
+ },
168
+ 'product-manager': {
169
+ category: 'business',
170
+ description: 'Product management with customer-centric discovery, prioritization, and execution',
171
+ rules: ['communication.mdc', 'discovery.mdc', 'metrics.mdc', 'overview.mdc', 'prioritization.mdc', 'requirements.mdc']
172
+ },
173
+ 'regulatory-sentinel': {
174
+ category: 'business',
175
+ description: 'Regulatory compliance tracking, impact assessment, monitoring, risk classification, and compliance reporting',
176
+ rules: ['compliance-tracking.mdc', 'impact-assessment.mdc', 'monitoring.mdc', 'overview.mdc', 'reporting.mdc', 'risk-classification.mdc']
177
+ },
178
+ 'research-assistant': {
179
+ category: 'professional',
180
+ description: 'World-class research with advanced search strategies, source evaluation, OSINT techniques, and rigorous synthesis',
181
+ rules: ['citation-attribution.mdc', 'information-synthesis.mdc', 'overview.mdc', 'research-methodologies.mdc', 'search-strategies.mdc', 'source-evaluation.mdc']
182
+ },
183
+ 'resource-allocator': {
184
+ category: 'business',
185
+ description: 'Resource allocation with demand prediction, scheduling optimization, crisis management, and capacity modeling',
186
+ rules: ['capacity-modeling.mdc', 'coordination.mdc', 'crisis-management.mdc', 'demand-prediction.mdc', 'overview.mdc', 'scheduling.mdc']
187
+ },
188
+ 'project-manager': {
189
+ category: 'business',
190
+ description: 'Project management with WBS planning, risk management, status reporting, and change control',
191
+ rules: ['overview.mdc', 'reporting.mdc', 'risk-management.mdc', 'scheduling.mdc', 'scope-management.mdc', 'stakeholder-management.mdc']
192
+ },
193
+ 'python-expert': {
194
+ category: 'languages',
195
+ description: 'Principal-level Python engineering (type system, async, testing, FastAPI, Django)',
196
+ rules: ['async-python.mdc', 'overview.mdc', 'patterns-and-idioms.mdc', 'performance.mdc', 'testing.mdc', 'tooling.mdc', 'type-system.mdc', 'web-and-apis.mdc']
197
+ },
198
+ 'qa-engineering': {
199
+ category: 'engineering',
200
+ description: 'Quality assurance programs for confident, rapid software delivery',
201
+ rules: ['automation.mdc', 'metrics.mdc', 'overview.mdc', 'quality-gates.mdc', 'test-design.mdc', 'test-strategy.mdc']
202
+ },
203
+ 'social-media-expert': {
204
+ category: 'creative',
205
+ description: 'Social media strategy covering platform optimization, content planning, audience growth, community management, and analytics',
206
+ rules: ['audience-growth.mdc', 'community-management.mdc', 'content-strategy.mdc', 'overview.mdc', 'platform-strategy.mdc', 'social-analytics.mdc']
207
+ },
208
+ 'strategic-negotiator': {
209
+ category: 'business',
210
+ description: 'Negotiation strategy with game theory, deal structuring, scenario modeling, preparation frameworks, and contract analysis',
211
+ rules: ['contract-analysis.mdc', 'deal-structuring.mdc', 'game-theory.mdc', 'overview.mdc', 'preparation.mdc', 'scenario-modeling.mdc']
212
+ },
213
+ 'supply-chain-harmonizer': {
214
+ category: 'business',
215
+ description: 'Supply chain optimization with disruption response, rerouting, inventory rebalancing, and scenario simulation',
216
+ rules: ['disruption-response.mdc', 'inventory-rebalancing.mdc', 'overview.mdc', 'rerouting.mdc', 'scenario-simulation.mdc', 'stakeholder-notifications.mdc']
217
+ },
218
+ 'ruby-expert': {
219
+ category: 'languages',
220
+ description: 'Principal-level Ruby engineering (idioms, concurrency, Rails, performance, testing)',
221
+ rules: ['concurrency-and-threading.mdc', 'error-handling.mdc', 'idioms-and-style.mdc', 'overview.mdc', 'performance.mdc', 'rails-and-frameworks.mdc', 'testing.mdc', 'tooling.mdc']
222
+ },
223
+ 'rust-expert': {
224
+ category: 'languages',
225
+ description: 'Principal-level Rust engineering (ownership, concurrency, unsafe, traits, async)',
226
+ rules: ['concurrency.mdc', 'ecosystem-and-tooling.mdc', 'error-handling.mdc', 'overview.mdc', 'ownership-and-borrowing.mdc', 'performance-and-unsafe.mdc', 'testing.mdc', 'traits-and-generics.mdc']
227
+ },
228
+ 'supply-chain': {
229
+ category: 'business',
230
+ description: 'Supply chain management with inventory optimization, demand forecasting, supplier evaluation, and logistics',
231
+ rules: ['cost-modeling.mdc', 'demand-forecasting.mdc', 'inventory-management.mdc', 'logistics.mdc', 'overview.mdc', 'supplier-evaluation.mdc']
232
+ },
233
+ 'swift-expert': {
234
+ category: 'languages',
235
+ description: 'Principal-level Swift engineering (concurrency, SwiftUI, protocols, testing, Apple platforms)',
236
+ rules: ['concurrency.mdc', 'error-handling.mdc', 'language-features.mdc', 'overview.mdc', 'performance.mdc', 'swiftui.mdc', 'testing.mdc', 'tooling.mdc']
237
+ },
238
+ 'trend-forecaster': {
239
+ category: 'creative',
240
+ description: 'Trend analysis with signal detection, cultural analysis, trend lifecycle modeling, forecasting methods, and reporting',
241
+ rules: ['cultural-analysis.mdc', 'forecasting-methods.mdc', 'overview.mdc', 'reporting.mdc', 'signal-analysis.mdc', 'trend-lifecycle.mdc']
242
+ },
243
+ 'testing': {
244
+ category: 'engineering',
245
+ description: 'Comprehensive testing practices (TDD, test design, CI/CD integration, performance testing)',
246
+ rules: ['advanced-techniques.mdc', 'ci-cd-integration.mdc', 'overview.mdc', 'performance-testing.mdc', 'quality-metrics.mdc', 'reliability.mdc', 'tdd-methodology.mdc', 'test-data.mdc', 'test-design.mdc', 'test-types.mdc']
247
+ },
248
+ 'unity-dev-expert': {
249
+ category: 'engineering',
250
+ description: 'Unity game development with C# architecture, ECS/DOTS, physics/rendering, UI systems, multiplayer networking, and performance optimization',
251
+ rules: ['csharp-architecture.mdc', 'multiplayer-networking.mdc', 'overview.mdc', 'performance-optimization.mdc', 'physics-rendering.mdc', 'ui-systems.mdc']
252
+ },
253
+ 'utility-agent': {
254
+ category: 'agents',
255
+ description: 'AI agent utilities with context management and hallucination prevention',
256
+ rules: ['action-control.mdc', 'context-management.mdc', 'hallucination-prevention.mdc', 'overview.mdc', 'token-optimization.mdc']
257
+ },
258
+ 'ux-designer': {
259
+ category: 'creative',
260
+ description: 'Principal-level UX design with user research, interaction design, design systems, accessibility, and emotional design',
261
+ rules: ['accessibility.mdc', 'emotional-design.mdc', 'handoff.mdc', 'information-architecture.mdc', 'interaction-design.mdc', 'overview.mdc', 'research.mdc', 'visual-design.mdc']
262
+ },
263
+ 'wellness-orchestrator': {
264
+ category: 'professional',
265
+ description: 'Unified wellness planning across fitness, nutrition, sleep, and mental wellness with wearable data integration',
266
+ rules: ['adaptive-planning.mdc', 'data-integration.mdc', 'fitness-programming.mdc', 'nutrition-planning.mdc', 'overview.mdc', 'sleep-optimization.mdc']
267
+ },
268
+ 'web-backend': {
269
+ category: 'engineering',
270
+ description: 'Backend APIs and services (REST, GraphQL, microservices)',
271
+ rules: ['api-design.mdc', 'authentication.mdc', 'database-patterns.mdc', 'error-handling.mdc', 'overview.mdc', 'security.mdc', 'testing.mdc']
272
+ },
273
+ 'web-frontend': {
274
+ category: 'engineering',
275
+ description: 'Frontend web applications (SPAs, SSR, static sites, PWAs)',
276
+ rules: ['accessibility.mdc', 'component-patterns.mdc', 'overview.mdc', 'performance.mdc', 'state-management.mdc', 'styling.mdc', 'testing.mdc']
277
+ }
278
+ };
279
+
280
+ // Shorthand aliases for language expert templates
281
+ const TEMPLATE_ALIASES = {
282
+ 'js': 'javascript-expert',
283
+ 'javascript': 'javascript-expert',
284
+ 'ts': 'javascript-expert',
285
+ 'typescript': 'javascript-expert',
286
+ 'go': 'golang-expert',
287
+ 'golang': 'golang-expert',
288
+ 'py': 'python-expert',
289
+ 'python': 'python-expert',
290
+ 'rs': 'rust-expert',
291
+ 'rust': 'rust-expert',
292
+ 'ruby': 'ruby-expert',
293
+ 'rb': 'ruby-expert',
294
+ 'swift': 'swift-expert',
295
+ 'kotlin': 'kotlin-expert',
296
+ 'kt': 'kotlin-expert',
297
+ 'java': 'java-expert',
298
+ 'cpp': 'cpp-expert',
299
+ 'csharp': 'csharp-expert',
300
+ 'cs': 'csharp-expert',
301
+ 'unity': 'unity-dev-expert',
302
+ 'teach': 'educator',
303
+ 'teacher': 'educator',
304
+ 'marketing': 'marketing-expert',
305
+ 'social-media': 'social-media-expert',
306
+ 'content-creation': 'content-creation-expert',
307
+ 'ux': 'ux-designer',
308
+ 'uxd': 'ux-designer',
309
+ 'design': 'ux-designer',
310
+ 'designer': 'ux-designer',
311
+ 'research': 'research-assistant',
312
+ 'researcher': 'research-assistant',
313
+ // Engineering
314
+ 'frontend': 'web-frontend',
315
+ 'fe': 'web-frontend',
316
+ 'backend': 'web-backend',
317
+ 'api': 'web-backend',
318
+ 'devops': 'devops-sre',
319
+ 'sre': 'devops-sre',
320
+ 'cli': 'cli-tools',
321
+ 'data': 'data-engineering',
322
+ 'dataeng': 'data-engineering',
323
+ 'ml': 'ml-ai',
324
+ 'ai': 'ml-ai',
325
+ 'qa': 'qa-engineering',
326
+ 'test': 'testing',
327
+ 'chain': 'blockchain',
328
+ 'web3': 'blockchain',
329
+ 'platform': 'platform-engineering',
330
+ 'platform-eng': 'platform-engineering',
331
+ // Professional
332
+ 'docs': 'documentation',
333
+ 'grants': 'grant-writer',
334
+ 'exec': 'executive-assistant',
335
+ 'ea': 'executive-assistant',
336
+ 'knowledge': 'knowledge-synthesis',
337
+ 'wellness': 'wellness-orchestrator',
338
+ 'life': 'life-logistics',
339
+ 'logistics': 'life-logistics',
340
+ // Business
341
+ 'product': 'product-manager',
342
+ 'project': 'project-manager',
343
+ 'compliance': 'regulatory-sentinel',
344
+ 'regulatory': 'regulatory-sentinel',
345
+ 'allocator': 'resource-allocator',
346
+ 'resources': 'resource-allocator',
347
+ 'market-intel': 'market-intelligence',
348
+ 'supplychain': 'supply-chain',
349
+ 'harmonizer': 'supply-chain-harmonizer',
350
+ 'negotiator': 'strategic-negotiator',
351
+ 'predictive': 'predictive-maintenance',
352
+ // Creative
353
+ 'brand': 'brand-guardian',
354
+ 'narrative': 'narrative-architect',
355
+ 'story': 'narrative-architect',
356
+ 'trends': 'trend-forecaster',
357
+ // Agents
358
+ 'agent': 'utility-agent',
359
+ 'utility': 'utility-agent',
360
+ };
361
+
362
+ /**
363
+ * Resolve a template alias to its canonical name
364
+ * @param {string} name - Template name or alias
365
+ * @returns {string} Canonical template name
366
+ */
367
+ function resolveTemplateAlias(name) {
368
+ return TEMPLATE_ALIASES[name] || name;
369
+ }
370
+
371
+ /**
372
+ * Get the source path for a template's rule files
373
+ * @param {string} template - Template name
374
+ * @param {string} rule - Rule filename
375
+ * @returns {string} Full path to the rule file in templates/<category>/<template>/.cursor/rules/
376
+ */
377
+ function getTemplateRulePath(template, rule) {
378
+ const { category } = TEMPLATES[template];
379
+ return path.join(TEMPLATES_DIR, category, template, '.cursor', 'rules', rule);
380
+ }
381
+
382
+ const SHARED_RULES = [
383
+ 'code-quality.mdc',
384
+ 'communication.mdc',
385
+ 'core-principles.mdc',
386
+ 'git-workflow.mdc',
387
+ 'security-fundamentals.mdc'
388
+ ];
389
+
390
+ /**
391
+ * Extract the description field from a .mdc file's YAML front matter
392
+ * Falls back to the first heading or the filename.
393
+ * @param {string} filePath - Full path to the .mdc file
394
+ * @returns {string} Description text
395
+ */
396
+ function extractDescription(filePath) {
397
+ try {
398
+ const content = fs.readFileSync(filePath, 'utf8');
399
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
400
+ if (fmMatch) {
401
+ const descMatch = fmMatch[1].match(/description:\s*(.+)/);
402
+ if (descMatch) return descMatch[1].trim();
403
+ }
404
+ const headingMatch = content.match(/^#\s+(.+)/m);
405
+ return headingMatch ? headingMatch[1].trim() : path.basename(filePath, '.mdc');
406
+ } catch {
407
+ return path.basename(filePath, '.mdc');
408
+ }
409
+ }
410
+
411
+ // Supported IDEs/tools
412
+ const SUPPORTED_IDES = ['cursor', 'claude', 'codex'];
413
+ const DEFAULT_IDES = ['cursor', 'claude', 'codex']; // Default: install for all IDEs
414
+
415
+ // Colors
416
+ const colors = {
417
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
418
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
419
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
420
+ blue: (s) => `\x1b[34m${s}\x1b[0m`,
421
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
422
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
423
+ };
424
+
425
+ /**
426
+ * Compare two semver version strings
427
+ * @returns {number} -1 if a < b, 0 if a === b, 1 if a > b
428
+ */
429
+ function compareVersions(a, b) {
430
+ const partsA = a.split('.').map(Number);
431
+ const partsB = b.split('.').map(Number);
432
+
433
+ for (let i = 0; i < 3; i++) {
434
+ const numA = partsA[i] || 0;
435
+ const numB = partsB[i] || 0;
436
+ if (numA < numB) return -1;
437
+ if (numA > numB) return 1;
438
+ }
439
+ return 0;
440
+ }
441
+
442
+ /**
443
+ * Check npm for the latest version and notify if update available
444
+ * Fails silently on network errors
445
+ */
446
+ async function checkForUpdates() {
447
+ try {
448
+ const { stdout } = await execAsync(`npm view ${PACKAGE_NAME} version`, {
449
+ timeout: 5000, // 5 second timeout
450
+ });
451
+ const latestVersion = stdout.trim();
452
+
453
+ if (compareVersions(CURRENT_VERSION, latestVersion) < 0) {
454
+ console.log(colors.cyan(`
455
+ ┌────────────────────────────────────────────────────────────┐
456
+ │ Update available: ${CURRENT_VERSION} → ${latestVersion} │
457
+ │ Run: npx ${PACKAGE_NAME}@latest │
458
+ └────────────────────────────────────────────────────────────┘
459
+ `));
460
+ }
461
+ } catch {
462
+ // Silently ignore network errors or timeouts
463
+ }
464
+ }
465
+
466
+ function printBanner() {
467
+ console.log(colors.blue(`
468
+ ╔═══════════════════════════════════════════════════════════╗
469
+ ║ Agent Skills Installer ║
470
+ ╚═══════════════════════════════════════════════════════════╝
471
+ `));
472
+ }
473
+
474
+ function printHelp() {
475
+ console.log(`${colors.yellow('Usage:')}
476
+ npx @djm204/agent-skills <templates...> [options]
477
+ npx @djm204/agent-skills --remove <templates...> [options]
478
+ npx @djm204/agent-skills --reset [options]
479
+
480
+ ${colors.yellow('Options:')}
481
+ --ide=<name> Install for specific IDE (cursor, claude, codex)
482
+ Can be specified multiple times: --ide=cursor --ide=claude
483
+ Default: all (cursor, claude, codex)
484
+ --list, -l List available templates
485
+ --help, -h Show this help message
486
+ --version, -v Show version number
487
+ --dry-run Show what would be changed
488
+ --force, -f Overwrite/remove even if files were modified
489
+ --yes, -y Skip confirmation prompt (for --remove and --reset)
490
+
491
+ ${colors.yellow('Removal Options:')}
492
+ --remove Remove specified templates (keeps shared rules and other templates)
493
+ --reset Remove ALL installed content (shared rules, templates, generated files)
494
+
495
+ ${colors.yellow('IDE Targets:')}
496
+ cursor .cursor/rules/ directory (Cursor IDE)
497
+ claude CLAUDE.md file (Claude Code, Cursor with Claude)
498
+ codex .github/copilot-instructions.md (GitHub Copilot)
499
+
500
+ ${colors.yellow('Shorthand Aliases:')}
501
+ Languages: js, ts, go, py, rs, ruby, rb, swift, kotlin, kt, java, cpp, csharp, cs
502
+ Engineering: frontend, fe, backend, api, devops, sre, cli, data, ml, ai, qa, test, chain, web3, platform
503
+ Professional: docs, grants, exec, ea, knowledge, wellness, life, logistics, research
504
+ Business: product, project, compliance, allocator, market-intel, supplychain, harmonizer, negotiator
505
+ Creative: ux, design, brand, narrative, story, trends, marketing, social-media, content-creation
506
+ Other: unity, teach, teacher, agent, utility
507
+
508
+ Run --list to see full alias → template mapping.
509
+
510
+ ${colors.yellow('Examples:')}
511
+ npx @djm204/agent-skills js
512
+ npx @djm204/agent-skills web-frontend
513
+ npx @djm204/agent-skills web-frontend --ide=cursor
514
+ npx @djm204/agent-skills web-frontend --ide=claude --ide=codex
515
+ npx @djm204/agent-skills fullstack --ide=codex
516
+ npx @djm204/agent-skills web-backend --force
517
+
518
+ ${colors.yellow('Removal Examples:')}
519
+ npx @djm204/agent-skills --remove web-frontend
520
+ npx @djm204/agent-skills --remove web-frontend web-backend
521
+ npx @djm204/agent-skills --remove web-frontend --ide=cursor
522
+ npx @djm204/agent-skills --reset
523
+ npx @djm204/agent-skills --reset --ide=cursor
524
+ npx @djm204/agent-skills --reset --yes
525
+
526
+ ${colors.dim('Shared rules (code-quality, security, git-workflow, etc.) are always included.')}
527
+ ${colors.dim('Identical files are skipped. Modified files are preserved; ours saved as *-1.mdc.')}
528
+ ${colors.dim('CLAUDE.md: missing sections are intelligently merged (not overwritten).')}
529
+ `);
530
+ }
531
+
532
+ function printTemplates() {
533
+ // Build reverse map: canonical name -> list of aliases
534
+ const aliasesByTemplate = {};
535
+ for (const [alias, canonical] of Object.entries(TEMPLATE_ALIASES)) {
536
+ if (!aliasesByTemplate[canonical]) {
537
+ aliasesByTemplate[canonical] = [];
538
+ }
539
+ aliasesByTemplate[canonical].push(alias);
540
+ }
541
+
542
+ console.log(colors.yellow('Available Templates:\n'));
543
+
544
+ // Group templates by category
545
+ const byCategory = {};
546
+ for (const [name, info] of Object.entries(TEMPLATES)) {
547
+ const cat = info.category;
548
+ if (!byCategory[cat]) byCategory[cat] = [];
549
+ byCategory[cat].push({ name, info });
550
+ }
551
+
552
+ for (const category of CATEGORIES) {
553
+ const templates = byCategory[category];
554
+ if (!templates || templates.length === 0) continue;
555
+ const label = category.charAt(0).toUpperCase() + category.slice(1);
556
+ console.log(colors.blue(` ${label}:`));
557
+ for (const { name, info } of templates) {
558
+ const aliases = aliasesByTemplate[name];
559
+ const aliasSuffix = aliases ? ` ${colors.dim(`(aliases: ${aliases.join(', ')})`)}` : '';
560
+ console.log(` ${colors.green(name)}${aliasSuffix}`);
561
+ console.log(` ${info.description}\n`);
562
+ }
563
+ }
564
+
565
+ console.log(colors.blue('Shared rules (always included):'));
566
+ for (const rule of SHARED_RULES) {
567
+ console.log(` - ${rule.replace('.mdc', '')}`);
568
+ }
569
+ console.log();
570
+ }
571
+
572
+ /**
573
+ * Check if two files have identical content
574
+ */
575
+ function filesMatch(file1, file2) {
576
+ try {
577
+ const content1 = fs.readFileSync(file1, 'utf8');
578
+ const content2 = fs.readFileSync(file2, 'utf8');
579
+ return content1 === content2;
580
+ } catch {
581
+ return false;
582
+ }
583
+ }
584
+
585
+ /**
586
+ * Parse markdown content into sections by ## headings
587
+ * @param {string} content - Markdown content
588
+ * @returns {Array<{heading: string, content: string, signature: string}>}
589
+ */
590
+ function parseMarkdownSections(content) {
591
+ const lines = content.split('\n');
592
+ const sections = [];
593
+ let currentSection = null;
594
+ let preamble = [];
595
+
596
+ for (const line of lines) {
597
+ if (line.startsWith('## ')) {
598
+ // Save previous section
599
+ if (currentSection) {
600
+ currentSection.content = currentSection.lines.join('\n');
601
+ currentSection.signature = generateSectionSignature(currentSection.heading, currentSection.lines);
602
+ delete currentSection.lines;
603
+ sections.push(currentSection);
604
+ }
605
+ // Start new section
606
+ currentSection = {
607
+ heading: line.slice(3).trim(),
608
+ lines: []
609
+ };
610
+ } else if (currentSection) {
611
+ currentSection.lines.push(line);
612
+ } else {
613
+ // Content before first ## heading (preamble)
614
+ preamble.push(line);
615
+ }
616
+ }
617
+
618
+ // Don't forget the last section
619
+ if (currentSection) {
620
+ currentSection.content = currentSection.lines.join('\n');
621
+ currentSection.signature = generateSectionSignature(currentSection.heading, currentSection.lines);
622
+ delete currentSection.lines;
623
+ sections.push(currentSection);
624
+ }
625
+
626
+ return { preamble: preamble.join('\n'), sections };
627
+ }
628
+
629
+ /**
630
+ * Generate a signature for a section based on heading + first meaningful lines
631
+ * Used for matching sections even if heading text differs slightly
632
+ * @param {string} heading
633
+ * @param {string[]} lines
634
+ * @returns {string}
635
+ */
636
+ function generateSectionSignature(heading, lines) {
637
+ // Normalize heading: lowercase, remove special chars, collapse whitespace
638
+ const normalizedHeading = heading.toLowerCase()
639
+ .replace(/[^a-z0-9\s]/g, '')
640
+ .replace(/\s+/g, ' ')
641
+ .trim();
642
+
643
+ // Get first 3 non-empty, non-heading lines for content signature
644
+ const meaningfulLines = lines
645
+ .filter(l => l.trim() && !l.startsWith('#') && !l.startsWith('|') && !l.startsWith('-'))
646
+ .slice(0, 3)
647
+ .map(l => l.toLowerCase().replace(/[^a-z0-9\s]/g, '').replace(/\s+/g, ' ').trim())
648
+ .join(' ');
649
+
650
+ return `${normalizedHeading}::${meaningfulLines.slice(0, 100)}`;
651
+ }
652
+
653
+ /**
654
+ * Find sections from template that are missing in existing content
655
+ * @param {string} existingContent
656
+ * @param {string} templateContent
657
+ * @returns {{missing: Array<{heading: string, content: string}>, matchedCount: number}}
658
+ */
659
+ function findMissingSections(existingContent, templateContent) {
660
+ const existing = parseMarkdownSections(existingContent);
661
+ const template = parseMarkdownSections(templateContent);
662
+
663
+ const existingSignatures = new Set(existing.sections.map(s => s.signature));
664
+ const existingHeadings = new Set(existing.sections.map(s => s.heading.toLowerCase()));
665
+
666
+ const missing = [];
667
+ let matchedCount = 0;
668
+
669
+ for (const section of template.sections) {
670
+ // Check by signature first (heading + content), then by heading alone
671
+ const signatureMatch = existingSignatures.has(section.signature);
672
+ const headingMatch = existingHeadings.has(section.heading.toLowerCase());
673
+
674
+ if (signatureMatch || headingMatch) {
675
+ matchedCount++;
676
+ } else {
677
+ missing.push(section);
678
+ }
679
+ }
680
+
681
+ return { missing, matchedCount };
682
+ }
683
+
684
+ /**
685
+ * Merge template sections into existing content, inserting missing sections in template order
686
+ * @param {string} existingContent
687
+ * @param {string} templateContent
688
+ * @returns {{merged: string, addedSections: string[]}}
689
+ */
690
+ function mergeClaudeContent(existingContent, templateContent) {
691
+ const existing = parseMarkdownSections(existingContent);
692
+ const template = parseMarkdownSections(templateContent);
693
+ const { missing } = findMissingSections(existingContent, templateContent);
694
+
695
+ if (missing.length === 0) {
696
+ return { merged: existingContent, addedSections: [] };
697
+ }
698
+
699
+ // Build a map of existing sections by normalized heading for insertion point lookup
700
+ const existingByHeading = new Map();
701
+ existing.sections.forEach((s, i) => {
702
+ existingByHeading.set(s.heading.toLowerCase(), i);
703
+ });
704
+
705
+ // Find template section order and determine where to insert missing sections
706
+ const templateOrder = template.sections.map(s => s.heading.toLowerCase());
707
+
708
+ // For each missing section, find the best insertion point based on template order
709
+ const insertions = []; // { afterIndex: number, section: section }
710
+
711
+ for (const missingSection of missing) {
712
+ const missingIndex = templateOrder.indexOf(missingSection.heading.toLowerCase());
713
+
714
+ // Find the closest preceding section that exists in the existing content
715
+ let insertAfterIndex = -1; // -1 means insert at beginning (after preamble)
716
+
717
+ for (let i = missingIndex - 1; i >= 0; i--) {
718
+ const precedingHeading = templateOrder[i];
719
+ if (existingByHeading.has(precedingHeading)) {
720
+ insertAfterIndex = existingByHeading.get(precedingHeading);
721
+ break;
722
+ }
723
+ }
724
+
725
+ insertions.push({ afterIndex: insertAfterIndex, section: missingSection });
726
+ }
727
+
728
+ // Sort insertions by afterIndex (descending) so we insert from bottom to top
729
+ // This preserves indices as we insert
730
+ insertions.sort((a, b) => b.afterIndex - a.afterIndex);
731
+
732
+ // Build the merged content
733
+ const mergedSections = [...existing.sections];
734
+ const addedSections = [];
735
+
736
+ for (const { afterIndex, section } of insertions) {
737
+ const insertAt = afterIndex + 1;
738
+ mergedSections.splice(insertAt, 0, section);
739
+ addedSections.push(section.heading);
740
+ }
741
+
742
+ // Reconstruct the markdown
743
+ let merged = existing.preamble;
744
+ if (merged && !merged.endsWith('\n\n')) {
745
+ merged = merged.trimEnd() + '\n\n';
746
+ }
747
+
748
+ for (const section of mergedSections) {
749
+ merged += `## ${section.heading}\n${section.content}\n`;
750
+ }
751
+
752
+ // addedSections is in reverse order due to sorting, reverse it back
753
+ addedSections.reverse();
754
+
755
+ return { merged: merged.trimEnd() + '\n', addedSections };
756
+ }
757
+
758
+ /**
759
+ * Get alternate filename with -1 suffix (e.g., code-quality.mdc -> code-quality-1.mdc)
760
+ */
761
+ function getAlternateFilename(filepath) {
762
+ const dir = path.dirname(filepath);
763
+ const ext = path.extname(filepath);
764
+ const base = path.basename(filepath, ext);
765
+ return path.join(dir, `${base}-1${ext}`);
766
+ }
767
+
768
+ /**
769
+ * Copy file, handling existing files intelligently
770
+ * @returns {{ status: string, destFile: string }}
771
+ * status: 'copied' | 'skipped' | 'renamed' | 'updated'
772
+ * destFile: actual destination path (may differ if renamed)
773
+ */
774
+ function copyFile(src, dest, force = false) {
775
+ const destDir = path.dirname(dest);
776
+ if (!fs.existsSync(destDir)) {
777
+ fs.mkdirSync(destDir, { recursive: true });
778
+ }
779
+
780
+ const exists = fs.existsSync(dest);
781
+
782
+ if (!exists) {
783
+ // File doesn't exist - copy normally
784
+ fs.copyFileSync(src, dest);
785
+ return { status: 'copied', destFile: dest };
786
+ }
787
+
788
+ if (force) {
789
+ // Force mode - overwrite
790
+ fs.copyFileSync(src, dest);
791
+ return { status: 'updated', destFile: dest };
792
+ }
793
+
794
+ // File exists - check if it matches our template
795
+ if (filesMatch(src, dest)) {
796
+ // Same content - skip
797
+ return { status: 'skipped', destFile: dest };
798
+ }
799
+
800
+ // Different content - save ours alongside with -1 suffix
801
+ const altDest = getAlternateFilename(dest);
802
+ fs.copyFileSync(src, altDest);
803
+ return { status: 'renamed', destFile: altDest };
804
+ }
805
+
806
+ function generateClaudeMdContent(installedTemplates) {
807
+ const templateList = installedTemplates
808
+ .map(t => `- **${t}**: ${TEMPLATES[t].description}`)
809
+ .join('\n');
810
+
811
+ const templateRuleTables = installedTemplates.map(template => {
812
+ const rules = TEMPLATES[template].rules
813
+ .map(rule => `| \`${template}-${rule}\` | ${rule.replace('.mdc', '').replace(/-/g, ' ')} guidelines |`)
814
+ .join('\n');
815
+
816
+ return `
817
+ #### ${template.charAt(0).toUpperCase() + template.slice(1)} Rules
818
+
819
+ | Rule | Purpose |
820
+ |------|---------|
821
+ ${rules}`;
822
+ }).join('\n');
823
+
824
+ return `# CLAUDE.md - Development Guide
825
+
826
+ This project uses AI-assisted development. Rules in \`.cursor/rules/\` provide guidance.
827
+
828
+ ## Installed Templates
829
+
830
+ - **Shared** (always included): Core principles, code quality, security, git workflow, communication
831
+ ${templateList}
832
+
833
+ ## Rule Files
834
+
835
+ All rules are in \`.cursor/rules/\`. The AI assistant reads these automatically.
836
+
837
+ #### Shared Rules
838
+
839
+ | Rule | Purpose |
840
+ |------|---------|
841
+ | \`core-principles.mdc\` | Honesty, simplicity, testing requirements |
842
+ | \`code-quality.mdc\` | SOLID, DRY, clean code patterns |
843
+ | \`security-fundamentals.mdc\` | Zero trust, input validation, secrets |
844
+ | \`git-workflow.mdc\` | Commits, branches, PRs, safety |
845
+ | \`communication.mdc\` | Direct, objective, professional |
846
+ ${templateRuleTables}
847
+
848
+ ## Customization
849
+
850
+ - Create new \`.mdc\` files in \`.cursor/rules/\` for project-specific rules
851
+ - Edit existing files directly; changes take effect immediately
852
+ - Re-run to update: \`npx @djm204/agent-skills ${installedTemplates.join(' ')}\`
853
+ `;
854
+ }
855
+
856
+ function generateClaudeMd(targetDir, installedTemplates) {
857
+ const content = generateClaudeMdContent(installedTemplates);
858
+ fs.writeFileSync(path.join(targetDir, 'CLAUDE.md'), content);
859
+ }
860
+
861
+ function generateClaudeMdToPath(targetDir, installedTemplates, destPath) {
862
+ const content = generateClaudeMdContent(installedTemplates);
863
+ fs.writeFileSync(destPath, content);
864
+ }
865
+
866
+ /**
867
+ * Generate content for GitHub Copilot instructions file.
868
+ * Uses description-based summaries instead of full content concatenation
869
+ * to keep the file within context window limits.
870
+ */
871
+ function generateCopilotInstructionsContent(installedTemplates) {
872
+ // Build shared rules table with descriptions from front matter
873
+ const sharedRulesTable = SHARED_RULES.map(rule => {
874
+ const rulePath = path.join(TEMPLATES_DIR, '_shared', rule);
875
+ const desc = extractDescription(rulePath);
876
+ return `| \`${rule}\` | ${desc} |`;
877
+ }).join('\n');
878
+
879
+ // Build template rules tables with descriptions from front matter
880
+ const templateTables = installedTemplates.map(template => {
881
+ const rulesRows = TEMPLATES[template].rules.map(rule => {
882
+ const rulePath = getTemplateRulePath(template, rule);
883
+ const desc = extractDescription(rulePath);
884
+ return `| \`${rule}\` | ${desc} |`;
885
+ }).join('\n');
886
+
887
+ return `### ${template}
888
+
889
+ ${TEMPLATES[template].description}
890
+
891
+ | Rule | Guidance |
892
+ |------|----------|
893
+ ${rulesRows}`;
894
+ }).join('\n\n');
895
+
896
+ return `# Copilot Instructions
897
+
898
+ Guidelines for GitHub Copilot in this project. Full rules are in \`.cursor/rules/\`.
899
+
900
+ ## Project Configuration
901
+
902
+ **Installed Templates:** ${installedTemplates.join(', ')}
903
+
904
+ ## Core Principles
905
+
906
+ - **Honesty over output**: Say what works and what doesn't; admit uncertainty
907
+ - **Security first**: Zero trust, validate all inputs, no secrets in code
908
+ - **Tests required**: No feature ships without tests; test behavior, not implementation
909
+ - **Code quality**: SOLID, DRY, explicit over implicit
910
+
911
+ ## Shared Rules
912
+
913
+ | Rule | Guidance |
914
+ |------|----------|
915
+ ${sharedRulesTable}
916
+
917
+ ## Template Rules
918
+
919
+ ${templateTables}
920
+ `;
921
+ }
922
+
923
+ async function install(targetDir, templates, dryRun = false, force = false, ides = DEFAULT_IDES, skipConfirm = false) {
924
+ const stats = { copied: 0, skipped: 0, updated: 0, renamed: 0 };
925
+ const renamedFiles = [];
926
+ const installedFor = [];
927
+
928
+ console.log(`${colors.blue('Installing to:')} ${targetDir}`);
929
+ console.log(`${colors.blue('Target IDEs:')} ${ides.join(', ')}`);
930
+ if (!force) {
931
+ console.log(colors.dim('(identical files skipped, modified files preserved with ours saved as *-1.mdc)'));
932
+ }
933
+ console.log();
934
+
935
+ // 1. Install .cursor/rules/ for Cursor IDE
936
+ if (ides.includes('cursor')) {
937
+ installedFor.push('cursor');
938
+ const cursorRulesDir = path.join(targetDir, CURSOR_RULES_DIR);
939
+
940
+ if (!dryRun && !fs.existsSync(cursorRulesDir)) {
941
+ fs.mkdirSync(cursorRulesDir, { recursive: true });
942
+ }
943
+
944
+ // Install shared rules
945
+ console.log(colors.green(`► Installing shared rules (${CURSOR_RULES_DIR}/)...`));
946
+ for (const rule of SHARED_RULES) {
947
+ const src = path.join(TEMPLATES_DIR, '_shared', rule);
948
+ const dest = path.join(cursorRulesDir, rule);
949
+
950
+ if (dryRun) {
951
+ const exists = fs.existsSync(dest);
952
+ if (!exists) {
953
+ console.log(` ${colors.dim('[copy]')} ${rule}`);
954
+ } else if (force) {
955
+ console.log(` ${colors.dim('[update]')} ${rule}`);
956
+ } else if (filesMatch(src, dest)) {
957
+ console.log(` ${colors.yellow('[skip]')} ${rule} (identical)`);
958
+ } else {
959
+ const altName = path.basename(getAlternateFilename(dest));
960
+ console.log(` ${colors.blue('[rename]')} ${rule} → ${altName}`);
961
+ }
962
+ } else {
963
+ const result = copyFile(src, dest, force);
964
+ stats[result.status]++;
965
+ if (result.status === 'skipped') {
966
+ console.log(` ${colors.yellow('[skip]')} ${rule} (identical)`);
967
+ } else if (result.status === 'renamed') {
968
+ const altName = path.basename(result.destFile);
969
+ renamedFiles.push({ original: rule, renamed: altName });
970
+ console.log(` ${colors.blue('[rename]')} ${rule} → ${altName}`);
971
+ } else {
972
+ console.log(` ${colors.dim(`[${result.status}]`)} ${rule}`);
973
+ }
974
+ }
975
+ }
976
+ console.log();
977
+
978
+ // Install template-specific rules
979
+ for (const template of templates) {
980
+ console.log(colors.green(`► Installing ${template} template (${CURSOR_RULES_DIR}/)...`));
981
+
982
+ for (const rule of TEMPLATES[template].rules) {
983
+ const src = getTemplateRulePath(template, rule);
984
+ const dest = path.join(cursorRulesDir, `${template}-${rule}`);
985
+ const destName = `${template}-${rule}`;
986
+
987
+ if (dryRun) {
988
+ const exists = fs.existsSync(dest);
989
+ if (!exists) {
990
+ console.log(` ${colors.dim('[copy]')} ${destName}`);
991
+ } else if (force) {
992
+ console.log(` ${colors.dim('[update]')} ${destName}`);
993
+ } else if (filesMatch(src, dest)) {
994
+ console.log(` ${colors.yellow('[skip]')} ${destName} (identical)`);
995
+ } else {
996
+ const altName = path.basename(getAlternateFilename(dest));
997
+ console.log(` ${colors.blue('[rename]')} ${destName} → ${altName}`);
998
+ }
999
+ } else {
1000
+ const result = copyFile(src, dest, force);
1001
+ stats[result.status]++;
1002
+ if (result.status === 'skipped') {
1003
+ console.log(` ${colors.yellow('[skip]')} ${destName} (identical)`);
1004
+ } else if (result.status === 'renamed') {
1005
+ const altName = path.basename(result.destFile);
1006
+ renamedFiles.push({ original: destName, renamed: altName });
1007
+ console.log(` ${colors.blue('[rename]')} ${destName} → ${altName}`);
1008
+ } else {
1009
+ console.log(` ${colors.dim(`[${result.status}]`)} ${destName}`);
1010
+ }
1011
+ }
1012
+ }
1013
+ console.log();
1014
+ }
1015
+
1016
+ // Legacy .cursorrules/ detection and cleanup
1017
+ const legacyDir = path.join(targetDir, LEGACY_CURSORRULES_DIR);
1018
+ if (fs.existsSync(legacyDir)) {
1019
+ console.log(colors.yellow(`⚠ Deprecated ${LEGACY_CURSORRULES_DIR}/ directory detected.`));
1020
+ console.log(colors.yellow(` Cursor now uses ${CURSOR_RULES_DIR}/ for rule files.`));
1021
+ console.log(colors.yellow(` New rules have been installed to ${CURSOR_RULES_DIR}/.`));
1022
+ console.log();
1023
+ console.log(colors.yellow(` Your existing ${LEGACY_CURSORRULES_DIR}/ files are still present.`));
1024
+ console.log(colors.yellow(` Support for ${LEGACY_CURSORRULES_DIR}/ will be removed in a future version.`));
1025
+ console.log();
1026
+
1027
+ if (!dryRun) {
1028
+ const shouldCleanup = skipConfirm || await confirm(
1029
+ colors.yellow(`? Would you like to remove the deprecated ${LEGACY_CURSORRULES_DIR}/ directory?`)
1030
+ );
1031
+
1032
+ if (shouldCleanup) {
1033
+ // Copy legacy rule files to .cursor/rules/ before removing (don't overwrite existing)
1034
+ const legacyEntries = fs.readdirSync(legacyDir, { withFileTypes: true });
1035
+ let copiedCount = 0;
1036
+ for (const entry of legacyEntries) {
1037
+ if (!entry.isFile()) continue;
1038
+ const name = entry.name;
1039
+ const legacyPath = path.join(legacyDir, name);
1040
+ const destPath = path.join(cursorRulesDir, name);
1041
+ if (!fs.existsSync(destPath)) {
1042
+ fs.copyFileSync(legacyPath, destPath);
1043
+ console.log(colors.dim(` ${colors.green('[migrated]')} ${name} → ${CURSOR_RULES_DIR}/`));
1044
+ copiedCount++;
1045
+ }
1046
+ }
1047
+ if (copiedCount > 0) {
1048
+ console.log(colors.green(` ✓ Migrated ${copiedCount} file(s) from ${LEGACY_CURSORRULES_DIR}/ to ${CURSOR_RULES_DIR}/.`));
1049
+ }
1050
+ fs.rmSync(legacyDir, { recursive: true });
1051
+ console.log(colors.green(` ✓ Removed deprecated ${LEGACY_CURSORRULES_DIR}/ directory.`));
1052
+ } else {
1053
+ // Create reference file so Cursor AI knows about legacy rules
1054
+ const noticePath = path.join(cursorRulesDir, 'legacy-cursorrules-notice.md');
1055
+ const noticeContent = `# Legacy Rules Notice
1056
+
1057
+ This project contains additional rule files in the deprecated \`.cursorrules/\` directory
1058
+ at the project root. Those rules are still active and should be consulted alongside the
1059
+ rules in this directory.
1060
+
1061
+ The \`.cursorrules/\` directory will be removed in a future version.
1062
+ To clean up manually, move any custom rules to \`.cursor/rules/\` and delete \`.cursorrules/\`.
1063
+ `;
1064
+ fs.writeFileSync(noticePath, noticeContent);
1065
+ console.log(colors.dim(` Created ${CURSOR_RULES_DIR}/legacy-cursorrules-notice.md as a reference.`));
1066
+ }
1067
+ } else {
1068
+ console.log(colors.dim(' (dry-run: skipping cleanup prompt)'));
1069
+ }
1070
+ console.log();
1071
+ }
1072
+ }
1073
+
1074
+ // 2. Generate CLAUDE.md for Claude Code
1075
+ if (ides.includes('claude')) {
1076
+ installedFor.push('claude');
1077
+ const claudePath = path.join(targetDir, 'CLAUDE.md');
1078
+ const claudeExists = fs.existsSync(claudePath);
1079
+ const templateContent = generateClaudeMdContent(templates);
1080
+
1081
+ console.log(colors.green('► Generating CLAUDE.md (Claude Code)...'));
1082
+ if (dryRun) {
1083
+ if (!claudeExists) {
1084
+ console.log(` ${colors.dim('[copy]')} CLAUDE.md`);
1085
+ } else if (force) {
1086
+ console.log(` ${colors.dim('[update]')} CLAUDE.md`);
1087
+ } else {
1088
+ const existingContent = fs.readFileSync(claudePath, 'utf8');
1089
+ const { missing } = findMissingSections(existingContent, templateContent);
1090
+ if (missing.length === 0) {
1091
+ console.log(` ${colors.yellow('[skip]')} CLAUDE.md (all sections present)`);
1092
+ } else {
1093
+ console.log(` ${colors.blue('[merge]')} CLAUDE.md (would add ${missing.length} section(s))`);
1094
+ for (const section of missing) {
1095
+ console.log(` ${colors.dim('+')} ${section.heading}`);
1096
+ }
1097
+ }
1098
+ }
1099
+ } else if (!claudeExists) {
1100
+ fs.writeFileSync(claudePath, templateContent);
1101
+ console.log(` ${colors.dim('[copied]')} CLAUDE.md`);
1102
+ stats.copied++;
1103
+ } else if (force) {
1104
+ fs.writeFileSync(claudePath, templateContent);
1105
+ console.log(` ${colors.dim('[updated]')} CLAUDE.md`);
1106
+ stats.updated++;
1107
+ } else {
1108
+ const existingContent = fs.readFileSync(claudePath, 'utf8');
1109
+ const { merged, addedSections } = mergeClaudeContent(existingContent, templateContent);
1110
+
1111
+ if (addedSections.length === 0) {
1112
+ console.log(` ${colors.yellow('[skip]')} CLAUDE.md (all sections present)`);
1113
+ stats.skipped++;
1114
+ } else {
1115
+ fs.writeFileSync(claudePath, merged);
1116
+ console.log(` ${colors.blue('[merged]')} CLAUDE.md`);
1117
+ console.log(` ${colors.green('Added sections:')}`);
1118
+ for (const heading of addedSections) {
1119
+ console.log(` ${colors.dim('+')} ${heading}`);
1120
+ }
1121
+ stats.updated++;
1122
+ }
1123
+ }
1124
+ console.log();
1125
+ }
1126
+
1127
+ // 3. Generate .github/copilot-instructions.md for GitHub Copilot (Codex)
1128
+ if (ides.includes('codex')) {
1129
+ installedFor.push('codex');
1130
+ const githubDir = path.join(targetDir, '.github');
1131
+ const copilotPath = path.join(githubDir, 'copilot-instructions.md');
1132
+ const copilotExists = fs.existsSync(copilotPath);
1133
+ const copilotContent = generateCopilotInstructionsContent(templates);
1134
+
1135
+ if (!dryRun && !fs.existsSync(githubDir)) {
1136
+ fs.mkdirSync(githubDir, { recursive: true });
1137
+ }
1138
+
1139
+ console.log(colors.green('► Generating .github/copilot-instructions.md (GitHub Copilot)...'));
1140
+ if (dryRun) {
1141
+ if (!copilotExists) {
1142
+ console.log(` ${colors.dim('[copy]')} .github/copilot-instructions.md`);
1143
+ } else if (force) {
1144
+ console.log(` ${colors.dim('[update]')} .github/copilot-instructions.md`);
1145
+ } else {
1146
+ const existingContent = fs.readFileSync(copilotPath, 'utf8');
1147
+ const { missing } = findMissingSections(existingContent, copilotContent);
1148
+ if (missing.length === 0) {
1149
+ console.log(` ${colors.yellow('[skip]')} .github/copilot-instructions.md (all sections present)`);
1150
+ } else {
1151
+ console.log(` ${colors.blue('[merge]')} .github/copilot-instructions.md (would add ${missing.length} section(s))`);
1152
+ }
1153
+ }
1154
+ } else if (!copilotExists) {
1155
+ fs.writeFileSync(copilotPath, copilotContent);
1156
+ console.log(` ${colors.dim('[copied]')} .github/copilot-instructions.md`);
1157
+ stats.copied++;
1158
+ } else if (force) {
1159
+ fs.writeFileSync(copilotPath, copilotContent);
1160
+ console.log(` ${colors.dim('[updated]')} .github/copilot-instructions.md`);
1161
+ stats.updated++;
1162
+ } else {
1163
+ const existingContent = fs.readFileSync(copilotPath, 'utf8');
1164
+ const { merged, addedSections } = mergeClaudeContent(existingContent, copilotContent);
1165
+
1166
+ if (addedSections.length === 0) {
1167
+ console.log(` ${colors.yellow('[skip]')} .github/copilot-instructions.md (all sections present)`);
1168
+ stats.skipped++;
1169
+ } else {
1170
+ fs.writeFileSync(copilotPath, merged);
1171
+ console.log(` ${colors.blue('[merged]')} .github/copilot-instructions.md`);
1172
+ stats.updated++;
1173
+ }
1174
+ }
1175
+ console.log();
1176
+ }
1177
+
1178
+ // Summary
1179
+ console.log(colors.green('════════════════════════════════════════════════════════════'));
1180
+ console.log(colors.green('✓ Installation complete!\n'));
1181
+
1182
+ console.log(colors.yellow('Summary:'));
1183
+ console.log(` - ${stats.copied} files created`);
1184
+ if (stats.updated > 0) {
1185
+ console.log(` - ${stats.updated} files updated`);
1186
+ }
1187
+ if (stats.skipped > 0) {
1188
+ console.log(` - ${stats.skipped} files skipped (identical to template)`);
1189
+ }
1190
+ if (stats.renamed > 0) {
1191
+ console.log(` - ${colors.blue(`${stats.renamed} files saved as *-1.mdc`)} (yours preserved)`);
1192
+ }
1193
+ console.log();
1194
+
1195
+ console.log(colors.yellow('Installed for:'));
1196
+ for (const ide of installedFor) {
1197
+ const ideInfo = {
1198
+ cursor: '.cursor/rules/ (Cursor IDE)',
1199
+ claude: 'CLAUDE.md (Claude Code)',
1200
+ codex: '.github/copilot-instructions.md (GitHub Copilot)'
1201
+ };
1202
+ console.log(` - ${ideInfo[ide]}`);
1203
+ }
1204
+ console.log();
1205
+
1206
+ console.log(colors.yellow('Templates:'));
1207
+ console.log(' - _shared (always included)');
1208
+ for (const template of templates) {
1209
+ console.log(` - ${template}`);
1210
+ }
1211
+ console.log();
1212
+
1213
+ if (renamedFiles.length > 0) {
1214
+ console.log(colors.blue('Files saved alongside existing (your files preserved):'));
1215
+ for (const { original, renamed } of renamedFiles) {
1216
+ console.log(` - ${original} → ${renamed}`);
1217
+ }
1218
+ console.log(colors.dim('\nReview the -1 files and merge changes as needed.'));
1219
+ console.log(colors.dim('Use --force to overwrite existing files instead.'));
1220
+ console.log();
1221
+ }
1222
+
1223
+ console.log(colors.blue('Next steps:'));
1224
+ if (installedFor.includes('claude')) {
1225
+ console.log(' 1. Review CLAUDE.md for any customization');
1226
+ }
1227
+ if (installedFor.includes('codex')) {
1228
+ console.log(' 2. Review .github/copilot-instructions.md');
1229
+ }
1230
+ console.log(' 3. Commit the new files to your repository');
1231
+ console.log();
1232
+ }
1233
+
1234
+ /**
1235
+ * Prompt user for confirmation
1236
+ * @param {string} message - The prompt message
1237
+ * @returns {Promise<boolean>}
1238
+ */
1239
+ async function confirm(message) {
1240
+ const readline = await import('readline');
1241
+ const rl = readline.createInterface({
1242
+ input: process.stdin,
1243
+ output: process.stdout
1244
+ });
1245
+
1246
+ return new Promise((resolve) => {
1247
+ rl.question(`${message} [y/N] `, (answer) => {
1248
+ rl.close();
1249
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
1250
+ });
1251
+ });
1252
+ }
1253
+
1254
+ /**
1255
+ * Check if a file was created by our installer (matches template content)
1256
+ * @param {string} filePath - Path to the file
1257
+ * @param {string} templatePath - Path to the template file
1258
+ * @returns {boolean}
1259
+ */
1260
+ function isOurFile(filePath, templatePath) {
1261
+ if (!fs.existsSync(filePath)) return false;
1262
+ if (!fs.existsSync(templatePath)) return true; // No template to compare, assume ours
1263
+ return filesMatch(filePath, templatePath);
1264
+ }
1265
+
1266
+ /**
1267
+ * Remove specific templates from the installation
1268
+ */
1269
+ async function remove(targetDir, templates, dryRun = false, force = false, skipConfirm = false, ides = DEFAULT_IDES) {
1270
+ const stats = { removed: 0, skipped: 0, notFound: 0 };
1271
+ const filesToRemove = [];
1272
+ const modifiedFiles = [];
1273
+
1274
+ console.log(`${colors.blue('Removing from:')} ${targetDir}`);
1275
+ console.log(`${colors.blue('Target IDEs:')} ${ides.join(', ')}`);
1276
+ console.log(`${colors.blue('Templates:')} ${templates.join(', ')}`);
1277
+ console.log();
1278
+
1279
+ // 1. Collect files to remove from .cursor/rules/ (and legacy .cursorrules/)
1280
+ if (ides.includes('cursor')) {
1281
+ const cursorRulesDir = path.join(targetDir, CURSOR_RULES_DIR);
1282
+ const legacyDir = path.join(targetDir, LEGACY_CURSORRULES_DIR);
1283
+ const dirsToScan = [];
1284
+
1285
+ if (fs.existsSync(cursorRulesDir)) dirsToScan.push({ dir: cursorRulesDir, label: CURSOR_RULES_DIR });
1286
+ if (fs.existsSync(legacyDir)) dirsToScan.push({ dir: legacyDir, label: LEGACY_CURSORRULES_DIR });
1287
+
1288
+ if (dirsToScan.length > 0) {
1289
+ for (const template of templates) {
1290
+ console.log(colors.yellow(`► Scanning ${template} template files...`));
1291
+
1292
+ for (const { dir, label } of dirsToScan) {
1293
+ for (const rule of TEMPLATES[template].rules) {
1294
+ const destName = `${template}-${rule}`;
1295
+ const destPath = path.join(dir, destName);
1296
+ const srcPath = getTemplateRulePath(template, rule);
1297
+
1298
+ if (!fs.existsSync(destPath)) {
1299
+ continue;
1300
+ }
1301
+
1302
+ const isUnmodified = isOurFile(destPath, srcPath);
1303
+ const displayName = `${destName} (${label}/)`;
1304
+
1305
+ if (!isUnmodified && !force) {
1306
+ console.log(` ${colors.yellow('[modified]')} ${displayName} (use --force to remove)`);
1307
+ modifiedFiles.push(displayName);
1308
+ stats.skipped++;
1309
+ } else {
1310
+ console.log(` ${colors.red('[remove]')} ${displayName}${!isUnmodified ? ' (modified, --force)' : ''}`);
1311
+ filesToRemove.push({ path: destPath, name: displayName });
1312
+ }
1313
+ }
1314
+
1315
+ // Also check for -1 variant files
1316
+ for (const rule of TEMPLATES[template].rules) {
1317
+ const altName = `${template}-${rule.replace('.mdc', '-1.mdc')}`;
1318
+ const altPath = path.join(dir, altName);
1319
+
1320
+ if (fs.existsSync(altPath)) {
1321
+ console.log(` ${colors.red('[remove]')} ${altName} (${label}/, alternate file)`);
1322
+ filesToRemove.push({ path: altPath, name: altName });
1323
+ }
1324
+ }
1325
+ }
1326
+
1327
+ // Check for legacy-cursorrules-notice.md in new dir
1328
+ const noticePath = path.join(cursorRulesDir, 'legacy-cursorrules-notice.md');
1329
+ if (fs.existsSync(noticePath)) {
1330
+ console.log(` ${colors.red('[remove]')} legacy-cursorrules-notice.md`);
1331
+ filesToRemove.push({ path: noticePath, name: 'legacy-cursorrules-notice.md' });
1332
+ }
1333
+
1334
+ // Log not-found for templates that weren't in either dir
1335
+ for (const rule of TEMPLATES[template].rules) {
1336
+ const destName = `${template}-${rule}`;
1337
+ const inNew = fs.existsSync(path.join(cursorRulesDir, destName));
1338
+ const inLegacy = fs.existsSync(path.join(legacyDir, destName));
1339
+ if (!inNew && !inLegacy) {
1340
+ console.log(` ${colors.dim('[not found]')} ${destName}`);
1341
+ stats.notFound++;
1342
+ }
1343
+ }
1344
+
1345
+ console.log();
1346
+ }
1347
+ } else {
1348
+ console.log(colors.dim(`No ${CURSOR_RULES_DIR}/ or ${LEGACY_CURSORRULES_DIR}/ directory found.\n`));
1349
+ }
1350
+ }
1351
+
1352
+ // 2. Note about CLAUDE.md and copilot-instructions.md
1353
+ // These are regenerated, not patched, so we can't easily remove just one template's content
1354
+ // We'll warn the user about this
1355
+ if (ides.includes('claude') || ides.includes('codex')) {
1356
+ console.log(colors.yellow('Note: CLAUDE.md and copilot-instructions.md contain merged content.'));
1357
+ console.log(colors.dim('To update these files, re-run the installer with the remaining templates.\n'));
1358
+ }
1359
+
1360
+ if (filesToRemove.length === 0) {
1361
+ console.log(colors.yellow('Nothing to remove.\n'));
1362
+ return;
1363
+ }
1364
+
1365
+ // Confirmation
1366
+ if (!dryRun && !skipConfirm) {
1367
+ console.log(colors.yellow(`\nAbout to remove ${filesToRemove.length} file(s).`));
1368
+ const confirmed = await confirm(colors.red('Proceed with removal?'));
1369
+ if (!confirmed) {
1370
+ console.log(colors.dim('\nAborted.\n'));
1371
+ return;
1372
+ }
1373
+ console.log();
1374
+ }
1375
+
1376
+ // Execute removal
1377
+ if (dryRun) {
1378
+ console.log(colors.yellow('DRY RUN - No files were removed.\n'));
1379
+ } else {
1380
+ for (const file of filesToRemove) {
1381
+ try {
1382
+ fs.unlinkSync(file.path);
1383
+ stats.removed++;
1384
+ } catch (err) {
1385
+ console.error(colors.red(`Failed to remove ${file.name}: ${err.message}`));
1386
+ }
1387
+ }
1388
+ }
1389
+
1390
+ // Summary
1391
+ console.log(colors.green('════════════════════════════════════════════════════════════'));
1392
+ console.log(colors.green(`✓ Removal complete!\n`));
1393
+
1394
+ console.log(colors.yellow('Summary:'));
1395
+ console.log(` - ${stats.removed} files removed`);
1396
+ if (stats.skipped > 0) {
1397
+ console.log(` - ${stats.skipped} files skipped (modified, use --force)`);
1398
+ }
1399
+ if (stats.notFound > 0) {
1400
+ console.log(` - ${stats.notFound} files not found`);
1401
+ }
1402
+ console.log();
1403
+
1404
+ if (modifiedFiles.length > 0) {
1405
+ console.log(colors.yellow('Modified files preserved:'));
1406
+ for (const file of modifiedFiles) {
1407
+ console.log(` - ${file}`);
1408
+ }
1409
+ console.log(colors.dim('\nUse --force to remove modified files.\n'));
1410
+ }
1411
+ }
1412
+
1413
+ /**
1414
+ * Reset - remove all installed content
1415
+ */
1416
+ async function reset(targetDir, dryRun = false, force = false, skipConfirm = false, ides = DEFAULT_IDES) {
1417
+ const stats = { removed: 0, skipped: 0 };
1418
+ const filesToRemove = [];
1419
+ const modifiedFiles = [];
1420
+ const dirsToRemove = [];
1421
+
1422
+ console.log(`${colors.blue('Resetting:')} ${targetDir}`);
1423
+ console.log(`${colors.blue('Target IDEs:')} ${ides.join(', ')}`);
1424
+ console.log();
1425
+
1426
+ // 1. Remove .cursor/rules/ and legacy .cursorrules/ contents for Cursor
1427
+ if (ides.includes('cursor')) {
1428
+ const cursorRulesDir = path.join(targetDir, CURSOR_RULES_DIR);
1429
+ const legacyDir = path.join(targetDir, LEGACY_CURSORRULES_DIR);
1430
+ const dirsToScan = [];
1431
+
1432
+ if (fs.existsSync(cursorRulesDir)) dirsToScan.push({ dir: cursorRulesDir, label: CURSOR_RULES_DIR });
1433
+ if (fs.existsSync(legacyDir)) dirsToScan.push({ dir: legacyDir, label: LEGACY_CURSORRULES_DIR });
1434
+
1435
+ if (dirsToScan.length > 0) {
1436
+ for (const { dir, label } of dirsToScan) {
1437
+ console.log(colors.yellow(`► Scanning ${label}/ directory...`));
1438
+
1439
+ // Check shared rules
1440
+ for (const rule of SHARED_RULES) {
1441
+ const destPath = path.join(dir, rule);
1442
+ const srcPath = path.join(TEMPLATES_DIR, '_shared', rule);
1443
+
1444
+ if (!fs.existsSync(destPath)) continue;
1445
+
1446
+ const isUnmodified = isOurFile(destPath, srcPath);
1447
+
1448
+ if (!isUnmodified && !force) {
1449
+ console.log(` ${colors.yellow('[modified]')} ${rule} (use --force to remove)`);
1450
+ modifiedFiles.push(`${rule} (${label}/)`);
1451
+ stats.skipped++;
1452
+ } else {
1453
+ console.log(` ${colors.red('[remove]')} ${rule}${!isUnmodified ? ' (modified, --force)' : ''}`);
1454
+ filesToRemove.push({ path: destPath, name: `${rule} (${label}/)` });
1455
+ }
1456
+
1457
+ // Check for -1 variant
1458
+ const altPath = path.join(dir, rule.replace('.mdc', '-1.mdc'));
1459
+ if (fs.existsSync(altPath)) {
1460
+ console.log(` ${colors.red('[remove]')} ${rule.replace('.mdc', '-1.mdc')} (alternate file)`);
1461
+ filesToRemove.push({ path: altPath, name: rule.replace('.mdc', '-1.mdc') });
1462
+ }
1463
+ }
1464
+
1465
+ // Check template-specific rules
1466
+ for (const [templateName, templateInfo] of Object.entries(TEMPLATES)) {
1467
+ for (const rule of templateInfo.rules) {
1468
+ const destName = `${templateName}-${rule}`;
1469
+ const destPath = path.join(dir, destName);
1470
+ const srcPath = getTemplateRulePath(templateName, rule);
1471
+
1472
+ if (!fs.existsSync(destPath)) continue;
1473
+
1474
+ const isUnmodified = isOurFile(destPath, srcPath);
1475
+
1476
+ if (!isUnmodified && !force) {
1477
+ console.log(` ${colors.yellow('[modified]')} ${destName} (use --force to remove)`);
1478
+ modifiedFiles.push(`${destName} (${label}/)`);
1479
+ stats.skipped++;
1480
+ } else {
1481
+ console.log(` ${colors.red('[remove]')} ${destName}${!isUnmodified ? ' (modified, --force)' : ''}`);
1482
+ filesToRemove.push({ path: destPath, name: `${destName} (${label}/)` });
1483
+ }
1484
+
1485
+ // Check for -1 variant
1486
+ const altName = destName.replace('.mdc', '-1.mdc');
1487
+ const altPath = path.join(dir, altName);
1488
+ if (fs.existsSync(altPath)) {
1489
+ console.log(` ${colors.red('[remove]')} ${altName} (alternate file)`);
1490
+ filesToRemove.push({ path: altPath, name: altName });
1491
+ }
1492
+ }
1493
+ }
1494
+
1495
+ // Check for legacy-cursorrules-notice.md
1496
+ const noticePath = path.join(dir, 'legacy-cursorrules-notice.md');
1497
+ if (fs.existsSync(noticePath)) {
1498
+ console.log(` ${colors.red('[remove]')} legacy-cursorrules-notice.md`);
1499
+ filesToRemove.push({ path: noticePath, name: 'legacy-cursorrules-notice.md' });
1500
+ }
1501
+
1502
+ // Check if we should remove the directory itself (only if it would be empty)
1503
+ const remainingFiles = fs.readdirSync(dir).filter(f => {
1504
+ const fullPath = path.join(dir, f);
1505
+ const willBeRemoved = filesToRemove.some(fr => fr.path === fullPath);
1506
+ return !willBeRemoved;
1507
+ });
1508
+
1509
+ if (remainingFiles.length === 0 || force) {
1510
+ console.log(` ${colors.red('[remove]')} ${label}/ directory`);
1511
+ dirsToRemove.push(dir);
1512
+ // If removing .cursor/rules/, also check if .cursor/ would be empty
1513
+ if (label === CURSOR_RULES_DIR) {
1514
+ const cursorDir = path.join(targetDir, '.cursor');
1515
+ dirsToRemove.push(cursorDir);
1516
+ }
1517
+ } else if (remainingFiles.length > 0) {
1518
+ console.log(colors.dim(` ${label}/ will be kept (${remainingFiles.length} non-template file(s) remain)`));
1519
+ }
1520
+
1521
+ console.log();
1522
+ }
1523
+ } else {
1524
+ console.log(colors.dim(`No ${CURSOR_RULES_DIR}/ or ${LEGACY_CURSORRULES_DIR}/ directory found.\n`));
1525
+ }
1526
+ }
1527
+
1528
+ // 2. Remove CLAUDE.md for Claude
1529
+ if (ides.includes('claude')) {
1530
+ const claudePath = path.join(targetDir, 'CLAUDE.md');
1531
+
1532
+ if (fs.existsSync(claudePath)) {
1533
+ console.log(colors.yellow('► Checking CLAUDE.md...'));
1534
+
1535
+ // Check if it contains our signature content
1536
+ const content = fs.readFileSync(claudePath, 'utf8');
1537
+ const isOurs = content.includes('# CLAUDE.md - Development Guide') &&
1538
+ (content.includes('.cursor/rules/') || content.includes('.cursorrules/'));
1539
+
1540
+ if (!isOurs && !force) {
1541
+ console.log(` ${colors.yellow('[modified]')} CLAUDE.md (doesn't match template, use --force)`);
1542
+ modifiedFiles.push('CLAUDE.md');
1543
+ stats.skipped++;
1544
+ } else {
1545
+ console.log(` ${colors.red('[remove]')} CLAUDE.md${!isOurs ? ' (modified, --force)' : ''}`);
1546
+ filesToRemove.push({ path: claudePath, name: 'CLAUDE.md' });
1547
+ }
1548
+ console.log();
1549
+ }
1550
+ }
1551
+
1552
+ // 3. Remove .github/copilot-instructions.md for Codex
1553
+ if (ides.includes('codex')) {
1554
+ const copilotPath = path.join(targetDir, '.github', 'copilot-instructions.md');
1555
+
1556
+ if (fs.existsSync(copilotPath)) {
1557
+ console.log(colors.yellow('► Checking .github/copilot-instructions.md...'));
1558
+
1559
+ // Check if it contains our signature content
1560
+ const content = fs.readFileSync(copilotPath, 'utf8');
1561
+ const isOurs = content.includes('# Copilot Instructions') &&
1562
+ content.includes('Installed Templates:');
1563
+
1564
+ if (!isOurs && !force) {
1565
+ console.log(` ${colors.yellow('[modified]')} .github/copilot-instructions.md (doesn't match template, use --force)`);
1566
+ modifiedFiles.push('.github/copilot-instructions.md');
1567
+ stats.skipped++;
1568
+ } else {
1569
+ console.log(` ${colors.red('[remove]')} .github/copilot-instructions.md${!isOurs ? ' (modified, --force)' : ''}`);
1570
+ filesToRemove.push({ path: copilotPath, name: '.github/copilot-instructions.md' });
1571
+ }
1572
+ console.log();
1573
+ }
1574
+ }
1575
+
1576
+ if (filesToRemove.length === 0 && dirsToRemove.length === 0) {
1577
+ console.log(colors.yellow('Nothing to remove.\n'));
1578
+ return;
1579
+ }
1580
+
1581
+ // Confirmation
1582
+ if (!dryRun && !skipConfirm) {
1583
+ const totalItems = filesToRemove.length + dirsToRemove.length;
1584
+ console.log(colors.yellow(`\nAbout to remove ${totalItems} item(s).`));
1585
+ const confirmed = await confirm(colors.red('Proceed with reset?'));
1586
+ if (!confirmed) {
1587
+ console.log(colors.dim('\nAborted.\n'));
1588
+ return;
1589
+ }
1590
+ console.log();
1591
+ }
1592
+
1593
+ // Execute removal
1594
+ if (dryRun) {
1595
+ console.log(colors.yellow('DRY RUN - No files were removed.\n'));
1596
+ } else {
1597
+ // Remove files first
1598
+ for (const file of filesToRemove) {
1599
+ try {
1600
+ fs.unlinkSync(file.path);
1601
+ stats.removed++;
1602
+ } catch (err) {
1603
+ console.error(colors.red(`Failed to remove ${file.name}: ${err.message}`));
1604
+ }
1605
+ }
1606
+
1607
+ // Then remove directories
1608
+ for (const dir of dirsToRemove) {
1609
+ try {
1610
+ // Check if directory is now empty
1611
+ const remaining = fs.existsSync(dir) ? fs.readdirSync(dir) : [];
1612
+ if (remaining.length === 0) {
1613
+ fs.rmdirSync(dir);
1614
+ stats.removed++;
1615
+ } else if (force) {
1616
+ fs.rmSync(dir, { recursive: true });
1617
+ stats.removed++;
1618
+ }
1619
+ } catch (err) {
1620
+ console.error(colors.red(`Failed to remove directory: ${err.message}`));
1621
+ }
1622
+ }
1623
+ }
1624
+
1625
+ // Summary
1626
+ console.log(colors.green('════════════════════════════════════════════════════════════'));
1627
+ console.log(colors.green(`✓ Reset complete!\n`));
1628
+
1629
+ console.log(colors.yellow('Summary:'));
1630
+ console.log(` - ${stats.removed} items removed`);
1631
+ if (stats.skipped > 0) {
1632
+ console.log(` - ${stats.skipped} files skipped (modified, use --force)`);
1633
+ }
1634
+ console.log();
1635
+
1636
+ if (modifiedFiles.length > 0) {
1637
+ console.log(colors.yellow('Modified files preserved:'));
1638
+ for (const file of modifiedFiles) {
1639
+ console.log(` - ${file}`);
1640
+ }
1641
+ console.log(colors.dim('\nUse --force to remove modified files.\n'));
1642
+ }
1643
+ }
1644
+
1645
+ export async function run(args) {
1646
+ const templates = [];
1647
+ const ides = [];
1648
+ let dryRun = false;
1649
+ let force = false;
1650
+ let skipConfirm = false;
1651
+ let removeMode = false;
1652
+ let resetMode = false;
1653
+
1654
+ // Parse arguments
1655
+ for (const arg of args) {
1656
+ if (arg === '--list' || arg === '-l') {
1657
+ printBanner();
1658
+ printTemplates();
1659
+ process.exit(0);
1660
+ } else if (arg === '--help' || arg === '-h') {
1661
+ printBanner();
1662
+ printHelp();
1663
+ process.exit(0);
1664
+ } else if (arg === '--version' || arg === '-v') {
1665
+ console.log(`${PACKAGE_NAME} v${CURRENT_VERSION}`);
1666
+ console.log(`${colors.dim('Changelog:')} ${CHANGELOG_URL}`);
1667
+ process.exit(0);
1668
+ } else if (arg === '--dry-run') {
1669
+ dryRun = true;
1670
+ } else if (arg === '--force' || arg === '-f') {
1671
+ force = true;
1672
+ } else if (arg === '--yes' || arg === '-y') {
1673
+ skipConfirm = true;
1674
+ } else if (arg === '--remove') {
1675
+ removeMode = true;
1676
+ } else if (arg === '--reset') {
1677
+ resetMode = true;
1678
+ } else if (arg.startsWith('--ide=')) {
1679
+ const ide = arg.slice(6).toLowerCase();
1680
+ if (!SUPPORTED_IDES.includes(ide)) {
1681
+ console.error(colors.red(`Error: Unknown IDE '${ide}'`));
1682
+ console.error(colors.dim(`Supported: ${SUPPORTED_IDES.join(', ')}`));
1683
+ process.exit(1);
1684
+ }
1685
+ if (!ides.includes(ide)) {
1686
+ ides.push(ide);
1687
+ }
1688
+ } else if (arg.startsWith('-')) {
1689
+ console.error(colors.red(`Error: Unknown option '${arg}'`));
1690
+ printHelp();
1691
+ process.exit(1);
1692
+ } else {
1693
+ templates.push(arg);
1694
+ }
1695
+ }
1696
+
1697
+ printBanner();
1698
+
1699
+ // Check for updates (non-blocking, fails silently)
1700
+ await checkForUpdates();
1701
+
1702
+ // Resolve template aliases to canonical names
1703
+ const resolvedTemplates = templates.map(resolveTemplateAlias);
1704
+
1705
+ // Use default IDEs if none specified
1706
+ const targetIdes = ides.length > 0 ? ides : DEFAULT_IDES;
1707
+
1708
+ // Handle reset mode
1709
+ if (resetMode) {
1710
+ if (removeMode) {
1711
+ console.error(colors.red('Error: Cannot use --remove and --reset together\n'));
1712
+ process.exit(1);
1713
+ }
1714
+ if (resolvedTemplates.length > 0) {
1715
+ console.error(colors.red('Error: --reset does not accept template arguments\n'));
1716
+ console.error(colors.dim('Use --remove <templates...> to remove specific templates.\n'));
1717
+ process.exit(1);
1718
+ }
1719
+
1720
+ if (dryRun) {
1721
+ console.log(colors.yellow('DRY RUN - No changes will be made\n'));
1722
+ }
1723
+ if (force) {
1724
+ console.log(colors.yellow('FORCE MODE - Modified files will be removed\n'));
1725
+ }
1726
+
1727
+ await reset(process.cwd(), dryRun, force, skipConfirm, targetIdes);
1728
+ return;
1729
+ }
1730
+
1731
+ // Handle remove mode
1732
+ if (removeMode) {
1733
+ if (resolvedTemplates.length === 0) {
1734
+ console.error(colors.red('Error: No templates specified for removal\n'));
1735
+ console.error(colors.dim('Usage: npx @djm204/agent-skills --remove <templates...>\n'));
1736
+ printTemplates();
1737
+ process.exit(1);
1738
+ }
1739
+
1740
+ for (const template of resolvedTemplates) {
1741
+ if (!TEMPLATES[template]) {
1742
+ console.error(colors.red(`Error: Unknown template '${template}'\n`));
1743
+ printTemplates();
1744
+ process.exit(1);
1745
+ }
1746
+ }
1747
+
1748
+ if (dryRun) {
1749
+ console.log(colors.yellow('DRY RUN - No changes will be made\n'));
1750
+ }
1751
+ if (force) {
1752
+ console.log(colors.yellow('FORCE MODE - Modified files will be removed\n'));
1753
+ }
1754
+
1755
+ await remove(process.cwd(), resolvedTemplates, dryRun, force, skipConfirm, targetIdes);
1756
+ return;
1757
+ }
1758
+
1759
+ // Install mode (default)
1760
+ if (resolvedTemplates.length === 0) {
1761
+ console.error(colors.red('Error: No templates specified\n'));
1762
+ printHelp();
1763
+ process.exit(1);
1764
+ }
1765
+
1766
+ for (const template of resolvedTemplates) {
1767
+ if (!TEMPLATES[template]) {
1768
+ console.error(colors.red(`Error: Unknown template '${template}'\n`));
1769
+ printTemplates();
1770
+ process.exit(1);
1771
+ }
1772
+ }
1773
+
1774
+ if (dryRun) {
1775
+ console.log(colors.yellow('DRY RUN - No changes will be made\n'));
1776
+ }
1777
+
1778
+ if (force) {
1779
+ console.log(colors.yellow('FORCE MODE - Existing files will be overwritten\n'));
1780
+ }
1781
+
1782
+ // Install to current directory
1783
+ await install(process.cwd(), resolvedTemplates, dryRun, force, targetIdes, skipConfirm);
1784
+ }
1785
+
1786
+ // Export internals for testing
1787
+ export const _internals = {
1788
+ PACKAGE_NAME,
1789
+ CURRENT_VERSION,
1790
+ REPO_URL,
1791
+ CHANGELOG_URL,
1792
+ CURSOR_RULES_DIR,
1793
+ LEGACY_CURSORRULES_DIR,
1794
+ CATEGORIES,
1795
+ TEMPLATES,
1796
+ TEMPLATE_ALIASES,
1797
+ SHARED_RULES,
1798
+ SUPPORTED_IDES,
1799
+ DEFAULT_IDES,
1800
+ compareVersions,
1801
+ checkForUpdates,
1802
+ resolveTemplateAlias,
1803
+ getTemplateRulePath,
1804
+ filesMatch,
1805
+ parseMarkdownSections,
1806
+ generateSectionSignature,
1807
+ findMissingSections,
1808
+ mergeClaudeContent,
1809
+ getAlternateFilename,
1810
+ copyFile,
1811
+ generateClaudeMdContent,
1812
+ generateCopilotInstructionsContent,
1813
+ isOurFile,
1814
+ install,
1815
+ remove,
1816
+ reset,
1817
+ };