bi-superpowers 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 (276) hide show
  1. package/.claude-plugin/marketplace.json +31 -0
  2. package/.claude-plugin/plugin.json +34 -0
  3. package/.claude-plugin/skill-manifest.json +79 -0
  4. package/.mcp.json +13 -0
  5. package/.plugin/plugin.json +14 -0
  6. package/LICENSE +21 -0
  7. package/README.md +849 -0
  8. package/bin/build-plugin.js +97 -0
  9. package/bin/cli.js +891 -0
  10. package/bin/commands/autoupdate.js +128 -0
  11. package/bin/commands/build-desktop.js +368 -0
  12. package/bin/commands/create-from-template.js +165 -0
  13. package/bin/commands/diff.js +435 -0
  14. package/bin/commands/install.js +542 -0
  15. package/bin/commands/lint.js +441 -0
  16. package/bin/commands/mcp-setup.js +255 -0
  17. package/bin/commands/session-update.js +204 -0
  18. package/bin/commands/smoke-test.js +20 -0
  19. package/bin/commands/uninstall.js +611 -0
  20. package/bin/commands/update-check.js +427 -0
  21. package/bin/commands/validate-cases.js +264 -0
  22. package/bin/commands/validate-projects.js +426 -0
  23. package/bin/commands/watch.js +251 -0
  24. package/bin/lib/agents.js +62 -0
  25. package/bin/lib/base-template-smoke.js +299 -0
  26. package/bin/lib/claude-hooks.js +160 -0
  27. package/bin/lib/generators/claude-plugin.js +529 -0
  28. package/bin/lib/generators/index.js +116 -0
  29. package/bin/lib/generators/shared.js +257 -0
  30. package/bin/lib/mcp-config.js +835 -0
  31. package/bin/lib/microsoft-mcp.js +206 -0
  32. package/bin/lib/powerbi-mcp-session.js +140 -0
  33. package/bin/lib/skills.js +164 -0
  34. package/bin/lib/template-scaffold.js +366 -0
  35. package/bin/mcp/powerbi-modeling-launcher.js +42 -0
  36. package/bin/postinstall.js +50 -0
  37. package/bin/utils/mcp-detect.js +346 -0
  38. package/bin/utils/tui.js +314 -0
  39. package/commands/bi-connect.md +520 -0
  40. package/commands/bi-dax.md +464 -0
  41. package/commands/bi-kickoff.md +550 -0
  42. package/commands/bi-modeling.md +485 -0
  43. package/commands/bi-performance.md +521 -0
  44. package/commands/bi-powerquery.md +229 -0
  45. package/commands/bi-refactor.md +249 -0
  46. package/commands/bi-scorecard.md +268 -0
  47. package/commands/bi-start.md +272 -0
  48. package/config.example.json +23 -0
  49. package/config.json +23 -0
  50. package/desktop-extension/manifest.json +30 -0
  51. package/desktop-extension/package.json +10 -0
  52. package/desktop-extension/server.js +137 -0
  53. package/package.json +94 -0
  54. package/skills/bi-connect/SKILL.md +522 -0
  55. package/skills/bi-connect/scripts/update-check.js +427 -0
  56. package/skills/bi-dax/SKILL.md +466 -0
  57. package/skills/bi-dax/scripts/update-check.js +427 -0
  58. package/skills/bi-kickoff/SKILL.md +552 -0
  59. package/skills/bi-kickoff/references/flow.html +78 -0
  60. package/skills/bi-kickoff/references/flow.md +62 -0
  61. package/skills/bi-kickoff/scripts/update-check.js +427 -0
  62. package/skills/bi-modeling/SKILL.md +487 -0
  63. package/skills/bi-modeling/scripts/update-check.js +427 -0
  64. package/skills/bi-performance/SKILL.md +523 -0
  65. package/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
  66. package/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
  67. package/skills/bi-performance/scripts/update-check.js +427 -0
  68. package/skills/bi-powerquery/SKILL.md +231 -0
  69. package/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
  70. package/skills/bi-powerquery/references/power-query-standards.md +74 -0
  71. package/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
  72. package/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
  73. package/skills/bi-powerquery/scripts/update-check.js +427 -0
  74. package/skills/bi-refactor/SKILL.md +251 -0
  75. package/skills/bi-refactor/references/flow.md +27 -0
  76. package/skills/bi-refactor/scripts/update-check.js +427 -0
  77. package/skills/bi-scorecard/SKILL.md +270 -0
  78. package/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
  79. package/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
  80. package/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
  81. package/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
  82. package/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
  83. package/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
  84. package/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
  85. package/skills/bi-scorecard/scripts/update-check.js +427 -0
  86. package/skills/bi-start/SKILL.md +274 -0
  87. package/skills/bi-start/scripts/update-check.js +427 -0
  88. package/src/content/base.md +197 -0
  89. package/src/content/mcp-requirements.json +57 -0
  90. package/src/content/routing.md +201 -0
  91. package/src/content/skills/bi-connect.md +493 -0
  92. package/src/content/skills/bi-dax.md +437 -0
  93. package/src/content/skills/bi-kickoff/SKILL.md +523 -0
  94. package/src/content/skills/bi-kickoff/references/flow.html +78 -0
  95. package/src/content/skills/bi-kickoff/references/flow.md +62 -0
  96. package/src/content/skills/bi-modeling.md +458 -0
  97. package/src/content/skills/bi-performance/SKILL.md +494 -0
  98. package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
  99. package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
  100. package/src/content/skills/bi-powerquery/SKILL.md +202 -0
  101. package/src/content/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
  102. package/src/content/skills/bi-powerquery/references/power-query-standards.md +74 -0
  103. package/src/content/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
  104. package/src/content/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
  105. package/src/content/skills/bi-refactor/SKILL.md +222 -0
  106. package/src/content/skills/bi-refactor/references/flow.md +27 -0
  107. package/src/content/skills/bi-scorecard/SKILL.md +241 -0
  108. package/src/content/skills/bi-scorecard/examples/base-template-scorecard-blueprint.expected.json +105 -0
  109. package/src/content/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
  110. package/src/content/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
  111. package/src/content/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
  112. package/src/content/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
  113. package/src/content/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
  114. package/src/content/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
  115. package/src/content/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
  116. package/src/content/skills/bi-start.md +266 -0
  117. package/templates/base-template/AGENTS.md +33 -0
  118. package/templates/base-template/base-template.Report/.platform +11 -0
  119. package/templates/base-template/base-template.Report/StaticResources/RegisteredResources/BISuperpowers.json +3888 -0
  120. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/CY18SU07.json +177 -0
  121. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/Fluent2-CY26SU03.json +4104 -0
  122. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleCityPark.json +26 -0
  123. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleDefault.json +26 -0
  124. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleNeutral.json +26 -0
  125. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleOrchid.json +26 -0
  126. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleTidal.json +26 -0
  127. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Bloom.json +139 -0
  128. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CityPark.json +40 -0
  129. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Classroom.json +40 -0
  130. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/ColorblindSafe.json +48 -0
  131. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CopilotDefault.json +1861 -0
  132. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Divergent.json +127 -0
  133. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Electric.json +48 -0
  134. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Frontier.json +136 -0
  135. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/HighContrast.json +40 -0
  136. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Highrise.json +41 -0
  137. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Innovate.json +227 -0
  138. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/NewExecutive.json +41 -0
  139. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Solar.json +33 -0
  140. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Storm.json +25 -0
  141. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Sunset.json +48 -0
  142. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Temperature.json +33 -0
  143. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Tidal.json +100 -0
  144. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Twilight.json +40 -0
  145. package/templates/base-template/base-template.Report/definition/bookmarks/1d40d43c7ade66e8603c.bookmark.json +2297 -0
  146. package/templates/base-template/base-template.Report/definition/bookmarks/af068ff51c0ca3089ea7.bookmark.json +2300 -0
  147. package/templates/base-template/base-template.Report/definition/bookmarks/bookmarks.json +11 -0
  148. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/page.json +130 -0
  149. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/mobile.json +11 -0
  150. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/visual.json +669 -0
  151. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/mobile.json +11 -0
  152. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/visual.json +723 -0
  153. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/mobile.json +11 -0
  154. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/visual.json +333 -0
  155. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/mobile.json +11 -0
  156. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/visual.json +109 -0
  157. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/mobile.json +31 -0
  158. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/visual.json +378 -0
  159. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/mobile.json +11 -0
  160. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/visual.json +175 -0
  161. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/mobile.json +11 -0
  162. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/visual.json +468 -0
  163. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/mobile.json +11 -0
  164. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/visual.json +359 -0
  165. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/mobile.json +11 -0
  166. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/visual.json +690 -0
  167. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/90677f13cea5d1275990/visual.json +17 -0
  168. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/mobile.json +11 -0
  169. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/visual.json +468 -0
  170. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/mobile.json +10 -0
  171. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/visual.json +328 -0
  172. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/mobile.json +11 -0
  173. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/visual.json +578 -0
  174. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/mobile.json +11 -0
  175. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/visual.json +432 -0
  176. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/mobile.json +11 -0
  177. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/visual.json +801 -0
  178. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/mobile.json +37 -0
  179. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/visual.json +1318 -0
  180. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b529688fe5a226643322/visual.json +209 -0
  181. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/mobile.json +11 -0
  182. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/visual.json +174 -0
  183. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/mobile.json +29 -0
  184. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/visual.json +241 -0
  185. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/page.json +130 -0
  186. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/mobile.json +11 -0
  187. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/visual.json +690 -0
  188. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/mobile.json +11 -0
  189. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/visual.json +468 -0
  190. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/mobile.json +11 -0
  191. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/visual.json +359 -0
  192. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/mobile.json +11 -0
  193. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/visual.json +669 -0
  194. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/mobile.json +11 -0
  195. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/visual.json +109 -0
  196. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/31c21f8cbeb3b208940a/visual.json +209 -0
  197. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/3ab72c25062437149b03/visual.json +17 -0
  198. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/mobile.json +11 -0
  199. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/visual.json +788 -0
  200. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/mobile.json +11 -0
  201. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/visual.json +592 -0
  202. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/mobile.json +11 -0
  203. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/visual.json +468 -0
  204. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/mobile.json +11 -0
  205. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/visual.json +1310 -0
  206. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/mobile.json +11 -0
  207. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/visual.json +175 -0
  208. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/mobile.json +11 -0
  209. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/visual.json +516 -0
  210. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d1e86f213a3841d12e20/visual.json +328 -0
  211. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/mobile.json +11 -0
  212. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/visual.json +432 -0
  213. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/mobile.json +11 -0
  214. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/visual.json +241 -0
  215. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/mobile.json +11 -0
  216. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/visual.json +174 -0
  217. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/mobile.json +11 -0
  218. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/visual.json +333 -0
  219. package/templates/base-template/base-template.Report/definition/pages/pages.json +8 -0
  220. package/templates/base-template/base-template.Report/definition/report.json +89 -0
  221. package/templates/base-template/base-template.Report/definition/version.json +4 -0
  222. package/templates/base-template/base-template.Report/definition.pbir +9 -0
  223. package/templates/base-template/base-template.SemanticModel/.platform +11 -0
  224. package/templates/base-template/base-template.SemanticModel/definition/cultures/es-AR.tmdl +11185 -0
  225. package/templates/base-template/base-template.SemanticModel/definition/database.tmdl +3 -0
  226. package/templates/base-template/base-template.SemanticModel/definition/expressions.tmdl +234 -0
  227. package/templates/base-template/base-template.SemanticModel/definition/functions.tmdl +637 -0
  228. package/templates/base-template/base-template.SemanticModel/definition/model.tmdl +82 -0
  229. package/templates/base-template/base-template.SemanticModel/definition/relationships.tmdl +271 -0
  230. package/templates/base-template/base-template.SemanticModel/definition/tables/Calendario.tmdl +200 -0
  231. package/templates/base-template/base-template.SemanticModel/definition/tables/Campa/303/261as.tmdl +75 -0
  232. package/templates/base-template/base-template.SemanticModel/definition/tables/Canales.tmdl +84 -0
  233. package/templates/base-template/base-template.SemanticModel/definition/tables/Clientes.tmdl +143 -0
  234. package/templates/base-template/base-template.SemanticModel/definition/tables/Devoluciones.tmdl +95 -0
  235. package/templates/base-template/base-template.SemanticModel/definition/tables/Ejecuci/303/263n proyectos.tmdl" +130 -0
  236. package/templates/base-template/base-template.SemanticModel/definition/tables/Entregas.tmdl +122 -0
  237. package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos m/303/251tricas.tmdl" +40 -0
  238. package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos.tmdl +73 -0
  239. package/templates/base-template/base-template.SemanticModel/definition/tables/Horas.tmdl +122 -0
  240. package/templates/base-template/base-template.SemanticModel/definition/tables/Interacciones clientes.tmdl +146 -0
  241. package/templates/base-template/base-template.SemanticModel/definition/tables/Leads.tmdl +119 -0
  242. package/templates/base-template/base-template.SemanticModel/definition/tables/Monedas.tmdl +44 -0
  243. package/templates/base-template/base-template.SemanticModel/definition/tables/Movimientos financieros.tmdl +145 -0
  244. package/templates/base-template/base-template.SemanticModel/definition/tables/M/303/251tricas.tmdl +1294 -0
  245. package/templates/base-template/base-template.SemanticModel/definition/tables/N/303/263mina.tmdl +110 -0
  246. package/templates/base-template/base-template.SemanticModel/definition/tables/Oportunidades.tmdl +135 -0
  247. package/templates/base-template/base-template.SemanticModel/definition/tables/Presupuesto.tmdl +125 -0
  248. package/templates/base-template/base-template.SemanticModel/definition/tables/Productos.tmdl +98 -0
  249. package/templates/base-template/base-template.SemanticModel/definition/tables/Proyectos.tmdl +77 -0
  250. package/templates/base-template/base-template.SemanticModel/definition/tables/Servicios.tmdl +75 -0
  251. package/templates/base-template/base-template.SemanticModel/definition/tables/Tareas proyecto.tmdl +102 -0
  252. package/templates/base-template/base-template.SemanticModel/definition/tables/Tipo de cambio.tmdl +67 -0
  253. package/templates/base-template/base-template.SemanticModel/definition/tables/Ventas.tmdl +180 -0
  254. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux An/303/241lisis dimensiones.tmdl" +38 -0
  255. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Comparaciones.tmdl +227 -0
  256. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Compatibilidad m/303/251trica-dimensi/303/263n.tmdl" +68 -0
  257. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modelo configuraci/303/263n.tmdl" +44 -0
  258. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modo fechas.tmdl +36 -0
  259. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux M/303/251trica-Equipo.tmdl" +102 -0
  260. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Overrides m/303/251trica-dimensi/303/263n.tmdl" +54 -0
  261. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Per/303/255odos.tmdl" +182 -0
  262. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas modo.tmdl +36 -0
  263. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas.tmdl +27 -0
  264. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Vista de calendario.tmdl +30 -0
  265. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC C/303/241lculo.tmdl" +70 -0
  266. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Eje X.tmdl +63 -0
  267. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC M/303/251trica.tmdl" +374 -0
  268. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Tipo c/303/241lculo.tmdl" +223 -0
  269. package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Dimensi/303/263n.tmdl" +98 -0
  270. package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Eje X.tmdl +68 -0
  271. package/templates/base-template/base-template.SemanticModel/definition/tables//303/223rdenes servicio.tmdl" +151 -0
  272. package/templates/base-template/base-template.SemanticModel/definition.pbism +5 -0
  273. package/templates/base-template/base-template.SemanticModel/diagramLayout.json +568 -0
  274. package/templates/base-template/base-template.pbip +14 -0
  275. package/templates/base-template/template.manifest.json +41 -0
  276. package/theme/BISuperpowers.json +3888 -0
@@ -0,0 +1,542 @@
1
+ /**
2
+ * Install Command — Multi-agent skill + MCP installer
3
+ * =====================================================
4
+ *
5
+ * Installs the bi-superpowers skills and Microsoft MCP servers into
6
+ * every supported AI coding agent:
7
+ * - Claude Code
8
+ * - GitHub Copilot
9
+ * - Codex (OpenAI)
10
+ * - Gemini CLI
11
+ * - Kilo Code
12
+ *
13
+ * Everything is installed at the user level (~/) so it applies across
14
+ * all projects without polluting any specific repo. Skills land in
15
+ * ~/.agents/skills/ (universal path) and each agent's own skill dir is
16
+ * symlinked to that universal copy when possible. Copy fallback mirrors
17
+ * managed skill directories on every run. MCPs are written to each agent's
18
+ * expected config file in the format that agent requires (JSON for
19
+ * most, TOML for Codex) — see `lib/mcp-config.js` for details.
20
+ *
21
+ * Fully open source (MIT). CLI copy, comments, and JSDoc stay in English
22
+ * so contributors from any language can work on the source.
23
+ *
24
+ * Usage:
25
+ * npx bi-superpowers install
26
+ * super install
27
+ * super install --agent claude-code --agent codex
28
+ * super install --all --yes
29
+ *
30
+ * @module commands/install
31
+ */
32
+
33
+ const fs = require('fs');
34
+ const path = require('path');
35
+ const os = require('os');
36
+ const readline = require('readline');
37
+ const { AGENTS, UNIVERSAL_DIR } = require('../lib/agents');
38
+ const { writeMcpConfigForAgent } = require('../lib/mcp-config');
39
+ const { getSkillPurpose } = require('../lib/generators/shared');
40
+
41
+ /**
42
+ * Detect which agents are installed by checking their config directories.
43
+ * Used in the interactive installer to pre-select the detected agents.
44
+ * @param {string} baseDir - Base directory to scan (typically the user's home)
45
+ * @returns {string[]} IDs of detected agents
46
+ */
47
+ function detectAgents(baseDir) {
48
+ const detected = [];
49
+ for (const [id, agent] of Object.entries(AGENTS)) {
50
+ const agentRoot = path.dirname(agent.dir);
51
+ const checkPaths =
52
+ id === 'kilo'
53
+ ? [path.join(baseDir, agentRoot), path.join(baseDir, '.config', 'kilo')]
54
+ : [path.join(baseDir, agentRoot)];
55
+
56
+ if (checkPaths.some((checkPath) => fs.existsSync(checkPath))) {
57
+ detected.push(id);
58
+ }
59
+ }
60
+ return detected;
61
+ }
62
+
63
+ /**
64
+ * Create a readline interface for interactive prompts.
65
+ */
66
+ function createReadline() {
67
+ return readline.createInterface({
68
+ input: process.stdin,
69
+ output: process.stdout,
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Promise-wrapped readline question.
75
+ */
76
+ function prompt(rl, question) {
77
+ return new Promise((resolve) => {
78
+ rl.question(question, (answer) => resolve(answer.trim()));
79
+ });
80
+ }
81
+
82
+ /**
83
+ * Render a numbered multi-select list and wait for the user's choice.
84
+ * @param {readline.Interface} rl
85
+ * @param {Array<{id: string, name: string}>} items
86
+ * @param {string[]} preselected - IDs that should default to selected
87
+ * @returns {Promise<string[]>} Selected IDs
88
+ */
89
+ async function selectMultiple(rl, items, preselected = []) {
90
+ items.forEach((item, i) => {
91
+ const marker = preselected.includes(item.id) ? '●' : '○';
92
+ console.log(` ${i + 1}) ${marker} ${item.name}`);
93
+ });
94
+ console.log();
95
+ console.log(' Enter numbers separated by commas (for example: 1,2,3)');
96
+ console.log(' Press Enter for detected agents, or "a" for all agents');
97
+
98
+ const answer = await prompt(rl, '\n > ');
99
+
100
+ if (answer.toLowerCase() === 'a') {
101
+ return items.map((item) => item.id);
102
+ }
103
+
104
+ if (answer === '') {
105
+ return preselected.length > 0 ? preselected : items.map((item) => item.id);
106
+ }
107
+
108
+ const indices = answer
109
+ .split(',')
110
+ .map((s) => parseInt(s.trim(), 10) - 1)
111
+ .filter((i) => i >= 0 && i < items.length);
112
+
113
+ return indices.map((i) => items[i].id);
114
+ }
115
+
116
+ /**
117
+ * Recursively copy a skill directory (SKILL.md + references/ + scripts/).
118
+ * Filesystem errors propagate to the caller for centralized handling.
119
+ * @param {string} srcDir - Source skill directory
120
+ * @param {string} destDir - Destination directory
121
+ */
122
+ function copySkillDir(srcDir, destDir) {
123
+ const resolvedSrc = path.resolve(srcDir);
124
+ const resolvedDest = path.resolve(destDir);
125
+ const destRoot = path.parse(resolvedDest).root;
126
+
127
+ if (
128
+ resolvedSrc === resolvedDest ||
129
+ resolvedSrc.startsWith(`${resolvedDest}${path.sep}`) ||
130
+ resolvedDest === destRoot
131
+ ) {
132
+ throw new Error(`Refusing to mirror skill directory into unsafe target: ${destDir}`);
133
+ }
134
+
135
+ // Skill directories are package-managed. Remove the old managed copy first
136
+ // so upgrades cannot leave deleted scripts or references behind.
137
+ const existingDest = fs.lstatSync(destDir, { throwIfNoEntry: false });
138
+ if (existingDest) {
139
+ if (existingDest.isSymbolicLink()) {
140
+ fs.unlinkSync(destDir);
141
+ } else {
142
+ fs.rmSync(destDir, { recursive: true, force: true });
143
+ }
144
+ }
145
+
146
+ fs.mkdirSync(destDir, { recursive: true });
147
+
148
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
149
+ for (const entry of entries) {
150
+ const srcPath = path.join(srcDir, entry.name);
151
+ const destPath = path.join(destDir, entry.name);
152
+
153
+ if (entry.isDirectory()) {
154
+ copySkillDir(srcPath, destPath);
155
+ } else {
156
+ fs.copyFileSync(srcPath, destPath);
157
+ }
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Format a filesystem error with a user-friendly hint based on the code.
163
+ * Keeps the underlying error message so debugging is still possible.
164
+ */
165
+ function formatFsError(err, context) {
166
+ const codeHints = {
167
+ EACCES: 'Permission denied. Check the directory permissions.',
168
+ EPERM: 'Operation not permitted. On Windows, try running as Administrator.',
169
+ ENOSPC: 'No disk space left.',
170
+ ENOENT: 'File or directory does not exist.',
171
+ EROFS: 'Read-only filesystem.',
172
+ };
173
+ const hint = codeHints[err.code] || '';
174
+ return `${context}: ${err.message}${hint ? `\n ${hint}` : ''}`;
175
+ }
176
+
177
+ /**
178
+ * Parse CLI arguments into an options object.
179
+ * Validates that each --agent / -a flag is followed by a real value
180
+ * so we don't silently accept dangling flags.
181
+ */
182
+ function parseArgs(args) {
183
+ const opts = {
184
+ isYes: args.includes('--yes') || args.includes('-y'),
185
+ isAll: args.includes('--all'),
186
+ autoUpdate: args.includes('--auto-update'),
187
+ agentFlags: [],
188
+ };
189
+
190
+ for (let i = 0; i < args.length; i++) {
191
+ if (args[i] === '--agent' || args[i] === '-a') {
192
+ const next = args[i + 1];
193
+ if (next === undefined || next.startsWith('-')) {
194
+ // Missing value — warn and skip this flag instead of crashing.
195
+ console.warn(
196
+ `⚠ Flag ${args[i]} is missing a value. Usage: ${args[i]} <agent-id>. Ignoring.`
197
+ );
198
+ continue;
199
+ }
200
+ opts.agentFlags.push(next);
201
+ i++;
202
+ }
203
+ }
204
+
205
+ return opts;
206
+ }
207
+
208
+ /**
209
+ * Resolve which agents to install based on flags or interactive prompt.
210
+ * @returns {Promise<string[]>} IDs of the selected agents
211
+ */
212
+ async function resolveSelectedAgents(opts, baseDir, chalk) {
213
+ if (opts.isAll) {
214
+ return Object.keys(AGENTS);
215
+ }
216
+
217
+ if (opts.agentFlags.length > 0) {
218
+ const known = opts.agentFlags.filter((a) => AGENTS[a]);
219
+ const unknown = opts.agentFlags.filter((a) => !AGENTS[a]);
220
+ if (unknown.length > 0) {
221
+ console.log(chalk.yellow(` Unknown agents: ${unknown.join(', ')}`));
222
+ console.log(chalk.gray(` Available agents: ${Object.keys(AGENTS).join(', ')}\n`));
223
+ }
224
+ return known;
225
+ }
226
+
227
+ if (opts.isYes) {
228
+ return Object.keys(AGENTS);
229
+ }
230
+
231
+ // Interactive mode — detect installed agents and prompt the user.
232
+ const detected = detectAgents(baseDir);
233
+ console.log(chalk.cyan(' Select the agents where you want to install:\n'));
234
+
235
+ const items = Object.entries(AGENTS).map(([id, agent]) => ({
236
+ id,
237
+ name: detected.includes(id) ? `${agent.name} ${chalk.green('(detected)')}` : agent.name,
238
+ }));
239
+
240
+ const rl = createReadline();
241
+ try {
242
+ return await selectMultiple(rl, items, detected);
243
+ } finally {
244
+ rl.close();
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Copy skills into the universal path first, then either symlink or copy
250
+ * each selected agent's skill directory to point at the universal copy.
251
+ * @returns {{agentResults: Array, copyFallbacks: number}}
252
+ */
253
+ function performInstall(skillsSourceDir, skillDirs, selectedAgents, baseDir) {
254
+ // Always install to the universal path first. This is the source of
255
+ // truth that all other agent dirs symlink to.
256
+ const universalTarget = path.join(baseDir, UNIVERSAL_DIR);
257
+ for (const skill of skillDirs) {
258
+ const src = path.join(skillsSourceDir, skill);
259
+ const dest = path.join(universalTarget, skill);
260
+ copySkillDir(src, dest);
261
+ }
262
+
263
+ const agentResults = [];
264
+ let copyFallbacks = 0;
265
+
266
+ for (const agentId of selectedAgents) {
267
+ const agent = AGENTS[agentId];
268
+ if (agent.dir === UNIVERSAL_DIR) continue; // Already handled above.
269
+
270
+ const agentTarget = path.join(baseDir, agent.dir);
271
+
272
+ // If a real directory already exists (not a symlink), copy into it
273
+ // directly so we don't destroy user data.
274
+ if (fs.existsSync(agentTarget) && !fs.lstatSync(agentTarget).isSymbolicLink()) {
275
+ for (const skill of skillDirs) {
276
+ copySkillDir(path.join(skillsSourceDir, skill), path.join(agentTarget, skill));
277
+ }
278
+ agentResults.push({ agent: agent.name, method: 'copied', dir: agent.dir });
279
+ continue;
280
+ }
281
+
282
+ const parentDir = path.dirname(agentTarget);
283
+ if (!fs.existsSync(parentDir)) {
284
+ fs.mkdirSync(parentDir, { recursive: true });
285
+ }
286
+
287
+ // Remove any pre-existing symlink so we can recreate it cleanly.
288
+ if (fs.existsSync(agentTarget) || fs.lstatSync(agentTarget, { throwIfNoEntry: false })) {
289
+ try {
290
+ fs.unlinkSync(agentTarget);
291
+ } catch (_) {
292
+ /* target didn't exist after all — that's fine */
293
+ }
294
+ }
295
+
296
+ try {
297
+ // Relative symlink from the agent's dir to the universal dir.
298
+ const relPath = path.relative(parentDir, universalTarget);
299
+ fs.symlinkSync(relPath, agentTarget);
300
+ agentResults.push({ agent: agent.name, method: 'symlinked', dir: agent.dir });
301
+ } catch (symlinkErr) {
302
+ // Windows without admin can't create symlinks. Fall back to copy
303
+ // and remember so we can warn the user at the end.
304
+ copyFallbacks++;
305
+ if (!fs.existsSync(agentTarget)) {
306
+ fs.mkdirSync(agentTarget, { recursive: true });
307
+ }
308
+ for (const skill of skillDirs) {
309
+ copySkillDir(path.join(skillsSourceDir, skill), path.join(agentTarget, skill));
310
+ }
311
+ agentResults.push({
312
+ agent: agent.name,
313
+ method: 'copied',
314
+ dir: agent.dir,
315
+ fallbackReason: symlinkErr.code || symlinkErr.message,
316
+ });
317
+ }
318
+ }
319
+
320
+ return { agentResults, copyFallbacks };
321
+ }
322
+
323
+ /**
324
+ * Configure the 2 MCP servers (powerbi-modeling + microsoft-learn)
325
+ * for each selected agent by writing the config file in the path and
326
+ * format that agent expects.
327
+ *
328
+ * Per-agent errors don't abort the whole flow: they're collected in the
329
+ * results array so the caller can display them and decide on the exit
330
+ * code.
331
+ *
332
+ * @param {string[]} selectedAgents - Agent IDs to configure
333
+ * @param {string} packageDir - Absolute path to the installed package
334
+ * @param {string} baseDir - User's home directory (for display)
335
+ * @param {Object} chalk - chalk instance for colored output
336
+ * @returns {Array<{agent: string, success: boolean, configPath?: string, error?: string}>}
337
+ */
338
+ function configureMcpsForAgents(selectedAgents, packageDir, baseDir, chalk) {
339
+ console.log(chalk.cyan('\n Configuring MCP servers (Power BI Modeling + Microsoft Learn)...\n'));
340
+
341
+ const results = [];
342
+ for (const agentId of selectedAgents) {
343
+ const agent = AGENTS[agentId];
344
+ try {
345
+ const configPath = writeMcpConfigForAgent(agentId, packageDir);
346
+ if (configPath) {
347
+ const relPath = configPath.replace(baseDir, '~');
348
+ console.log(chalk.green(` ✓ ${relPath} — ${agent.name}`));
349
+ results.push({ agent: agent.name, configPath, success: true });
350
+ }
351
+ } catch (err) {
352
+ console.log(chalk.red(` ✗ ${agent.name}: ${err.message}`));
353
+ results.push({ agent: agent.name, success: false, error: err.message });
354
+ }
355
+ }
356
+ return results;
357
+ }
358
+
359
+ /**
360
+ * Main handler for the `super install` command.
361
+ * @param {string[]} args - CLI arguments
362
+ * @param {Object} config - Command config from the CLI (packageDir, version)
363
+ */
364
+ async function installCommand(args, config) {
365
+ const chalk = require('chalk');
366
+ const boxen = require('boxen');
367
+
368
+ const opts = parseArgs(args);
369
+
370
+ // Always install at the user level (home directory) — skills and MCPs
371
+ // apply across all projects without polluting any specific repo.
372
+ const baseDir = os.homedir();
373
+
374
+ // Locate the skills inside the installed package.
375
+ const packageDir = config.packageDir || path.dirname(path.dirname(__dirname));
376
+ const skillsSourceDir = path.join(packageDir, 'skills');
377
+
378
+ if (!fs.existsSync(skillsSourceDir)) {
379
+ console.error(
380
+ chalk.red(
381
+ 'Skills directory not found. Reinstall the package with: npm install -g bi-superpowers'
382
+ )
383
+ );
384
+ process.exit(1);
385
+ }
386
+
387
+ // Read the available skill directories from the package.
388
+ let skillDirs;
389
+ try {
390
+ skillDirs = fs
391
+ .readdirSync(skillsSourceDir, { withFileTypes: true })
392
+ .filter(
393
+ (d) => d.isDirectory() && fs.existsSync(path.join(skillsSourceDir, d.name, 'SKILL.md'))
394
+ )
395
+ .map((d) => d.name);
396
+ } catch (err) {
397
+ console.error(chalk.red(formatFsError(err, 'Could not read skills')));
398
+ process.exit(1);
399
+ }
400
+
401
+ // Header box shown at the top of every install run.
402
+ console.log(
403
+ boxen(
404
+ chalk.bold.cyan('BI Agent Superpowers') +
405
+ chalk.gray(` v${config.version}`) +
406
+ '\n' +
407
+ chalk.gray('Multi-agent installer'),
408
+ {
409
+ padding: 1,
410
+ borderStyle: 'round',
411
+ borderColor: 'cyan',
412
+ }
413
+ )
414
+ );
415
+
416
+ console.log(chalk.gray(` Install path: ~/${UNIVERSAL_DIR}/`));
417
+ console.log(chalk.gray(` Skills available: ${skillDirs.length}\n`));
418
+
419
+ // Resolve which agents to configure.
420
+ const selectedAgents = await resolveSelectedAgents(opts, baseDir, chalk);
421
+
422
+ if (selectedAgents.length === 0) {
423
+ console.log(chalk.yellow('\n No agent selected. Nothing to install.'));
424
+ return;
425
+ }
426
+
427
+ console.log(
428
+ chalk.cyan(`\n Installing ${skillDirs.length} skills for ${selectedAgents.length} agents...\n`)
429
+ );
430
+
431
+ // Phase 1: copy skills and create symlinks per agent.
432
+ let agentResults;
433
+ let copyFallbacks;
434
+ try {
435
+ const result = performInstall(skillsSourceDir, skillDirs, selectedAgents, baseDir);
436
+ agentResults = result.agentResults;
437
+ copyFallbacks = result.copyFallbacks;
438
+ } catch (err) {
439
+ console.error(chalk.red(formatFsError(err, 'Skill installation failed')));
440
+ process.exit(1);
441
+ }
442
+
443
+ // Report on the universal skills path.
444
+ const universalAgents = selectedAgents
445
+ .filter((id) => AGENTS[id] && AGENTS[id].dir === UNIVERSAL_DIR)
446
+ .map((id) => AGENTS[id].name);
447
+ const universalSuffix = universalAgents.length > 0 ? ` — ${universalAgents.join(', ')}` : '';
448
+ console.log(chalk.green(` ✓ ${UNIVERSAL_DIR}/ (${skillDirs.length} skills)${universalSuffix}`));
449
+
450
+ // Report per agent.
451
+ for (const result of agentResults) {
452
+ const icon = result.method === 'symlinked' ? '→' : '✓';
453
+ console.log(chalk.green(` ${icon} ${result.dir}/ (${result.method}) — ${result.agent}`));
454
+ }
455
+
456
+ // Warn if any agent fell back from symlink to copy.
457
+ if (copyFallbacks > 0) {
458
+ console.log(
459
+ chalk.yellow(
460
+ `\n ⚠ ${copyFallbacks} agent(s) used copy fallback instead of symlink ` +
461
+ '(probably Windows without admin permissions).\n' +
462
+ " Re-run 'super install' after each upgrade; copied installs are mirrored and stale runtimes are removed."
463
+ )
464
+ );
465
+ }
466
+
467
+ // Phase 2: write the 2 MCP configs per agent.
468
+ const mcpResults = configureMcpsForAgents(selectedAgents, packageDir, baseDir, chalk);
469
+
470
+ // Build the final summary box.
471
+ const totalAgents = agentResults.length + (universalAgents.length > 0 ? 1 : 0);
472
+ const mcpSuccess = mcpResults.filter((r) => r.success).length;
473
+ const mcpFailures = mcpResults.filter((r) => !r.success);
474
+ const hasFailures = mcpFailures.length > 0;
475
+
476
+ const successMsg = `Installed ${skillDirs.length} skills + 2 MCPs for ${totalAgents} agents`;
477
+ const failureMsg = `Installed ${skillDirs.length} skills. MCPs: ${mcpSuccess}/${mcpResults.length} agents ok, ${mcpFailures.length} failed.`;
478
+ const headerLine = hasFailures ? chalk.yellow.bold(failureMsg) : chalk.green.bold(successMsg);
479
+
480
+ const failureDetail = hasFailures
481
+ ? '\n' +
482
+ chalk.red('Agents with MCP errors:') +
483
+ '\n' +
484
+ mcpFailures.map((r) => chalk.red(` ✗ ${r.agent}: ${r.error}`)).join('\n') +
485
+ '\n'
486
+ : '';
487
+
488
+ const skillSummary = skillDirs
489
+ .map((skillName) => ` /${skillName.padEnd(15)} — ${getSkillPurpose(skillName)}`)
490
+ .join('\n');
491
+
492
+ console.log(
493
+ boxen(
494
+ headerLine +
495
+ failureDetail +
496
+ '\n\n' +
497
+ chalk.gray(`MCPs configured in ${mcpSuccess}/${mcpResults.length} agents.`) +
498
+ '\n' +
499
+ chalk.gray('Restart your AI agent so it loads the new MCP configuration.') +
500
+ '\n\n' +
501
+ chalk.gray(`Skills available (${skillDirs.length}):`) +
502
+ '\n' +
503
+ chalk.gray(skillSummary),
504
+ {
505
+ padding: 1,
506
+ margin: { top: 1 },
507
+ borderStyle: 'round',
508
+ borderColor: hasFailures ? 'yellow' : 'green',
509
+ }
510
+ )
511
+ );
512
+
513
+ // Opt-in: register the Claude Code SessionStart auto-update hook.
514
+ if (opts.autoUpdate) {
515
+ try {
516
+ const { enableAutoupdate } = require('./autoupdate');
517
+ enableAutoupdate(packageDir);
518
+ console.log(
519
+ chalk.green('\n ✓ Auto-update enabled (Claude Code SessionStart hook).') +
520
+ chalk.gray('\n New Claude Code sessions self-update via npm (throttled, background).')
521
+ );
522
+ } catch (err) {
523
+ console.log(chalk.yellow(`\n ⚠ Could not enable auto-update: ${err.message}`));
524
+ }
525
+ }
526
+
527
+ if (hasFailures) {
528
+ // Non-zero exit so CI/scripts know something went wrong. Exit code 2
529
+ // distinguishes partial failure (skills ok, some MCPs failed) from
530
+ // total failure (exit code 1).
531
+ process.exitCode = 2;
532
+ }
533
+ }
534
+
535
+ // Internal exports for testing.
536
+ module.exports = installCommand;
537
+ module.exports.parseArgs = parseArgs;
538
+ module.exports.detectAgents = detectAgents;
539
+ module.exports.copySkillDir = copySkillDir;
540
+ module.exports.formatFsError = formatFsError;
541
+ module.exports.AGENTS = AGENTS;
542
+ module.exports.UNIVERSAL_DIR = UNIVERSAL_DIR;