@luquimbo/bi-superpowers 3.2.0 → 4.1.1

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 (91) 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 +53 -36
  6. package/CHANGELOG.md +310 -0
  7. package/README.md +77 -26
  8. package/bin/build-plugin.js +11 -4
  9. package/bin/cli.js +113 -16
  10. package/bin/commands/build-desktop.js +35 -16
  11. package/bin/commands/diff.js +31 -13
  12. package/bin/commands/install.js +7 -3
  13. package/bin/commands/lint.js +40 -26
  14. package/bin/commands/mcp-setup.js +3 -10
  15. package/bin/commands/update-check.js +403 -0
  16. package/bin/lib/generators/claude-plugin.js +162 -6
  17. package/bin/lib/generators/shared.js +29 -33
  18. package/bin/lib/mcp-config.js +168 -12
  19. package/bin/lib/skills.js +115 -27
  20. package/bin/postinstall.js +4 -2
  21. package/bin/utils/mcp-detect.js +2 -2
  22. package/commands/bi-start.md +197 -0
  23. package/commands/pbi-connect.md +43 -65
  24. package/commands/project-kickoff.md +393 -673
  25. package/commands/report-design.md +403 -0
  26. package/desktop-extension/manifest.json +3 -3
  27. package/package.json +7 -5
  28. package/skills/bi-start/SKILL.md +199 -0
  29. package/skills/bi-start/scripts/update-check.js +403 -0
  30. package/skills/pbi-connect/SKILL.md +45 -67
  31. package/skills/pbi-connect/scripts/update-check.js +403 -0
  32. package/skills/project-kickoff/SKILL.md +395 -675
  33. package/skills/project-kickoff/scripts/update-check.js +403 -0
  34. package/skills/report-design/SKILL.md +405 -0
  35. package/skills/report-design/references/cli-commands.md +184 -0
  36. package/skills/report-design/references/cli-setup.md +101 -0
  37. package/skills/report-design/references/close-write-open-pattern.md +80 -0
  38. package/skills/report-design/references/layouts/finance.md +65 -0
  39. package/skills/report-design/references/layouts/generic.md +46 -0
  40. package/skills/report-design/references/layouts/hr.md +48 -0
  41. package/skills/report-design/references/layouts/marketing.md +45 -0
  42. package/skills/report-design/references/layouts/operations.md +44 -0
  43. package/skills/report-design/references/layouts/sales.md +50 -0
  44. package/skills/report-design/references/native-visuals.md +341 -0
  45. package/skills/report-design/references/pbi-desktop-installation.md +87 -0
  46. package/skills/report-design/references/pbir-preview-activation.md +40 -0
  47. package/skills/report-design/references/slicer.md +89 -0
  48. package/skills/report-design/references/textbox.md +101 -0
  49. package/skills/report-design/references/themes/BISuperpowers.json +915 -0
  50. package/skills/report-design/references/troubleshooting.md +135 -0
  51. package/skills/report-design/references/visual-types.md +78 -0
  52. package/skills/report-design/scripts/apply-theme.js +243 -0
  53. package/skills/report-design/scripts/create-visual.js +878 -0
  54. package/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
  55. package/skills/report-design/scripts/update-check.js +403 -0
  56. package/skills/report-design/scripts/validate-pbir.js +322 -0
  57. package/src/content/base.md +12 -68
  58. package/src/content/mcp-requirements.json +0 -25
  59. package/src/content/routing.md +19 -74
  60. package/src/content/skills/bi-start.md +191 -0
  61. package/src/content/skills/pbi-connect.md +22 -65
  62. package/src/content/skills/project-kickoff.md +372 -673
  63. package/src/content/skills/report-design/SKILL.md +376 -0
  64. package/src/content/skills/report-design/references/cli-commands.md +184 -0
  65. package/src/content/skills/report-design/references/cli-setup.md +101 -0
  66. package/src/content/skills/report-design/references/close-write-open-pattern.md +80 -0
  67. package/src/content/skills/report-design/references/layouts/finance.md +65 -0
  68. package/src/content/skills/report-design/references/layouts/generic.md +46 -0
  69. package/src/content/skills/report-design/references/layouts/hr.md +48 -0
  70. package/src/content/skills/report-design/references/layouts/marketing.md +45 -0
  71. package/src/content/skills/report-design/references/layouts/operations.md +44 -0
  72. package/src/content/skills/report-design/references/layouts/sales.md +50 -0
  73. package/src/content/skills/report-design/references/native-visuals.md +341 -0
  74. package/src/content/skills/report-design/references/pbi-desktop-installation.md +87 -0
  75. package/src/content/skills/report-design/references/pbir-preview-activation.md +40 -0
  76. package/src/content/skills/report-design/references/slicer.md +89 -0
  77. package/src/content/skills/report-design/references/textbox.md +101 -0
  78. package/src/content/skills/report-design/references/themes/BISuperpowers.json +915 -0
  79. package/src/content/skills/report-design/references/troubleshooting.md +135 -0
  80. package/src/content/skills/report-design/references/visual-types.md +78 -0
  81. package/src/content/skills/report-design/scripts/apply-theme.js +243 -0
  82. package/src/content/skills/report-design/scripts/create-visual.js +878 -0
  83. package/src/content/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
  84. package/src/content/skills/report-design/scripts/validate-pbir.js +322 -0
  85. package/bin/commands/install.test.js +0 -289
  86. package/bin/commands/lint.test.js +0 -103
  87. package/bin/lib/generators/claude-plugin.test.js +0 -111
  88. package/bin/lib/mcp-config.test.js +0 -310
  89. package/bin/lib/microsoft-mcp.test.js +0 -115
  90. package/bin/utils/mcp-detect.test.js +0 -81
  91. package/bin/utils/tui.test.js +0 -127
package/README.md CHANGED
@@ -5,62 +5,89 @@
5
5
  [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)](https://nodejs.org)
6
6
  [![Power BI](https://img.shields.io/badge/Power%20BI-Desktop-F2C811?logo=powerbi)](https://powerbi.microsoft.com)
7
7
 
8
- Toolkit open-source para trabajar con **Power BI Desktop** desde tu agente AI favorito. Funciona con los 5 agentes soportados: Claude Code, GitHub Copilot, Codex, Gemini CLI y Kilo Code.
8
+ Toolkit open-source para trabajar con **Power BI Desktop** desde Claude Code, GitHub Copilot, Codex, Gemini CLI y Kilo Code.
9
9
 
10
- > **Estado:** versión inicial. 2 skills y 2 MCP servers para empezar a iterar.
10
+ > **Estado:** `v4.1.0` — **primera versión estable**. Incluye 4 skills (`/bi-start` + 3 especialistas) y 2 MCP servers oficiales de Microsoft. `/report-design` genera PBIR via scripts Node propios (no depende de `pbi-cli-tool` para authoring Windows + Power BI Desktop sí sigue siendo requisito runtime).
11
+ >
12
+ > _Nota de versionado_: las versiones 2.x, 3.x y 4.0.0 fueron iteraciones mientras el alcance y la arquitectura del plugin se estaban asentando. **Tratá a v4.1.x como si fuera la 1.0** del producto — es el primer release que el autor considera listo para uso real. El numeral se queda en la línea 4.x porque npm es estrictamente monotónico (no se puede bajar el número), pero la madurez del producto arranca acá.
11
13
 
12
14
  ---
13
15
 
14
- ## Quick Start
16
+ ## Instalación
17
+
18
+ Elegí el camino según tu agente principal:
19
+
20
+ ### 👉 Claude Code (recomendado para usuarios de Claude Code)
21
+
22
+ Dentro de Claude Code, ejecutá:
23
+
24
+ ```
25
+ /plugin marketplace add luquimbo/bi-superpowers
26
+ /plugin install bi-superpowers
27
+ ```
28
+
29
+ Eso instala el plugin completo (4 skills + 2 MCPs) en el perfil de Claude Code. Después podés actualizar con `/plugin update bi-superpowers` directamente desde Claude Code — sin pasar por npm.
30
+
31
+ Si también querés el plugin local de proyecto (con slash commands `/project-kickoff`, `/pbi-connect`, `/report-design` en un repo específico), corré `super kickoff` dentro del repo — requiere haber instalado la CLI via el otro path (abajo).
32
+
33
+ ### 👉 Otros agentes — Copilot, Codex, Gemini CLI, Kilo Code (o multi-agente)
15
34
 
16
35
  ```bash
17
36
  # 1. Instalá la CLI
18
37
  npm install -g @luquimbo/bi-superpowers
19
38
 
20
- # 2. Instalá skills y MCPs en todos tus agentes
39
+ # 2. Instalá skills + MCPs en todos tus agentes
21
40
  super install
22
41
  ```
23
42
 
24
- Eso es todo. El instalador:
43
+ El instalador:
25
44
 
26
45
  1. Detecta qué agentes AI tenés instalados (Claude Code, Copilot, Codex, Gemini, Kilo).
27
46
  2. Te deja elegir para cuáles instalar (o hace todos con `--all --yes`).
28
- 3. Copia los 2 skills en los directorios correctos de cada agente.
47
+ 3. Copia los 4 skills en los directorios correctos de cada agente.
29
48
  4. Escribe los 2 MCPs en el config file correcto de cada agente (con el formato/schema que cada uno espera).
30
49
 
31
- Reiniciá tu agente AI, y ya tenés bi-superpowers funcionando.
50
+ Reiniciá tu agente AI y ya tenés bi-superpowers funcionando.
51
+
52
+ > **¿Por qué dos caminos?** El marketplace de Claude Code es la UX más limpia para usuarios de Claude Code — cero dependencias externas, updates nativos. La CLI via npm cubre los otros 4 agentes (que no tienen un marketplace equivalente) y funciona como denominador común cuando querés las mismas skills + MCPs en múltiples agentes. Los dos caminos son compatibles: podés combinar instalación via marketplace en Claude Code con instalación via CLI para los otros.
32
53
 
33
54
  ---
34
55
 
35
56
  ## Qué viene incluido
36
57
 
37
- ### 2 Skills
58
+ ### 4 Skills
38
59
 
39
60
  | Skill | Para qué |
40
61
  |---|---|
41
- | `project-kickoff` | Analizá el estado de tu proyecto BI y decidí próximos pasos |
62
+ | `bi-start` | **Arrancar una sesión**: muestra el menú de skills, corre update-check, y (si detecta Power BI Desktop abierto) ofrece conectar vía MCP. Tu entrada por defecto en cada conversación nueva. |
63
+ | `project-kickoff` | Analizá el estado de tu proyecto BI **nuevo** y armá `AGENTS.md` + modelo base |
42
64
  | `pbi-connect` | Conectá tu agente AI a Power BI Desktop vía MCP |
65
+ | `report-design` | Generá páginas PBIR vía scripts Node propios (`create-visual.js`, `apply-theme.js`, `validate-pbir.js`), con allowlist de 28 visualTypes nativos |
66
+
67
+ Si no sabés por dónde empezar, decile a tu agente `/bi-start` — te muestra los 4 skills, chequea updates, y rutea al que necesites. `/project-kickoff` está reservado para cuando arrancás un proyecto BI desde cero.
68
+
69
+ `report-design` requiere **Windows + Power BI Desktop** (standalone, no la versión de Microsoft Store). Los scripts Node son portables, pero el ciclo de verificación (relaunch, render) necesita Desktop. `pbi-cli-tool` es opcional y solo se usa para introspección del modelo (preferido: Microsoft Modeling MCP cuando está disponible).
43
70
 
44
71
  ### 2 MCP Servers (oficiales de Microsoft)
45
72
 
46
73
  | MCP | Para qué |
47
74
  |---|---|
48
- | `powerbi-modeling` | Conexión local a Power BI Desktop (XMLA). Leer/escribir modelo semántico, ejecutar DAX. |
75
+ | `powerbi-modeling-mcp` | Conexión local a Power BI Desktop (XMLA). Leer/escribir modelo semántico, ejecutar DAX. |
49
76
  | `microsoft-learn` | HTTP MCP de Microsoft Learn — docs oficiales de Power BI/DAX/Fabric en contexto de la conversación. |
50
77
 
51
78
  ---
52
79
 
53
80
  ## Agentes soportados
54
81
 
55
- | Agente | Skills | MCP config path |
56
- |---|---|---|
57
- | **Claude Code** | ✅ `~/.claude/skills/` | `~/.claude.json` |
58
- | **GitHub Copilot** | ✅ `~/.copilot/skills/` | `~/.copilot/mcp-config.json` |
59
- | **Codex (OpenAI)** | ✅ `~/.agents/skills/` | `~/.codex/config.toml` |
60
- | **Gemini CLI** | ✅ `~/.gemini/skills/` | `~/.gemini/settings.json` |
61
- | **Kilo Code** | ✅ `~/.kilo/skills/` | `~/.kilo/mcp_settings.json` |
82
+ | Agente | Skills | MCP config path | Cómo se usa |
83
+ |---|---|---|---|
84
+ | **Claude Code** | ✅ via `/plugin install` o `~/.claude/skills/` | `~/.claude.json` | Lenguaje natural o slash commands si corrés `super kickoff` |
85
+ | **GitHub Copilot** | ✅ `~/.copilot/skills/` | `~/.copilot/mcp-config.json` | Lenguaje natural |
86
+ | **Codex (OpenAI)** | ✅ `~/.agents/skills/` | `~/.codex/config.toml` | Lenguaje natural |
87
+ | **Gemini CLI** | ✅ `~/.gemini/skills/` | `~/.gemini/settings.json` | Lenguaje natural |
88
+ | **Kilo Code** | ✅ `~/.kilo/skills/` | `~/.kilo/mcp_settings.json` | Lenguaje natural |
62
89
 
63
- `super install` escribe todo esto automáticamente.
90
+ `super install` (npm path) escribe los skills + MCPs automáticamente para todos los agentes detectados.
64
91
 
65
92
  ### Instalación selectiva
66
93
 
@@ -79,12 +106,35 @@ super install --all --yes
79
106
 
80
107
  ## Actualizar
81
108
 
109
+ Dos caminos según cómo instalaste:
110
+
111
+ ### Claude Code (instalado via marketplace)
112
+
113
+ Dentro de Claude Code:
114
+
115
+ ```
116
+ /plugin update bi-superpowers
117
+ ```
118
+
119
+ Eso trae la última versión publicada en el marketplace. Cero interacción con npm.
120
+
121
+ ### npm (todos los otros agentes)
122
+
82
123
  ```bash
83
- # Actualizar la CLI a la última versión
84
- npm install -g @luquimbo/bi-superpowers@latest
124
+ # 1. Actualizá la CLI a la última versión
125
+ super upgrade
85
126
 
86
- # Re-instalar skills y MCPs (sobrescribe los viejos)
87
- super install --all --yes
127
+ # 2. Refrescá skills + MCPs en tus agentes (no se hace automático, es un paso separado)
128
+ super install --yes
129
+ ```
130
+
131
+ `super upgrade` reinstala el paquete global y al final te imprime un recordatorio con este segundo paso. No lo hace automático a propósito: los usuarios que solo quieren actualizar la CLI (p.ej. desarrollando local) pueden saltarlo.
132
+
133
+ Equivalente manual si `super upgrade` falla:
134
+
135
+ ```bash
136
+ npm install -g @luquimbo/bi-superpowers@latest
137
+ super install --yes
88
138
  ```
89
139
 
90
140
  ---
@@ -111,7 +161,8 @@ Si ya instalaste los MCPs por alguno de estos caminos, no necesitás correr `sup
111
161
  ## Requisitos
112
162
 
113
163
  - **Node.js ≥ 18**
114
- - **Power BI Desktop en Windows** (para el MCP `powerbi-modeling` el MCP `microsoft-learn` funciona en cualquier plataforma)
164
+ - **Power BI Desktop en Windows** (standalone, no Microsoft Store) para workflows locales contra Desktop (`powerbi-modeling-mcp` y `report-design`)
165
+ - **Python 3.10+**, **`pipx`** y **`pbi-cli-tool`** son **opcionales** — solo hacen falta para introspección del modelo via XMLA cuando el Microsoft Modeling MCP no está disponible. Para authoring de visuales, `report-design` usa scripts Node propios y no depende de esa cadena.
115
166
  - Al menos uno de: Claude Code, GitHub Copilot, Codex, Gemini CLI, Kilo Code
116
167
 
117
168
  ---
@@ -119,11 +170,11 @@ Si ya instalaste los MCPs por alguno de estos caminos, no necesitás correr `sup
119
170
  ## Comandos
120
171
 
121
172
  ```bash
122
- super install # Instalá skills + MCPs en tus agentes AI
123
- super kickoff # Generá el plugin de Claude Code en un proyecto (avanzado)
173
+ super install # Instalá 4 skills + 2 MCPs en tus agentes AI
174
+ super kickoff # Generá el plugin local de Claude Code con slash commands
124
175
  super recharge # Regenerá el plugin tras editar skills fuente
125
176
  super powers # Listá skills disponibles
126
- super upgrade # Actualizá la CLI a la última versión
177
+ super upgrade # Actualizá la CLI a la última versión + imprime recordatorio de `super install`
127
178
  super help # Ayuda completa
128
179
  ```
129
180
 
@@ -84,7 +84,14 @@ async function main() {
84
84
  verifyPluginOutputs(packageDir);
85
85
  }
86
86
 
87
- main().catch((error) => {
88
- console.error(error.message);
89
- process.exit(1);
90
- });
87
+ // Export for unit testing. The script is also invoked directly during
88
+ // `npm run build:plugin` — we only run main() when it's the entry point,
89
+ // otherwise the test suite would trigger a full build on every import.
90
+ module.exports = { verifyPluginOutputs, main };
91
+
92
+ if (require.main === module) {
93
+ main().catch((error) => {
94
+ console.error(error.message);
95
+ process.exit(1);
96
+ });
97
+ }
package/bin/cli.js CHANGED
@@ -28,6 +28,34 @@ const path = require('path');
28
28
  const { execSync } = require('child_process');
29
29
  const { loadSkills } = require('./lib/skills');
30
30
 
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
+
31
59
  // Optional lib import — may not be available during npm install phase.
32
60
  let generators;
33
61
  try {
@@ -132,6 +160,14 @@ function main() {
132
160
  const args = process.argv.slice(2);
133
161
  const command = args[0] || 'help';
134
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
+
135
171
  if (commands[command]) {
136
172
  commands[command](args.slice(1));
137
173
  } else {
@@ -157,7 +193,7 @@ Usage:
157
193
  super <command> [options]
158
194
 
159
195
  Primary commands:
160
- install Install the 2 skills + 2 MCPs across your AI agents
196
+ install Install the 4 skills + 2 MCPs across your AI agents
161
197
  kickoff [path] Generate the full Claude Code plugin in a project
162
198
  recharge [path] Regenerate the plugin after editing source skills
163
199
  build-desktop Build the .mcpb extension for Claude Desktop
@@ -558,27 +594,83 @@ function showCompletionMessage(targetDir, tools, skillCount) {
558
594
  }
559
595
 
560
596
  /**
561
- * `super upgrade` reinstall the package at the latest version using
562
- * whichever package manager the user ran npm with.
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.
563
603
  */
564
- function updatePackage() {
565
- 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
+ }
566
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) {
567
642
  try {
568
- const userAgent = process.env.npm_config_user_agent || '';
569
- let pm = 'npm';
570
- if (userAgent.includes('pnpm')) pm = 'pnpm';
571
- else if (userAgent.includes('yarn')) pm = 'yarn';
572
- 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
+ }
573
650
 
574
- const cmd =
575
- pm === 'yarn'
576
- ? `yarn global add ${PACKAGE_NAME}@latest`
577
- : `${pm} install -g ${PACKAGE_NAME}@latest`;
651
+ function updatePackage() {
652
+ console.log(`Updating ${PACKAGE_NAME}...\n`);
578
653
 
654
+ try {
655
+ const { cmd } = getUpgradeCommand(process.env.npm_config_user_agent);
579
656
  console.log(`Running: ${cmd}\n`);
580
657
  execSync(cmd, { stdio: 'inherit' });
581
- 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
+ );
582
674
  } catch (error) {
583
675
  console.error('Update failed:', error.message);
584
676
  console.log(`\nTry manually: npm install -g ${PACKAGE_NAME}@latest`);
@@ -710,9 +802,14 @@ module.exports = {
710
802
  getSkillFiles,
711
803
  loadToolConfig,
712
804
  saveToolConfig,
805
+ getUpgradeCommand,
806
+ resetUpdateCheckStateAfterUpgrade,
713
807
  AI_TOOLS,
714
808
  SKILLS_DIR,
715
809
  VERSION,
716
810
  };
717
811
 
718
- main();
812
+ // Only run main() when invoked as the binary (not when required from tests).
813
+ if (require.main === module) {
814
+ main();
815
+ }
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Builds a .mcpb extension for Claude Desktop by:
6
6
  * 1. Copying desktop-extension/ template to a temp directory
7
- * 2. Copying all 24 skill sources into temp/skills/
7
+ * 2. Copying every skill source (flat + folder-based) into temp/skills/
8
8
  * 3. Installing dependencies
9
9
  * 4. Running `npx @anthropic-ai/mcpb pack` to create the .mcpb file
10
10
  * 5. Moving the result to the current directory
@@ -18,6 +18,7 @@ const fs = require('fs');
18
18
  const path = require('path');
19
19
  const os = require('os');
20
20
  const { execSync } = require('child_process');
21
+ const { loadSkills } = require('../lib/skills');
21
22
 
22
23
  /** Directory where the npm package is installed */
23
24
  const PACKAGE_DIR = path.dirname(path.dirname(__dirname));
@@ -25,8 +26,27 @@ const PACKAGE_DIR = path.dirname(path.dirname(__dirname));
25
26
  /** Desktop extension template source */
26
27
  const DESKTOP_TEMPLATE_DIR = path.join(PACKAGE_DIR, 'desktop-extension');
27
28
 
28
- /** Skill source files directory */
29
- const SKILLS_SOURCE_DIR = path.join(PACKAGE_DIR, 'src', 'content', 'skills');
29
+ /**
30
+ * Bundle skills into the Desktop extension's skills/ directory.
31
+ *
32
+ * Handles both flat `src/content/skills/<name>.md` and folder-based
33
+ * `src/content/skills/<name>/SKILL.md` layouts by flattening each skill
34
+ * to a single `<name>.md` file inside `skillsOutDir`. The Claude Desktop
35
+ * MCP server loads those flat files as prompts — `references/` and
36
+ * `scripts/` are distributed through `super install`, not bundled here.
37
+ *
38
+ * @param {string} skillsOutDir - Destination directory (created if missing)
39
+ * @param {string} packageDir - npm package root containing src/content/skills/
40
+ * @returns {string[]} Names of skills bundled into skillsOutDir
41
+ */
42
+ function bundleSkills(skillsOutDir, packageDir) {
43
+ fs.mkdirSync(skillsOutDir, { recursive: true });
44
+ const skills = loadSkills({ packageDir });
45
+ for (const skill of skills) {
46
+ fs.writeFileSync(path.join(skillsOutDir, `${skill.name}.md`), skill.content);
47
+ }
48
+ return skills.map((s) => s.name);
49
+ }
30
50
 
31
51
  /**
32
52
  * Build the .mcpb extension for Claude Desktop.
@@ -34,7 +54,7 @@ const SKILLS_SOURCE_DIR = path.join(PACKAGE_DIR, 'src', 'content', 'skills');
34
54
  * @param {string[]} args - CLI arguments
35
55
  * @param {Object} config - Command config from CLI
36
56
  */
37
- module.exports = function buildDesktop(_args, _config) {
57
+ function buildDesktop(_args, _config) {
38
58
  const outputDir = process.cwd();
39
59
 
40
60
  console.log(`
@@ -50,7 +70,8 @@ BI Agent Superpowers — Build Desktop Extension
50
70
  }
51
71
 
52
72
  // Verify skills exist
53
- if (!fs.existsSync(SKILLS_SOURCE_DIR)) {
73
+ const skillsSourceDir = path.join(PACKAGE_DIR, 'src', 'content', 'skills');
74
+ if (!fs.existsSync(skillsSourceDir)) {
54
75
  console.error(
55
76
  'Error: skill sources not found. Try reinstalling: npm install -g @luquimbo/bi-superpowers'
56
77
  );
@@ -71,15 +92,10 @@ BI Agent Superpowers — Build Desktop Extension
71
92
  }
72
93
  }
73
94
 
74
- // Copy all skill .md files into temp/skills/
75
- const skillsOutDir = path.join(tmpDir, 'skills');
76
- fs.mkdirSync(skillsOutDir, { recursive: true });
77
-
78
- const skillFiles = fs.readdirSync(SKILLS_SOURCE_DIR).filter((f) => f.endsWith('.md'));
79
- for (const file of skillFiles) {
80
- fs.copyFileSync(path.join(SKILLS_SOURCE_DIR, file), path.join(skillsOutDir, file));
81
- }
82
- console.log(` Bundled ${skillFiles.length} skills`);
95
+ // Bundle every skill (flat + folder-based) into temp/skills/
96
+ const bundledNames = bundleSkills(path.join(tmpDir, 'skills'), PACKAGE_DIR);
97
+ const skillFiles = bundledNames.map((n) => `${n}.md`);
98
+ console.log(` Bundled ${bundledNames.length} skills`);
83
99
 
84
100
  // Patch template placeholder versions with the real package version
85
101
  const pkgVersion = require(path.join(PACKAGE_DIR, 'package.json')).version;
@@ -149,7 +165,7 @@ BI Agent Superpowers — Build Desktop Extension
149
165
  2. Go to Settings > Extensions > Install Extension
150
166
 
151
167
  The extension adds ${skillFiles.length} BI skills as MCP prompts.
152
- Use the "setup-mcp" prompt for Power BI/Fabric MCP configuration.
168
+ Use the "setup-mcp" prompt for Power BI Modeling MCP configuration.
153
169
  `);
154
170
  } else {
155
171
  console.log('\n Build complete. Check current directory for .mcpb file.');
@@ -165,4 +181,7 @@ BI Agent Superpowers — Build Desktop Extension
165
181
  // Ignore cleanup errors
166
182
  }
167
183
  }
168
- };
184
+ }
185
+
186
+ module.exports = buildDesktop;
187
+ module.exports.bundleSkills = bundleSkills;
@@ -12,6 +12,7 @@
12
12
  const fs = require('fs');
13
13
  const path = require('path');
14
14
  const tui = require('../utils/tui');
15
+ const { readSkillDirectory, normalizeSkillName } = require('../lib/skills');
15
16
 
16
17
  /**
17
18
  * Generate a simple diff between two strings
@@ -122,7 +123,12 @@ function compareFiles(skillPath, generatedPath) {
122
123
  function getGeneratedPath(skillName, tool, targetDir) {
123
124
  switch (tool) {
124
125
  case 'claude-code':
125
- return path.join(targetDir, '.claude', 'commands', `${skillName}.md`);
126
+ // The Claude Code plugin generator (bin/lib/generators/claude-plugin.js)
127
+ // writes slash commands to `<targetDir>/commands/<skill>.md` — NOT
128
+ // `.claude/commands/...`. An earlier path here pointed at the old
129
+ // location and silently made `super scan --tool claude-code`
130
+ // report every skill as "not-generated".
131
+ return path.join(targetDir, 'commands', `${skillName}.md`);
126
132
  case 'cursor':
127
133
  // Cursor uses a single file, can't diff per-skill
128
134
  return null;
@@ -249,23 +255,27 @@ function diffCommand(args, config) {
249
255
  return;
250
256
  }
251
257
 
252
- // Get skill files to compare
258
+ // Get skill files to compare. Use the shared skill loader so both
259
+ // flat (`<name>.md`) and folder-based (`<name>/SKILL.md`) skills
260
+ // are picked up — a previous version filtered with
261
+ // `f.endsWith('.md')` and silently dropped every folder-based skill.
262
+ const allSkills = readSkillDirectory(skillsDir);
263
+ const skillsByName = new Map(allSkills.map((s) => [s.name, s]));
264
+ const skillNameByPath = new Map(allSkills.map((s) => [s.path, s.name]));
253
265
  let skillFiles = [];
254
266
 
255
267
  if (options.skill) {
256
- const skillName = options.skill.replace('.md', '');
257
- const skillPath = path.join(skillsDir, `${skillName}.md`);
258
- if (fs.existsSync(skillPath)) {
259
- skillFiles = [skillPath];
268
+ // normalizeSkillName accepts `dax`, `dax.md`, `report-design`, or
269
+ // `report-design/SKILL.md` and returns the canonical skill name.
270
+ const skill = skillsByName.get(normalizeSkillName(options.skill));
271
+ if (skill) {
272
+ skillFiles = [skill.path];
260
273
  } else {
261
274
  tui.error(`Skill not found: ${options.skill}`);
262
275
  process.exit(1);
263
276
  }
264
277
  } else {
265
- skillFiles = fs
266
- .readdirSync(skillsDir)
267
- .filter((f) => f.endsWith('.md'))
268
- .map((f) => path.join(skillsDir, f));
278
+ skillFiles = allSkills.map((s) => s.path);
269
279
  }
270
280
 
271
281
  if (skillFiles.length === 0) {
@@ -276,9 +286,11 @@ function diffCommand(args, config) {
276
286
  tui.info(`Comparing ${skillFiles.length} skill(s) for ${options.tool}...`);
277
287
  tui.section('Changes');
278
288
 
279
- // Compare each skill
289
+ // Compare each skill. Use the loader-built map to derive the canonical
290
+ // skill name — for folder-based skills the path is `<folder>/SKILL.md`
291
+ // and `path.basename(...)` would return `SKILL`, breaking the diff.
280
292
  const results = skillFiles.map((skillPath) => {
281
- const skillName = path.basename(skillPath, '.md');
293
+ const skillName = skillNameByPath.get(skillPath) || path.basename(skillPath, '.md');
282
294
  const generatedPath = getGeneratedPath(skillName, options.tool, targetDir);
283
295
 
284
296
  if (!generatedPath) {
@@ -324,4 +336,10 @@ function diffCommand(args, config) {
324
336
  }
325
337
  }
326
338
 
327
- module.exports = diffCommand;
339
+ // Expose primitives for tests (B3 — replace fake tests with real ones).
340
+ module.exports = Object.assign(diffCommand, {
341
+ generateDiff,
342
+ compareFiles,
343
+ getGeneratedPath,
344
+ parseArgs,
345
+ });
@@ -470,11 +470,15 @@ async function installCommand(args, config) {
470
470
  '\n' +
471
471
  chalk.gray('Reiniciá tu agente AI para que tome los MCPs nuevos.') +
472
472
  '\n\n' +
473
- chalk.gray('Los 2 skills disponibles:') +
473
+ chalk.gray('Los 4 skills disponibles:') +
474
474
  '\n' +
475
- chalk.gray(' /project-kickoff Analizá tu proyecto BI') +
475
+ chalk.gray(' /bi-start Arrancar una sesión: menú + update + conexión') +
476
476
  '\n' +
477
- chalk.gray(' /pbi-connect Conectá tu agente a Power BI Desktop'),
477
+ chalk.gray(' /project-kickoff Analizá tu proyecto BI (proyecto nuevo)') +
478
+ '\n' +
479
+ chalk.gray(' /pbi-connect — Conectá tu agente a Power BI Desktop') +
480
+ '\n' +
481
+ chalk.gray(' /report-design — Generá reportes PBIR para Power BI Desktop (Windows)'),
478
482
  {
479
483
  padding: 1,
480
484
  margin: { top: 1 },