@luquimbo/bi-superpowers 3.1.1 → 4.1.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 (186) hide show
  1. package/.claude-plugin/marketplace.json +5 -3
  2. package/.claude-plugin/plugin.json +28 -2
  3. package/.claude-plugin/skill-manifest.json +22 -6
  4. package/.plugin/plugin.json +1 -1
  5. package/AGENTS.md +52 -36
  6. package/CHANGELOG.md +295 -0
  7. package/README.md +75 -26
  8. package/bin/build-plugin.js +17 -10
  9. package/bin/cli.js +278 -322
  10. package/bin/commands/build-desktop.js +35 -16
  11. package/bin/commands/diff.js +31 -13
  12. package/bin/commands/install.js +93 -72
  13. package/bin/commands/lint.js +40 -26
  14. package/bin/commands/mcp-setup.js +3 -10
  15. package/bin/commands/update-check.js +389 -0
  16. package/bin/lib/agents.js +19 -0
  17. package/bin/lib/generators/claude-plugin.js +144 -6
  18. package/bin/lib/generators/shared.js +29 -33
  19. package/bin/lib/mcp-config.js +191 -16
  20. package/bin/lib/skills.js +115 -27
  21. package/bin/postinstall.js +4 -2
  22. package/bin/utils/mcp-detect.js +2 -2
  23. package/commands/bi-start.md +218 -0
  24. package/commands/pbi-connect.md +43 -65
  25. package/commands/project-kickoff.md +393 -673
  26. package/commands/report-design.md +403 -0
  27. package/desktop-extension/manifest.json +5 -12
  28. package/desktop-extension/server.js +34 -25
  29. package/package.json +6 -10
  30. package/skills/bi-start/SKILL.md +220 -0
  31. package/skills/bi-start/scripts/update-check.js +389 -0
  32. package/skills/pbi-connect/SKILL.md +45 -67
  33. package/skills/pbi-connect/scripts/update-check.js +389 -0
  34. package/skills/project-kickoff/SKILL.md +395 -675
  35. package/skills/project-kickoff/scripts/update-check.js +389 -0
  36. package/skills/report-design/SKILL.md +405 -0
  37. package/skills/report-design/references/cli-commands.md +184 -0
  38. package/skills/report-design/references/cli-setup.md +101 -0
  39. package/skills/report-design/references/close-write-open-pattern.md +80 -0
  40. package/skills/report-design/references/layouts/finance.md +65 -0
  41. package/skills/report-design/references/layouts/generic.md +46 -0
  42. package/skills/report-design/references/layouts/hr.md +48 -0
  43. package/skills/report-design/references/layouts/marketing.md +45 -0
  44. package/skills/report-design/references/layouts/operations.md +44 -0
  45. package/skills/report-design/references/layouts/sales.md +50 -0
  46. package/skills/report-design/references/native-visuals.md +341 -0
  47. package/skills/report-design/references/pbi-desktop-installation.md +87 -0
  48. package/skills/report-design/references/pbir-preview-activation.md +40 -0
  49. package/skills/report-design/references/slicer.md +89 -0
  50. package/skills/report-design/references/textbox.md +101 -0
  51. package/skills/report-design/references/themes/BISuperpowers.json +915 -0
  52. package/skills/report-design/references/troubleshooting.md +135 -0
  53. package/skills/report-design/references/visual-types.md +78 -0
  54. package/skills/report-design/scripts/apply-theme.js +243 -0
  55. package/skills/report-design/scripts/create-visual.js +878 -0
  56. package/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
  57. package/skills/report-design/scripts/update-check.js +389 -0
  58. package/skills/report-design/scripts/validate-pbir.js +322 -0
  59. package/src/content/base.md +12 -68
  60. package/src/content/mcp-requirements.json +0 -25
  61. package/src/content/routing.md +19 -74
  62. package/src/content/skills/bi-start.md +191 -0
  63. package/src/content/skills/pbi-connect.md +22 -65
  64. package/src/content/skills/project-kickoff.md +372 -673
  65. package/src/content/skills/report-design/SKILL.md +376 -0
  66. package/src/content/skills/report-design/references/cli-commands.md +184 -0
  67. package/src/content/skills/report-design/references/cli-setup.md +101 -0
  68. package/src/content/skills/report-design/references/close-write-open-pattern.md +80 -0
  69. package/src/content/skills/report-design/references/layouts/finance.md +65 -0
  70. package/src/content/skills/report-design/references/layouts/generic.md +46 -0
  71. package/src/content/skills/report-design/references/layouts/hr.md +48 -0
  72. package/src/content/skills/report-design/references/layouts/marketing.md +45 -0
  73. package/src/content/skills/report-design/references/layouts/operations.md +44 -0
  74. package/src/content/skills/report-design/references/layouts/sales.md +50 -0
  75. package/src/content/skills/report-design/references/native-visuals.md +341 -0
  76. package/src/content/skills/report-design/references/pbi-desktop-installation.md +87 -0
  77. package/src/content/skills/report-design/references/pbir-preview-activation.md +40 -0
  78. package/src/content/skills/report-design/references/slicer.md +89 -0
  79. package/src/content/skills/report-design/references/textbox.md +101 -0
  80. package/src/content/skills/report-design/references/themes/BISuperpowers.json +915 -0
  81. package/src/content/skills/report-design/references/troubleshooting.md +135 -0
  82. package/src/content/skills/report-design/references/visual-types.md +78 -0
  83. package/src/content/skills/report-design/scripts/apply-theme.js +243 -0
  84. package/src/content/skills/report-design/scripts/create-visual.js +878 -0
  85. package/src/content/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
  86. package/src/content/skills/report-design/scripts/validate-pbir.js +322 -0
  87. package/bin/commands/add.js +0 -533
  88. package/bin/commands/add.test.js +0 -77
  89. package/bin/commands/changelog.js +0 -443
  90. package/bin/commands/install.test.js +0 -289
  91. package/bin/commands/lint.test.js +0 -103
  92. package/bin/commands/pull.js +0 -287
  93. package/bin/commands/pull.test.js +0 -36
  94. package/bin/commands/push.js +0 -231
  95. package/bin/commands/push.test.js +0 -14
  96. package/bin/commands/search.js +0 -344
  97. package/bin/commands/search.test.js +0 -115
  98. package/bin/commands/setup.js +0 -545
  99. package/bin/commands/setup.test.js +0 -46
  100. package/bin/commands/sync-profile.js +0 -405
  101. package/bin/commands/sync-profile.test.js +0 -14
  102. package/bin/commands/sync-source.js +0 -418
  103. package/bin/commands/sync-source.test.js +0 -14
  104. package/bin/lib/generators/claude-plugin.test.js +0 -111
  105. package/bin/lib/mcp-config.test.js +0 -310
  106. package/bin/lib/microsoft-mcp.test.js +0 -115
  107. package/bin/utils/errors.js +0 -159
  108. package/bin/utils/git.js +0 -298
  109. package/bin/utils/logger.js +0 -142
  110. package/bin/utils/mcp-detect.test.js +0 -81
  111. package/bin/utils/pbix.js +0 -305
  112. package/bin/utils/pbix.test.js +0 -37
  113. package/bin/utils/profiles.js +0 -312
  114. package/bin/utils/projects.js +0 -169
  115. package/bin/utils/readline.js +0 -206
  116. package/bin/utils/readline.test.js +0 -47
  117. package/bin/utils/tui.test.js +0 -127
  118. package/docs/openrouter-free-models.md +0 -92
  119. package/library/examples/README.md +0 -151
  120. package/library/examples/finance-reporting/README.md +0 -351
  121. package/library/examples/finance-reporting/data-model.md +0 -267
  122. package/library/examples/finance-reporting/measures.dax +0 -557
  123. package/library/examples/hr-analytics/README.md +0 -371
  124. package/library/examples/hr-analytics/data-model.md +0 -315
  125. package/library/examples/hr-analytics/measures.dax +0 -460
  126. package/library/examples/marketing-analytics/README.md +0 -37
  127. package/library/examples/marketing-analytics/data-model.md +0 -62
  128. package/library/examples/marketing-analytics/measures.dax +0 -110
  129. package/library/examples/retail-analytics/README.md +0 -439
  130. package/library/examples/retail-analytics/data-model.md +0 -288
  131. package/library/examples/retail-analytics/measures.dax +0 -481
  132. package/library/examples/supply-chain/README.md +0 -37
  133. package/library/examples/supply-chain/data-model.md +0 -69
  134. package/library/examples/supply-chain/measures.dax +0 -77
  135. package/library/examples/udf-library/README.md +0 -228
  136. package/library/examples/udf-library/functions.dax +0 -571
  137. package/library/snippets/dax/README.md +0 -292
  138. package/library/snippets/dax/business-domains.md +0 -576
  139. package/library/snippets/dax/calculate-patterns.md +0 -276
  140. package/library/snippets/dax/calculation-groups.md +0 -489
  141. package/library/snippets/dax/error-handling.md +0 -495
  142. package/library/snippets/dax/iterators-and-aggregations.md +0 -474
  143. package/library/snippets/dax/kpis-and-metrics.md +0 -293
  144. package/library/snippets/dax/rankings-and-topn.md +0 -235
  145. package/library/snippets/dax/security-patterns.md +0 -413
  146. package/library/snippets/dax/text-and-formatting.md +0 -316
  147. package/library/snippets/dax/time-intelligence.md +0 -196
  148. package/library/snippets/dax/user-defined-functions.md +0 -477
  149. package/library/snippets/dax/virtual-tables.md +0 -546
  150. package/library/snippets/excel-formulas/README.md +0 -84
  151. package/library/snippets/excel-formulas/aggregations.md +0 -330
  152. package/library/snippets/excel-formulas/dates-and-times.md +0 -361
  153. package/library/snippets/excel-formulas/dynamic-arrays.md +0 -314
  154. package/library/snippets/excel-formulas/lookups.md +0 -169
  155. package/library/snippets/excel-formulas/text-functions.md +0 -363
  156. package/library/snippets/governance/naming-conventions.md +0 -97
  157. package/library/snippets/governance/review-checklists.md +0 -107
  158. package/library/snippets/power-query/README.md +0 -389
  159. package/library/snippets/power-query/api-integration.md +0 -707
  160. package/library/snippets/power-query/connections.md +0 -434
  161. package/library/snippets/power-query/data-cleaning.md +0 -298
  162. package/library/snippets/power-query/error-handling.md +0 -526
  163. package/library/snippets/power-query/parameters.md +0 -350
  164. package/library/snippets/power-query/performance.md +0 -506
  165. package/library/snippets/power-query/transformations.md +0 -330
  166. package/library/snippets/report-design/accessibility.md +0 -78
  167. package/library/snippets/report-design/chart-selection.md +0 -54
  168. package/library/snippets/report-design/layout-patterns.md +0 -87
  169. package/library/templates/data-models/README.md +0 -93
  170. package/library/templates/data-models/finance-model.md +0 -627
  171. package/library/templates/data-models/retail-star-schema.md +0 -473
  172. package/library/templates/excel/README.md +0 -83
  173. package/library/templates/excel/budget-tracker.md +0 -432
  174. package/library/templates/excel/data-entry-form.md +0 -533
  175. package/library/templates/power-bi/README.md +0 -72
  176. package/library/templates/power-bi/finance-report.md +0 -449
  177. package/library/templates/power-bi/kpi-scorecard.md +0 -461
  178. package/library/templates/power-bi/sales-dashboard.md +0 -281
  179. package/library/themes/excel/README.md +0 -436
  180. package/library/themes/power-bi/README.md +0 -271
  181. package/library/themes/power-bi/accessible.json +0 -307
  182. package/library/themes/power-bi/bi-superpowers-default.json +0 -858
  183. package/library/themes/power-bi/corporate-blue.json +0 -291
  184. package/library/themes/power-bi/dark-mode.json +0 -291
  185. package/library/themes/power-bi/minimal.json +0 -292
  186. package/library/themes/power-bi/print-friendly.json +0 -309
package/bin/cli.js CHANGED
@@ -1,21 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * BI Agent Superpowers - Command Line Interface
4
+ * BI Agent Superpowers Command Line Interface
5
5
  * ==============================================
6
6
  *
7
- * This is the main entry point for the BI Agent Superpowers CLI tool.
8
- * It provides commands to initialize, configure, and manage AI-powered
9
- * assistance for Power BI, Fabric, and Excel development.
7
+ * Main entry point for the `super` CLI. Provides commands to install
8
+ * skills and MCP servers into AI coding agents, and to generate the
9
+ * native Claude Code plugin into a project.
10
10
  *
11
11
  * Architecture:
12
- * - Single Source of Truth: Skills are defined ONCE in src/content/skills/
13
- * and generated for the Claude Code plugin.
14
- * - Supports: Claude Code, 1code.dev, Claude Desktop (via MCPB).
12
+ * - Skills are authored once in src/content/skills/ and copied out to
13
+ * each supported agent by `super install`.
14
+ * - `super kickoff` generates a full Claude Code plugin tree in a
15
+ * user project (skills + commands + MCP config).
16
+ * - `super recharge` regenerates that plugin after local edits.
15
17
  *
16
- * Licensing:
17
- * - Open source (MIT) — no license activation required
18
- * - All skills and library content ship with the npm package
18
+ * Supported agents: Claude Code, GitHub Copilot, Codex, Gemini CLI, Kilo Code.
19
+ * License: MIT. This project is fully open source — no activation, no keys.
19
20
  *
20
21
  * @module cli
21
22
  * @author Lucas Sanchez (@luquimbo)
@@ -27,114 +28,124 @@ const path = require('path');
27
28
  const { execSync } = require('child_process');
28
29
  const { loadSkills } = require('./lib/skills');
29
30
 
30
- // Import lib modules (extracted from cli.js for better organization)
31
+ // Background update check. update-notifier spawns a detached child process
32
+ // that fetches the latest version from npm and caches it; the banner that
33
+ // `notify()` schedules is printed at process exit, so this is zero-latency
34
+ // on the command path. Errors are swallowed silently — the CLI must not
35
+ // break because of a failed update check.
36
+ let _updateNotifierNotify = null;
37
+ try {
38
+ const updateNotifier = require('update-notifier');
39
+ const pkg = require('../package.json');
40
+ const notifier = updateNotifier({
41
+ pkg,
42
+ updateCheckInterval: 1000 * 60 * 60 * 24, // 24h
43
+ shouldNotifyInNpmScript: false,
44
+ });
45
+ _updateNotifierNotify = () =>
46
+ notifier.notify({
47
+ defer: true,
48
+ isGlobal: true,
49
+ message:
50
+ 'Update available {currentVersion} → {latestVersion}\n' +
51
+ 'Run {updateCommand} to update,\n' +
52
+ 'then `super install --yes` to propagate the new skills.',
53
+ });
54
+ } catch (_) {
55
+ // update-notifier not available during npm install phase, or network
56
+ // probe failed — skip silently.
57
+ }
58
+
59
+ // Optional lib import — may not be available during npm install phase.
31
60
  let generators;
32
61
  try {
33
62
  generators = require('./lib/generators');
34
- } catch (e) {
35
- // Modules may not be available during npm install phase
63
+ } catch (_) {
64
+ // Silent fallback; commands will report a useful error when invoked.
36
65
  }
37
66
 
38
- // Import command modules - these provide the xray, checkup, scan, sentinel, and mcp-setup commands
39
- // Wrapped in try-catch because they may not be available during initial npm install
40
- let searchCommand, lintCommand, diffCommand, watchCommand, mcpSetupCommand, tui;
41
- let setupCommand, addCommand, pullCommand, pushCommand, syncProfileCommand, syncSourceCommand;
42
- let changelogCommand, buildDesktopCommand, installCommand;
67
+ // Optional command imports each module may fail to load during npm
68
+ // install before dependencies are wired up. The CLI still renders `help`
69
+ // and `version` because those are hoisted, module-free functions.
70
+ let lintCommand;
71
+ let diffCommand;
72
+ let watchCommand;
73
+ let mcpSetupCommand;
74
+ let buildDesktopCommand;
75
+ let installCommand;
76
+ let tui;
43
77
  try {
44
- searchCommand = require('./commands/search'); // Fuzzy search across library content
45
- lintCommand = require('./commands/lint'); // Skill file validation
46
- diffCommand = require('./commands/diff'); // Compare source vs generated configs
47
- watchCommand = require('./commands/watch'); // Auto-regenerate on file changes
78
+ lintCommand = require('./commands/lint'); // checkup: skill file validation
79
+ diffCommand = require('./commands/diff'); // scan: diff source vs generated
80
+ watchCommand = require('./commands/watch'); // sentinel: watch + auto regen
48
81
  mcpSetupCommand = require('./commands/mcp-setup'); // MCP server configuration
49
- tui = require('./utils/tui'); // Terminal UI helpers (colors, tables, etc.)
50
-
51
- // Repo multi-project commands (v3)
52
- setupCommand = require('./commands/setup'); // Onboarding wizard for bi-repo
53
- addCommand = require('./commands/add'); // Add project to repo
54
- pullCommand = require('./commands/pull'); // Pull changes from original file
55
- pushCommand = require('./commands/push'); // Push changes to original file
56
- syncProfileCommand = require('./commands/sync-profile'); // Sync snippets to profile
57
- syncSourceCommand = require('./commands/sync-source'); // Bidirectional sync
58
- changelogCommand = require('./commands/changelog'); // Generate changelog from Git
59
- buildDesktopCommand = require('./commands/build-desktop'); // Build MCPB for Claude Desktop
60
- installCommand = require('./commands/install'); // Multi-agent skill installer
61
- } catch (e) {
62
- // Silent fail - commands may not be available during npm install phase
63
- // This is expected behavior, not an error condition
82
+ buildDesktopCommand = require('./commands/build-desktop'); // .mcpb for Claude Desktop
83
+ installCommand = require('./commands/install'); // multi-agent skill + MCP installer
84
+ tui = require('./utils/tui'); // colors, tables, boxes for CLI output
85
+ } catch (_) {
86
+ // Expected during `npm install` modules become available after deps are linked.
64
87
  }
65
88
 
66
89
  // ============================================
67
90
  // CONFIGURATION CONSTANTS
68
91
  // ============================================
69
92
 
70
- /** Package version from package.json */
93
+ /** Package version (read from package.json at runtime) */
71
94
  const VERSION = require('../package.json').version;
72
95
 
73
- /** Dynamic skill/command counts from the plugin generator (avoids hardcoding) */
74
- let COMMAND_COUNT = 11;
75
- let TOTAL_SKILL_COUNT = 24;
96
+ /**
97
+ * Skill and command counts used by the help text and dry-run previews.
98
+ * Pulled dynamically from the generator so we never hardcode outdated totals.
99
+ */
100
+ let COMMAND_COUNT = 0;
101
+ let TOTAL_SKILL_COUNT = 0;
76
102
  try {
77
103
  const { COMMAND_SKILLS, REFERENCE_SKILLS } = require('./lib/generators/claude-plugin');
78
104
  COMMAND_COUNT = COMMAND_SKILLS.size;
79
105
  TOTAL_SKILL_COUNT = COMMAND_SKILLS.size + REFERENCE_SKILLS.size;
80
106
  } catch (_) {
81
- // Fallback to defaults during npm install phase
107
+ // Fallback during npm install phase — values stay at 0 until the module loads.
82
108
  }
83
109
 
84
- /** Directory where the npm package is installed */
110
+ /** Absolute path to the installed package directory (one level above bin/) */
85
111
  const PACKAGE_DIR = path.dirname(__dirname);
86
112
 
87
- /** Directory containing skill source files (.md) */
113
+ /** Directory containing the authoring source for each skill */
88
114
  const SKILLS_DIR = path.join(PACKAGE_DIR, 'src', 'content', 'skills');
89
115
 
90
- /** Directory containing code snippets, templates, and themes */
91
- const LIBRARY_DIR = path.join(PACKAGE_DIR, 'library');
92
-
93
- /** Project-local config file name (stores tool selections) */
116
+ /** Project-local config file name used by kickoff/recharge */
94
117
  const CONFIG_FILE = '.bi-superpowers.json';
95
118
 
96
- /** npm package name for update commands */
119
+ /** npm package name for the upgrade command */
97
120
  const PACKAGE_NAME = '@luquimbo/bi-superpowers';
121
+
122
+ /** Default tool set generated by kickoff (currently only the Claude Code plugin) */
98
123
  const DEFAULT_TOOLS = ['claude-plugin'];
99
124
 
100
- /**
101
- * AI Tools Configuration - uses generators from lib/generators module
102
- * Falls back to empty object if module not loaded
103
- */
125
+ /** Generator registry (populated from lib/generators if available) */
104
126
  const AI_TOOLS = generators ? generators.AI_TOOLS : {};
105
127
 
106
- /**
107
- * Command Routing Map
108
- *
109
- * Maps CLI command names to their handler functions.
110
- * Supports both branded names (kickoff, recharge) and legacy names (init, sync)
111
- * for backward compatibility.
112
- *
113
- * Command Categories:
114
- * - Core: Basic info commands (help, version, about, status)
115
- * - Setup: Project initialization and configuration (kickoff, recharge, upgrade)
116
- * - Developer: Advanced tools for content management (xray, checkup, scan, sentinel, powers)
117
- * - Legacy: Old command names maintained for backward compatibility
118
- */
119
- // Commands are registered in two phases to avoid TDZ (temporal dead zone) errors.
120
- // Phase 1: hoisted function declarations (showHelp, initProject, etc.) go directly
121
- // into the object literal below — safe because `function` declarations hoist.
122
- // Phase 2: wrapper-based commands that depend on `createCommandWrapper` (defined
123
- // further down in the file) are attached imperatively after that function exists.
124
- // See the `commands.xray = runSearch;` block after the wrapper `const`s.
128
+ // ============================================
129
+ // COMMAND ROUTING
130
+ // ============================================
131
+ // Commands are registered in two phases to avoid temporal-dead-zone errors.
132
+ // Phase 1: hoisted function declarations (help, version, about, kickoff...)
133
+ // go directly into the object literal below.
134
+ // Phase 2: wrapper-based commands that depend on createCommandWrapper
135
+ // (defined further below) are attached imperatively.
125
136
  const commands = {
126
- // Core commands - basic info (hoisted functions, safe here)
137
+ // Core commands hoisted functions, safe to reference here.
127
138
  help: showHelp,
128
139
  version: showVersion,
129
140
  about: showInfo,
130
141
 
131
- // Setup & sync - project configuration (hoisted functions, safe here)
142
+ // Primary flow also hoisted functions.
132
143
  kickoff: initProject,
133
144
  recharge: syncProject,
134
145
  upgrade: updatePackage,
135
146
  powers: listAgents,
136
147
 
137
- // Legacy aliases (hoisted functions, safe here)
148
+ // Legacy aliases kept for backwards compatibility.
138
149
  init: initProject,
139
150
  sync: syncProject,
140
151
  update: updatePackage,
@@ -143,12 +154,20 @@ const commands = {
143
154
  };
144
155
 
145
156
  /**
146
- * Main entry point - parses CLI arguments and routes to appropriate command
157
+ * Main entry point parses CLI arguments and routes to the handler.
147
158
  */
148
159
  function main() {
149
160
  const args = process.argv.slice(2);
150
161
  const command = args[0] || 'help';
151
162
 
163
+ // Schedule the update-notifier banner to print at process exit. Only fire
164
+ // for "normal" commands — skipping machine-readable and ultra-hot paths so
165
+ // tools that parse super output don't get surprised by the banner.
166
+ const SKIP_NOTIFY_COMMANDS = new Set(['version', 'help', 'about', 'info']);
167
+ if (_updateNotifierNotify && !SKIP_NOTIFY_COMMANDS.has(command)) {
168
+ _updateNotifierNotify();
169
+ }
170
+
152
171
  if (commands[command]) {
153
172
  commands[command](args.slice(1));
154
173
  } else {
@@ -163,67 +182,47 @@ function showHelp() {
163
182
  BI Agent Superpowers v${VERSION}
164
183
  ================================
165
184
 
166
- Claude Code plugin for Power BI, Fabric & Excel development.
185
+ Open-source toolkit for Power BI Desktop development across 5 AI coding agents:
186
+ Claude Code · GitHub Copilot · Codex · Gemini CLI · Kilo Code.
167
187
 
168
188
  Quick Start:
169
- super kickoff # Genera el plugin en tu proyecto
170
- claude --plugin-dir . # Abrí Claude Code con el plugin
189
+ super install # Install skills + MCPs for all your AI agents
190
+ super kickoff # Generate the Claude Code plugin in a project
171
191
 
172
192
  Usage:
173
193
  super <command> [options]
174
194
 
175
- Primary commands (Claude Code):
176
- kickoff [path] Genera el plugin completo (skills + commands + MCPs)
177
- recharge [path] Regenerá el plugin tras editar skills fuente
178
- build-desktop Buildea la extensión .mcpb para Claude Desktop
179
- mcp-setup Configurá los MCP servers de Microsoft
180
- powers Listá skills y recursos disponibles
181
- upgrade Actualizá a la última versión
182
- about Info de la instalación
183
- help Mostrá esta ayuda
195
+ Primary commands:
196
+ install Install the 4 skills + 2 MCPs across your AI agents
197
+ kickoff [path] Generate the full Claude Code plugin in a project
198
+ recharge [path] Regenerate the plugin after editing source skills
199
+ build-desktop Build the .mcpb extension for Claude Desktop
200
+ mcp-setup Configure the official Microsoft MCP servers
201
+ powers List available skills and MCPs
202
+ upgrade Update to the latest version on npm
203
+ about Show installation info
204
+ help Show this help
184
205
 
185
206
  Developer tools:
186
- xray <query> Buscá snippets y contenido de la biblioteca
187
- checkup [file] Validá archivos de skills
188
- scan Diff entre source y generated
189
- sentinel Watch y auto-regenerá
190
-
191
- Repo Multi-Proyecto:
192
- setup Creá tu bi-repo para version control
193
- add <file> Agregá un proyecto .pbix/.xlsx al repo
194
- pull [project] Pull changes desde el archivo original
195
- push [project] Push changes al archivo original
196
- sync-source Bidirectional sync (detecta cuál es más nuevo)
197
- sync-profile Sync snippets al profile base
198
-
199
- Experimental (solo skills, sin commands ni MCPs):
200
- install Instalá skills en otros agentes AI (Copilot, Codex, Gemini, Kilo)
207
+ checkup [file] Lint/validate skill source files
208
+ scan Diff between source skills and generated plugin
209
+ sentinel Watch skill sources and auto-regenerate
201
210
 
202
211
  Options:
203
- --dry-run Preview de cambios sin escribir archivos (kickoff, recharge)
212
+ --dry-run Preview changes without writing files (kickoff, recharge)
204
213
 
205
214
  Examples:
206
- super kickoff # Inicializá el plugin en el directorio actual
207
- super kickoff ./my-project # Inicializá en un directorio específico
208
- super kickoff --dry-run # Preview de qué archivos se crearían
209
- super recharge # Regenerá el plugin tras editar skills
210
- super build-desktop # Buildeá .mcpb para Claude Desktop
211
- super mcp-setup # Configurá los MCPs de Microsoft
212
- super powers # Mostrá todos los skills disponibles
213
- claude --plugin-dir . # Corré Claude Code con el plugin
214
-
215
- super install # [Experimental] Instalá skills en otros agentes
216
- super install -a claude-code # Instalá solo para un agente específico
217
-
218
- Repo Multi-Proyecto:
219
- super setup # Create your bi-repo (first time)
220
- super add "Sales.pbix" # Add project to repo
221
- super pull # Pull changes from original
222
- super push # Push changes to original
223
- super sync-source # Auto-detect and sync
224
- super sync-profile # Save snippets to profile
225
-
226
- Open source — MIT licensed
215
+ super install # Interactive installer for all agents
216
+ super install --all --yes # Non-interactive install for every agent
217
+ super install -a claude-code # Install only for Claude Code
218
+ super kickoff # Initialize plugin in current directory
219
+ super kickoff ./my-project # Initialize in a specific directory
220
+ super kickoff --dry-run # Preview what would be created
221
+ super recharge # Regenerate plugin after editing skills
222
+ super build-desktop # Build .mcpb for Claude Desktop
223
+ super mcp-setup # Configure the local Power BI Modeling MCP
224
+
225
+ Open source MIT licensed.
227
226
  Documentation: https://github.com/luquimbo/bi-superpowers
228
227
  `);
229
228
  }
@@ -235,11 +234,11 @@ function showVersion() {
235
234
  function showInfo() {
236
235
  const skillCount = getSkillFiles().length;
237
236
  const aiToolsList = Object.entries(AI_TOOLS)
238
- .map(([_k, v]) => ` - ${v.name}`)
237
+ .map(([, v]) => ` - ${v.name}`)
239
238
  .join('\n');
240
239
 
241
240
  console.log(`
242
- BI Agent Superpowers - Installation Info
241
+ BI Agent Superpowers Installation Info
243
242
  ========================================
244
243
 
245
244
  Version: ${VERSION}
@@ -248,62 +247,41 @@ Package dir: ${PACKAGE_DIR}
248
247
  Skills: ${skillCount} available
249
248
  License: MIT (open source)
250
249
 
251
- Architecture: Single Source of Truth
252
- Skills defined once, generated for the Claude Code plugin
250
+ Supported AI agents:
251
+ - Claude Code (native plugin + MCP)
252
+ - GitHub Copilot (agent skills + MCP)
253
+ - Codex (OpenAI) (agent skills + MCP)
254
+ - Gemini CLI (agent skills + MCP)
255
+ - Kilo Code (agent skills + MCP)
253
256
 
254
- Compatible with:
255
- - Claude Code (plugin)
256
- - GitHub Copilot (agent skills)
257
- - Codex (OpenAI)
258
- - Gemini CLI
259
- - Kilo Code
260
- - Claude Desktop (via MCPB extension)
261
-
262
- Plugin Generators:
257
+ Plugin generators:
263
258
  ${aiToolsList}
264
259
 
265
260
  GitHub: https://github.com/luquimbo/bi-superpowers
266
261
  `);
267
262
  }
268
263
 
269
- // ============================================
270
- // LICENSE MANAGEMENT
271
- // ============================================
272
264
  // ============================================
273
265
  // SKILL FILE MANAGEMENT
274
266
  // ============================================
275
- // Functions for reading and parsing skill definition files.
276
- // Skills are markdown files in src/content/skills/ that define
277
- // AI assistant behaviors, triggers, and code patterns.
278
267
 
279
268
  /**
280
- * Get all skill files from the source directory
281
- *
282
- * Reads all .md files from the skills directory and returns their metadata.
283
- * Each skill file contains:
284
- * - Trigger keywords that activate the skill
285
- * - Identity/role description for the AI
286
- * - Mandatory rules and constraints
287
- * - Code examples and patterns
288
- *
289
- * @returns {Array<{name: string, path: string, content: string}>} Array of skill objects
269
+ * Load all skill source files from the package.
270
+ * @returns {Array<{name: string, path: string, content: string}>}
290
271
  */
291
272
  function getSkillFiles() {
292
- return loadSkills({
293
- packageDir: PACKAGE_DIR,
294
- preferLocal: true,
295
- });
273
+ return loadSkills({ packageDir: PACKAGE_DIR });
296
274
  }
297
275
 
298
276
  /**
299
- * Extract skill metadata from markdown content
300
- * Delegates to generators module if available
277
+ * Extract lightweight metadata (title, triggers, identity) from a skill's
278
+ * markdown content. Delegates to the generators module when available.
301
279
  */
302
280
  function parseSkillMetadata(content) {
303
281
  if (generators && generators.parseSkillMetadata) {
304
282
  return generators.parseSkillMetadata(content);
305
283
  }
306
- // Fallback for when module not loaded
284
+ // Minimal fallback when the module isn't loaded yet.
307
285
  const metadata = { title: '', triggers: [], identity: '' };
308
286
  const titleMatch = content.match(/^#\s+(.+)/m);
309
287
  if (titleMatch) metadata.title = titleMatch[1];
@@ -311,23 +289,20 @@ function parseSkillMetadata(content) {
311
289
  }
312
290
 
313
291
  // ============================================
314
- // PROJECT INITIALIZATION
292
+ // PROJECT INITIALIZATION (kickoff / recharge)
315
293
  // ============================================
316
- // Functions for setting up BI Agent Superpowers in a user's project.
317
- // This involves generating tool-specific config files and saving preferences.
318
294
 
319
295
  /**
320
- * Initialize project with interactive prompts (super kickoff)
296
+ * `super kickoff` generate the Claude Code plugin in the target directory.
321
297
  *
322
- * This is the main setup wizard that:
323
- * 1. Generates config files for the Claude Code plugin in the target directory
324
- * 2. Saves the selected tools to .bi-superpowers.json
325
- * 3. Copies a default config.json template if none exists
298
+ * What it does:
299
+ * 1. Generates .claude-plugin/, .mcp.json, commands/, skills/ in the target.
300
+ * 2. Writes .bi-superpowers.json tracking tool selections.
301
+ * 3. Copies a default config.json template if none exists yet.
326
302
  *
327
- * Supports --dry-run flag to preview changes without writing files.
303
+ * Supports --dry-run to preview without writing files.
328
304
  *
329
- * @param {string[]} args - Command line arguments
330
- * @param {string} [args[0]] - Target directory (defaults to cwd)
305
+ * @param {string[]} args - CLI arguments (first positional = target dir)
331
306
  */
332
307
  async function initProject(args) {
333
308
  const dryRun = hasDryRunFlag(args);
@@ -345,7 +320,6 @@ Initializing in: ${targetDir}
345
320
  Skills available: ${skills.length}
346
321
  `);
347
322
 
348
- // Show dry-run notice
349
323
  if (dryRun) {
350
324
  if (tui) {
351
325
  tui.dryRunNotice();
@@ -373,13 +347,9 @@ Skills available: ${skills.length}
373
347
  return;
374
348
  }
375
349
 
376
- // Save selected tools to config
377
350
  saveToolConfig(targetDir, selectedTools);
378
-
379
- // Ensure project-level config.json exists (used as AI preferences/context)
380
351
  ensureProjectConfigJson(targetDir);
381
352
 
382
- // Generate configs for selected tools
383
353
  console.log('');
384
354
  for (const tool of selectedTools) {
385
355
  await generateForTool(tool, targetDir, skills);
@@ -389,20 +359,15 @@ Skills available: ${skills.length}
389
359
  }
390
360
 
391
361
  /**
392
- * Sync project - regenerate configs without prompts (super recharge)
393
- *
394
- * Regenerates the Claude Code plugin and any configured legacy adapters.
395
- * Uses the saved tool preferences from .bi-superpowers.json.
362
+ * `super recharge` regenerate the Claude Code plugin without prompts.
396
363
  *
397
- * Use this command after:
398
- * - Editing skill files in src/content/skills/
399
- * - Updating the package to a new version
400
- * - Adding new AI tools to your project
364
+ * Re-reads the saved tool preferences from .bi-superpowers.json (or falls
365
+ * back to the default toolset) and regenerates everything. Useful after:
366
+ * - editing files in src/content/skills/
367
+ * - bumping the package version
368
+ * - adding new supported tools
401
369
  *
402
- * Supports --dry-run flag to preview changes without writing files.
403
- *
404
- * @param {string[]} args - Command line arguments
405
- * @param {string} [args[0]] - Target directory (defaults to cwd)
370
+ * @param {string[]} args - CLI arguments (first positional = target dir)
406
371
  */
407
372
  async function syncProject(args) {
408
373
  const dryRun = hasDryRunFlag(args);
@@ -412,12 +377,11 @@ async function syncProject(args) {
412
377
  const skills = getSkillFiles();
413
378
 
414
379
  console.log(`
415
- BI Agent Superpowers - Sync
380
+ BI Agent Superpowers Sync
416
381
  ===========================
417
382
  Regenerating configs from ${skills.length} skills...
418
383
  `);
419
384
 
420
- // Show dry-run notice
421
385
  if (dryRun) {
422
386
  if (tui) {
423
387
  tui.dryRunNotice();
@@ -429,12 +393,10 @@ Regenerating configs from ${skills.length} skills...
429
393
  }
430
394
  }
431
395
 
432
- // Read saved config or default to plugin only
433
396
  const config = loadToolConfig(targetDir);
434
397
  const selectedTools = ensurePluginTool(config.tools || [...DEFAULT_TOOLS]);
435
398
 
436
399
  if (dryRun) {
437
- // Preview what would be regenerated
438
400
  console.log('[DRY RUN] Would regenerate the following files:\n');
439
401
  previewGeneration(targetDir, selectedTools, skills);
440
402
  console.log('\nRun without --dry-run to apply changes.');
@@ -446,18 +408,16 @@ Regenerating configs from ${skills.length} skills...
446
408
  }
447
409
 
448
410
  console.log(`
449
- Done! Plugin regenerated for: ${selectedTools.map((t) => AI_TOOLS[t].name).join(', ')}
411
+ Done. Plugin regenerated for: ${selectedTools.map((t) => AI_TOOLS[t].name).join(', ')}
450
412
 
451
- If you modified skills in src/content/skills/,
452
- your Claude Code plugin is now updated.
413
+ If you modified skills in src/content/skills/, your Claude Code plugin is now up to date.
453
414
 
454
- Tip: Run 'super build-desktop' to rebuild the Claude Desktop extension.
415
+ Tip: run 'super build-desktop' to rebuild the Claude Desktop MCPB extension.
455
416
  `);
456
417
  }
457
418
 
458
419
  /**
459
- * Preview what files would be generated (for dry-run mode)
460
- * Delegates to the generators module
420
+ * Delegate to the generators module to preview what would be written.
461
421
  */
462
422
  function previewGeneration(targetDir, tools, skills) {
463
423
  if (generators) {
@@ -466,9 +426,8 @@ function previewGeneration(targetDir, tools, skills) {
466
426
  }
467
427
 
468
428
  /**
469
- * Save tool configuration to project directory
470
- * @param {string} targetDir - Project directory path
471
- * @param {string[]} tools - Array of selected AI tool IDs
429
+ * Ensure the tool list always includes the Claude Code plugin as the
430
+ * primary target. Deduplicates and preserves order.
472
431
  */
473
432
  function ensurePluginTool(tools = []) {
474
433
  const normalized = Array.from(new Set((tools || []).filter(Boolean)));
@@ -479,15 +438,13 @@ function ensurePluginTool(tools = []) {
479
438
  }
480
439
 
481
440
  /**
482
- * Resolve generation options for a target directory.
483
- *
484
- * @param {string} targetDir - Target project directory
485
- * @returns {Object} Options passed into generators
441
+ * Build the options object passed into individual generators.
442
+ * If the target directory has its own local `library/` folder, skills
443
+ * will reference that; otherwise they reference the library bundled
444
+ * inside the installed npm package.
486
445
  */
487
446
  function getGenerationOptions(targetDir) {
488
447
  const usePluginRootLauncher = path.resolve(targetDir) === PACKAGE_DIR;
489
- // If the project has a local library/ folder, use it; otherwise point to
490
- // the library bundled inside the installed npm package.
491
448
  const libraryPrefix = fs.existsSync(path.join(targetDir, 'library'))
492
449
  ? 'library'
493
450
  : path.join(PACKAGE_DIR, 'library');
@@ -500,6 +457,9 @@ function getGenerationOptions(targetDir) {
500
457
  };
501
458
  }
502
459
 
460
+ /**
461
+ * Write .bi-superpowers.json with the current tool selection and metadata.
462
+ */
503
463
  function saveToolConfig(targetDir, tools) {
504
464
  const configPath = path.join(targetDir, CONFIG_FILE);
505
465
  const normalizedTools = ensurePluginTool(tools);
@@ -509,7 +469,6 @@ function saveToolConfig(targetDir, tools) {
509
469
  name: 'bi-superpowers',
510
470
  enabled: true,
511
471
  },
512
- legacyTools: normalizedTools.filter((tool) => tool !== 'claude-plugin'),
513
472
  version: VERSION,
514
473
  lastSync: new Date().toISOString(),
515
474
  };
@@ -517,16 +476,13 @@ function saveToolConfig(targetDir, tools) {
517
476
  }
518
477
 
519
478
  /**
520
- * Preview project-level config.json creation (for dry-run mode)
521
- * This file is used by AI assistants as preferences/context, not by the CLI runtime.
522
- * @param {string} targetDir - Project directory path
479
+ * Log what config.json the kickoff would create (dry-run only).
523
480
  */
524
481
  function previewProjectConfigJson(targetDir) {
525
482
  const projectConfigPath = path.join(targetDir, 'config.json');
526
483
  if (fs.existsSync(projectConfigPath)) {
527
484
  return;
528
485
  }
529
-
530
486
  if (tui) {
531
487
  tui.info(`Would create: ${tui.formatPath(projectConfigPath)}`);
532
488
  } else {
@@ -535,9 +491,8 @@ function previewProjectConfigJson(targetDir) {
535
491
  }
536
492
 
537
493
  /**
538
- * Ensure project-level config.json exists
539
- * Copies the package template config.json into the project directory if missing.
540
- * @param {string} targetDir - Project directory path
494
+ * Copy the package's config.json template into the target directory
495
+ * unless one already exists there.
541
496
  * @returns {{created: boolean, path: string, reason?: string, error?: string}}
542
497
  */
543
498
  function ensureProjectConfigJson(targetDir) {
@@ -566,9 +521,8 @@ function ensureProjectConfigJson(targetDir) {
566
521
  }
567
522
 
568
523
  /**
569
- * Load tool configuration from project directory
570
- * @param {string} targetDir - Project directory path
571
- * @returns {Object} Configuration object or empty object if not found
524
+ * Load the previously saved tool selection from .bi-superpowers.json.
525
+ * Falls back to the default toolset if the file is missing or invalid.
572
526
  */
573
527
  function loadToolConfig(targetDir) {
574
528
  const configPath = path.join(targetDir, CONFIG_FILE);
@@ -576,31 +530,22 @@ function loadToolConfig(targetDir) {
576
530
  try {
577
531
  const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
578
532
  config.tools = ensurePluginTool(config.tools || []);
579
- config.legacyTools = config.tools.filter((tool) => tool !== 'claude-plugin');
580
533
  if (!config.plugin) {
581
- config.plugin = {
582
- name: 'bi-superpowers',
583
- enabled: true,
584
- };
534
+ config.plugin = { name: 'bi-superpowers', enabled: true };
585
535
  }
586
536
  return config;
587
- } catch (e) {
537
+ } catch (_) {
588
538
  return {};
589
539
  }
590
540
  }
591
541
  return {
592
542
  tools: [...DEFAULT_TOOLS],
593
- legacyTools: [],
594
- plugin: {
595
- name: 'bi-superpowers',
596
- enabled: true,
597
- },
543
+ plugin: { name: 'bi-superpowers', enabled: true },
598
544
  };
599
545
  }
600
546
 
601
547
  /**
602
- * Generate config for a specific AI tool
603
- * Delegates to the tool-specific generator from lib/generators module
548
+ * Dispatch to the tool-specific generator.
604
549
  */
605
550
  async function generateForTool(tool, targetDir, skills) {
606
551
  if (generators) {
@@ -615,10 +560,9 @@ function showCompletionMessage(targetDir, tools, skillCount) {
615
560
  ════════════════════════════════════════════════════════════
616
561
 
617
562
  Skills: ${skillCount} skills generated
618
- Library: ${LIBRARY_DIR}
619
563
 
620
564
  ────────────────────────────────────────────────────────────
621
- CLAUDE CODE / 1CODE.DEV
565
+ CLAUDE CODE
622
566
  ────────────────────────────────────────────────────────────
623
567
 
624
568
  Plugin files:
@@ -643,34 +587,90 @@ function showCompletionMessage(targetDir, tools, skillCount) {
643
587
 
644
588
  ────────────────────────────────────────────────────────────
645
589
 
646
- Regenerate after changes: super recharge
647
- Free models (OpenRouter): See docs/openrouter-free-models.md
590
+ Regenerate after edits: super recharge
648
591
 
649
592
  ════════════════════════════════════════════════════════════
650
593
  `);
651
594
  }
652
595
 
653
596
  /**
654
- * Update the package to the latest version using detected package manager
597
+ * Detect the package manager the user ran from the npm_config_user_agent.
598
+ * Returns the pm name ('npm', 'pnpm', 'yarn', 'bun') and the install command
599
+ * string appropriate for a global install to @latest.
600
+ *
601
+ * Exported (via module.exports) so tests can exercise the detection without
602
+ * spawning a real install.
655
603
  */
656
- function updatePackage() {
657
- console.log(`Updating ${PACKAGE_NAME}...\n`);
604
+ function getUpgradeCommand(userAgent) {
605
+ const agent = userAgent || '';
606
+ let pm = 'npm';
607
+ if (agent.includes('pnpm')) pm = 'pnpm';
608
+ else if (agent.includes('yarn')) pm = 'yarn';
609
+ else if (agent.includes('bun')) pm = 'bun';
610
+
611
+ const cmd =
612
+ pm === 'yarn'
613
+ ? `yarn global add ${PACKAGE_NAME}@latest`
614
+ : `${pm} install -g ${PACKAGE_NAME}@latest`;
615
+
616
+ return { pm, cmd };
617
+ }
658
618
 
619
+ /**
620
+ * `super upgrade` — reinstall the package at the latest version.
621
+ *
622
+ * After the reinstall, prints a "next steps" block with both update paths
623
+ * (Claude Code `/plugin update` vs npm-based `super install --yes`) so
624
+ * users know how to propagate the new skills into their agents. We
625
+ * intentionally don't auto-chain into `super install`:
626
+ * - Claude Code users who installed via the plugin marketplace refresh
627
+ * from inside Claude Code (`/plugin update bi-superpowers`), they don't
628
+ * need `super install`.
629
+ * - npm users want to be able to opt out of re-propagation (e.g. testing
630
+ * a version before rolling it across all agents).
631
+ */
632
+ /**
633
+ * Wipe ~/.bi-superpowers/update-state.json after a successful upgrade so
634
+ * the new version starts with a clean cache (no stale snooze TTL, no
635
+ * cached "latest" from the previous version). Best-effort: any failure
636
+ * is swallowed — the reset is a convenience, not a correctness gate.
637
+ *
638
+ * Separate function + exported so tests can exercise it without spawning
639
+ * a real `super upgrade`.
640
+ */
641
+ function resetUpdateCheckStateAfterUpgrade(homeDir) {
659
642
  try {
660
- const userAgent = process.env.npm_config_user_agent || '';
661
- let pm = 'npm';
662
- if (userAgent.includes('pnpm')) pm = 'pnpm';
663
- else if (userAgent.includes('yarn')) pm = 'yarn';
664
- else if (userAgent.includes('bun')) pm = 'bun';
643
+ const { resetState } = require('./commands/update-check');
644
+ resetState(path.join(homeDir, '.bi-superpowers'));
645
+ return true;
646
+ } catch (_) {
647
+ return false;
648
+ }
649
+ }
665
650
 
666
- const cmd =
667
- pm === 'yarn'
668
- ? `yarn global add ${PACKAGE_NAME}@latest`
669
- : `${pm} install -g ${PACKAGE_NAME}@latest`;
651
+ function updatePackage() {
652
+ console.log(`Updating ${PACKAGE_NAME}...\n`);
670
653
 
654
+ try {
655
+ const { cmd } = getUpgradeCommand(process.env.npm_config_user_agent);
671
656
  console.log(`Running: ${cmd}\n`);
672
657
  execSync(cmd, { stdio: 'inherit' });
673
- console.log('\n✓ Update complete!');
658
+ console.log('\n✓ CLI upgraded.');
659
+
660
+ // Clear the update-check cache + snooze state so the newly-installed
661
+ // version gets a fresh read on next skill invocation.
662
+ resetUpdateCheckStateAfterUpgrade(require('os').homedir());
663
+
664
+ console.log('\nNext step — refresh the skills + MCPs in your agents:\n');
665
+ console.log(' Claude Code (installed via marketplace):');
666
+ console.log(' /plugin update bi-superpowers');
667
+ console.log('');
668
+ console.log(' Any other install path (npm + super install):');
669
+ console.log(' super install --yes');
670
+ console.log('');
671
+ console.log(
672
+ 'If you only wanted the CLI updated (e.g. developing locally), you can skip the above.'
673
+ );
674
674
  } catch (error) {
675
675
  console.error('Update failed:', error.message);
676
676
  console.log(`\nTry manually: npm install -g ${PACKAGE_NAME}@latest`);
@@ -678,59 +678,32 @@ function updatePackage() {
678
678
  }
679
679
  }
680
680
 
681
+ /**
682
+ * `super powers` — list the available skills (and their titles).
683
+ */
681
684
  function listAgents() {
682
685
  const skills = getSkillFiles();
683
686
 
684
687
  console.log(`
685
- BI Agent Superpowers - Skills & Resources
686
- =========================================
688
+ BI Agent Superpowers Skills
689
+ =============================
687
690
  Single Source of Truth: ${skills.length} skills (open source)
688
691
  `);
689
692
 
690
- console.log('Skills (source content for the plugin and optional adapters):');
693
+ console.log('Skills:');
691
694
  for (const skill of skills) {
692
695
  const meta = parseSkillMetadata(skill.content);
693
696
  console.log(` /${skill.name.padEnd(20)} ${meta.title || ''}`);
694
697
  }
695
698
  console.log('');
696
699
 
697
- // List snippets
698
- const snippetsDir = path.join(LIBRARY_DIR, 'snippets');
699
- if (fs.existsSync(snippetsDir)) {
700
- console.log('Snippets:');
701
- fs.readdirSync(snippetsDir).forEach((category) => {
702
- const categoryPath = path.join(snippetsDir, category);
703
- try {
704
- if (fs.statSync(categoryPath).isDirectory()) {
705
- const count = fs.readdirSync(categoryPath).filter((f) => f.endsWith('.md')).length;
706
- console.log(` 📝 ${category} (${count} patterns)`);
707
- }
708
- } catch (e) {
709
- // Skip directories that can't be read
710
- }
711
- });
712
- console.log('');
713
- }
714
-
715
- // List themes
716
- const themesDir = path.join(LIBRARY_DIR, 'themes', 'power-bi');
717
- if (fs.existsSync(themesDir)) {
718
- console.log('Themes:');
719
- fs.readdirSync(themesDir).forEach((file) => {
720
- if (file.endsWith('.json')) {
721
- console.log(` 🎨 ${file.replace('.json', '')}`);
722
- }
723
- });
724
- console.log('');
725
- }
726
-
727
- console.log('Supported AI Tools:');
728
- Object.entries(AI_TOOLS).forEach(([, config]) => {
729
- console.log(` • ${config.name}`);
700
+ console.log('Supported AI tools:');
701
+ Object.entries(AI_TOOLS).forEach(([, cfg]) => {
702
+ console.log(` ${cfg.name}`);
730
703
  });
731
704
  console.log('');
732
705
 
733
- console.log("Run 'bi-superpowers recharge' to regenerate configs after editing skills.");
706
+ console.log("Run 'super recharge' to regenerate configs after editing skills.");
734
707
  }
735
708
 
736
709
  // ============================================
@@ -738,24 +711,19 @@ Single Source of Truth: ${skills.length} skills (open source)
738
711
  // ============================================
739
712
 
740
713
  /**
741
- * Get configuration object for commands
714
+ * Shared config object passed into every command module.
742
715
  */
743
716
  function getCommandConfig() {
744
717
  return {
745
718
  skillsDir: SKILLS_DIR,
746
- libraryDir: LIBRARY_DIR,
747
719
  packageDir: PACKAGE_DIR,
748
720
  version: VERSION,
749
721
  };
750
722
  }
751
723
 
752
724
  /**
753
- * Create a command wrapper with error handling
754
- * Factory pattern to reduce boilerplate in command handlers
755
- *
756
- * @param {Function|null} commandModule - The command module function
757
- * @param {string} commandName - Display name for error messages
758
- * @returns {Function} Wrapped command handler
725
+ * Factory that wraps a command module with a consistent "missing module"
726
+ * error so every non-core command fails the same way during `npm install`.
759
727
  */
760
728
  function createCommandWrapper(commandModule, commandName) {
761
729
  return (args) => {
@@ -767,44 +735,29 @@ function createCommandWrapper(commandModule, commandName) {
767
735
  };
768
736
  }
769
737
 
770
- // Command wrappers using factory pattern
771
- const runSearch = createCommandWrapper(searchCommand, 'Search');
738
+ // Wrapper instances created after createCommandWrapper is defined.
772
739
  const runLint = createCommandWrapper(lintCommand, 'Lint');
773
740
  const runDiff = createCommandWrapper(diffCommand, 'Diff');
774
741
  const runMcpSetup = createCommandWrapper(mcpSetupCommand, 'MCP setup');
775
- const runSetup = createCommandWrapper(setupCommand, 'Setup');
776
- const runAdd = createCommandWrapper(addCommand, 'Add');
777
- const runPull = createCommandWrapper(pullCommand, 'Pull');
778
- const runPush = createCommandWrapper(pushCommand, 'Push');
779
- const runSyncSource = createCommandWrapper(syncSourceCommand, 'Sync-source');
780
- const runSyncProfile = createCommandWrapper(syncProfileCommand, 'Sync-profile');
781
- const runChangelog = createCommandWrapper(changelogCommand, 'Changelog');
782
742
  const runBuildDesktop = createCommandWrapper(buildDesktopCommand, 'Build Desktop');
783
743
  const runInstall = createCommandWrapper(installCommand, 'Install');
784
744
 
785
- // Register commands that depend on createCommandWrapper (avoids TDZ in object literal)
745
+ // Register wrapper-based commands into the command map (phase 2).
786
746
  commands.install = runInstall;
787
- commands.xray = runSearch;
788
747
  commands.checkup = runLint;
789
748
  commands.scan = runDiff;
790
749
  commands.sentinel = runWatch;
791
750
  commands['mcp-setup'] = runMcpSetup;
792
751
  commands.mcp = runMcpSetup;
793
752
  commands['build-desktop'] = runBuildDesktop;
794
- commands.setup = runSetup;
795
- commands.add = runAdd;
796
- commands.pull = runPull;
797
- commands.push = runPush;
798
- commands['sync-source'] = runSyncSource;
799
- commands['sync-profile'] = runSyncProfile;
800
- commands.changelog = runChangelog;
801
- commands.search = runSearch;
802
753
  commands.lint = runLint;
803
754
  commands.diff = runDiff;
804
755
  commands.watch = runWatch;
805
756
 
806
757
  /**
807
- * Run watch command (special case - needs additional context)
758
+ * `super sentinel` — watch skill sources and auto-regenerate the plugin.
759
+ * Needs extra context (a reference to the sync function) so it has its
760
+ * own wrapper instead of using createCommandWrapper.
808
761
  */
809
762
  function runWatch(args) {
810
763
  if (!watchCommand) {
@@ -812,14 +765,13 @@ function runWatch(args) {
812
765
  process.exit(1);
813
766
  }
814
767
 
815
- // Create a reference to sync function for watch to use
816
768
  const cliModule = {
817
769
  syncProjectInternal: (targetDir, tools) => {
818
770
  const skills = getSkillFiles();
819
771
  for (const tool of tools) {
820
- const config = AI_TOOLS[tool];
821
- if (config && config.generate) {
822
- config.generate(targetDir, skills, { packageDir: PACKAGE_DIR });
772
+ const cfg = AI_TOOLS[tool];
773
+ if (cfg && cfg.generate) {
774
+ cfg.generate(targetDir, skills, { packageDir: PACKAGE_DIR });
823
775
  }
824
776
  }
825
777
  },
@@ -829,14 +781,14 @@ function runWatch(args) {
829
781
  }
830
782
 
831
783
  /**
832
- * Check if --dry-run flag is present in args
784
+ * Check if --dry-run (or -n) is present in the argument list.
833
785
  */
834
786
  function hasDryRunFlag(args) {
835
787
  return args.includes('--dry-run') || args.includes('-n');
836
788
  }
837
789
 
838
790
  /**
839
- * Remove --dry-run flag from args
791
+ * Strip the --dry-run / -n flag from the argument list.
840
792
  */
841
793
  function removeDryRunFlag(args) {
842
794
  return args.filter((a) => a !== '--dry-run' && a !== '-n');
@@ -850,10 +802,14 @@ module.exports = {
850
802
  getSkillFiles,
851
803
  loadToolConfig,
852
804
  saveToolConfig,
805
+ getUpgradeCommand,
806
+ resetUpdateCheckStateAfterUpgrade,
853
807
  AI_TOOLS,
854
808
  SKILLS_DIR,
855
- LIBRARY_DIR,
856
809
  VERSION,
857
810
  };
858
811
 
859
- main();
812
+ // Only run main() when invoked as the binary (not when required from tests).
813
+ if (require.main === module) {
814
+ main();
815
+ }