@luquimbo/bi-superpowers 4.1.2 → 4.1.4
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/skill-manifest.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/AGENTS.md +9 -7
- package/CHANGELOG.md +40 -0
- package/README.md +637 -96
- package/bin/cli.js +76 -61
- package/bin/commands/build-desktop.js +60 -6
- package/bin/commands/diff.js +86 -1
- package/bin/commands/mcp-setup.js +26 -3
- package/bin/commands/watch.js +50 -5
- package/bin/postinstall.js +1 -1
- package/bin/utils/mcp-detect.js +1 -1
- package/commands/bi-start.md +3 -3
- package/commands/pbi-connect.md +60 -24
- package/commands/report-design.md +1 -1
- package/desktop-extension/server.js +43 -10
- package/package.json +3 -4
- package/skills/bi-start/SKILL.md +4 -4
- package/skills/bi-start/scripts/update-check.js +1 -1
- package/skills/pbi-connect/SKILL.md +61 -25
- package/skills/pbi-connect/scripts/update-check.js +1 -1
- package/skills/project-kickoff/SKILL.md +1 -1
- package/skills/project-kickoff/scripts/update-check.js +1 -1
- package/skills/report-design/SKILL.md +2 -2
- package/skills/report-design/references/layouts/finance.md +2 -2
- package/skills/report-design/references/native-visuals.md +2 -2
- package/skills/report-design/references/slicer.md +1 -1
- package/skills/report-design/references/textbox.md +1 -1
- package/skills/report-design/scripts/create-visual.js +65 -1
- package/skills/report-design/scripts/update-check.js +1 -1
- package/skills/report-design/scripts/validate-pbir.js +29 -0
- package/src/content/base.md +1 -1
- package/src/content/routing.md +1 -1
- package/src/content/skills/bi-start.md +3 -3
- package/src/content/skills/pbi-connect.md +60 -24
- package/src/content/skills/report-design/SKILL.md +1 -1
- package/src/content/skills/report-design/references/layouts/finance.md +2 -2
- package/src/content/skills/report-design/references/native-visuals.md +2 -2
- package/src/content/skills/report-design/references/slicer.md +1 -1
- package/src/content/skills/report-design/references/textbox.md +1 -1
- package/src/content/skills/report-design/scripts/create-visual.js +65 -1
- package/src/content/skills/report-design/scripts/validate-pbir.js +29 -0
package/bin/cli.js
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* Architecture:
|
|
12
12
|
* - Skills are authored once in src/content/skills/ and copied out to
|
|
13
13
|
* each supported agent by `super install`.
|
|
14
|
-
* - `super kickoff` generates a
|
|
14
|
+
* - `super kickoff` optionally generates a local Claude Code plugin tree in a
|
|
15
15
|
* user project (skills + commands + MCP config).
|
|
16
|
-
* - `super recharge` regenerates
|
|
16
|
+
* - `super recharge` regenerates an existing local Claude Code plugin after edits.
|
|
17
17
|
*
|
|
18
18
|
* Supported agents: Claude Code, GitHub Copilot, Codex, Gemini CLI, Kilo Code.
|
|
19
19
|
* License: MIT. This project is fully open source — no activation, no keys.
|
|
@@ -28,34 +28,6 @@ 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 refresh your install path (`/plugin update bi-superpowers`, `super install --yes`, or run `super recharge` inside each repo where you used `super kickoff`).',
|
|
53
|
-
});
|
|
54
|
-
} catch (_) {
|
|
55
|
-
// update-notifier not available during npm install phase, or network
|
|
56
|
-
// probe failed — skip silently.
|
|
57
|
-
}
|
|
58
|
-
|
|
59
31
|
// Optional lib import — may not be available during npm install phase.
|
|
60
32
|
let generators;
|
|
61
33
|
try {
|
|
@@ -160,14 +132,6 @@ function main() {
|
|
|
160
132
|
const args = process.argv.slice(2);
|
|
161
133
|
const command = args[0] || 'help';
|
|
162
134
|
|
|
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
|
-
|
|
171
135
|
if (commands[command]) {
|
|
172
136
|
commands[command](args.slice(1));
|
|
173
137
|
} else {
|
|
@@ -186,18 +150,18 @@ Open-source toolkit for Power BI Desktop development across 5 AI coding agents:
|
|
|
186
150
|
Claude Code · GitHub Copilot · Codex · Gemini CLI · Kilo Code.
|
|
187
151
|
|
|
188
152
|
Quick Start:
|
|
189
|
-
super install
|
|
190
|
-
super
|
|
153
|
+
super install --all --yes # Install skills + MCPs user-level for all agents
|
|
154
|
+
super powers # List the skills and MCPs available
|
|
191
155
|
|
|
192
156
|
Usage:
|
|
193
157
|
super <command> [options]
|
|
194
158
|
|
|
195
159
|
Primary commands:
|
|
196
|
-
install Install the 4 skills + 2 MCPs across your AI agents
|
|
197
|
-
kickoff [path]
|
|
198
|
-
recharge [path]
|
|
160
|
+
install Install the 4 skills + 2 MCPs user-level across your AI agents
|
|
161
|
+
kickoff [path] Optional: generate a repo-local Claude Code plugin
|
|
162
|
+
recharge [path] Optional: regenerate an existing repo-local Claude Code plugin
|
|
199
163
|
build-desktop Build the .mcpb extension for Claude Desktop
|
|
200
|
-
mcp-setup
|
|
164
|
+
mcp-setup Refresh MCP config for an existing Claude Code local plugin
|
|
201
165
|
powers List available skills and MCPs
|
|
202
166
|
upgrade Update to the latest version on npm
|
|
203
167
|
about Show installation info
|
|
@@ -214,13 +178,14 @@ Options:
|
|
|
214
178
|
Examples:
|
|
215
179
|
super install # Interactive installer for all agents
|
|
216
180
|
super install --all --yes # Non-interactive install for every agent
|
|
181
|
+
super install -a codex # Install user-level skills + MCPs for Codex
|
|
217
182
|
super install -a claude-code # Install only for Claude Code
|
|
218
|
-
super kickoff #
|
|
219
|
-
super kickoff ./my-project #
|
|
220
|
-
super kickoff --dry-run # Preview
|
|
221
|
-
super recharge # Regenerate
|
|
183
|
+
super kickoff # Claude Code only: create local plugin files
|
|
184
|
+
super kickoff ./my-project # Claude Code only: initialize in a repo
|
|
185
|
+
super kickoff --dry-run # Preview local Claude Code plugin files
|
|
186
|
+
super recharge # Regenerate existing local Claude Code plugin
|
|
222
187
|
super build-desktop # Build .mcpb for Claude Desktop
|
|
223
|
-
super mcp-setup #
|
|
188
|
+
super mcp-setup # Existing local Claude Code plugin only
|
|
224
189
|
|
|
225
190
|
Open source — MIT licensed.
|
|
226
191
|
Documentation: https://github.com/luquimbo/bi-superpowers
|
|
@@ -293,7 +258,7 @@ function parseSkillMetadata(content) {
|
|
|
293
258
|
// ============================================
|
|
294
259
|
|
|
295
260
|
/**
|
|
296
|
-
* `super kickoff` — generate
|
|
261
|
+
* `super kickoff` — generate an optional local Claude Code plugin in the target directory.
|
|
297
262
|
*
|
|
298
263
|
* What it does:
|
|
299
264
|
* 1. Generates .claude-plugin/, .mcp.json, commands/, skills/ in the target.
|
|
@@ -314,10 +279,17 @@ async function initProject(args) {
|
|
|
314
279
|
console.log(`
|
|
315
280
|
BI Agent Superpowers v${VERSION}
|
|
316
281
|
================================
|
|
317
|
-
Claude Code
|
|
282
|
+
Claude Code local plugin setup
|
|
318
283
|
|
|
319
284
|
Initializing in: ${targetDir}
|
|
320
285
|
Skills available: ${skills.length}
|
|
286
|
+
|
|
287
|
+
This is not the multi-agent install path. For Codex, GitHub Copilot,
|
|
288
|
+
Gemini CLI, Kilo Code, and user-level Claude Code installs, run:
|
|
289
|
+
|
|
290
|
+
super install --all --yes
|
|
291
|
+
|
|
292
|
+
kickoff writes repo-local Claude Code plugin files only.
|
|
321
293
|
`);
|
|
322
294
|
|
|
323
295
|
if (dryRun) {
|
|
@@ -359,7 +331,7 @@ Skills available: ${skills.length}
|
|
|
359
331
|
}
|
|
360
332
|
|
|
361
333
|
/**
|
|
362
|
-
* `super recharge` — regenerate
|
|
334
|
+
* `super recharge` — regenerate an existing local Claude Code plugin without prompts.
|
|
363
335
|
*
|
|
364
336
|
* Re-reads the saved tool preferences from .bi-superpowers.json (or falls
|
|
365
337
|
* back to the default toolset) and regenerates everything. Useful after:
|
|
@@ -393,6 +365,23 @@ Regenerating configs from ${skills.length} skills...
|
|
|
393
365
|
}
|
|
394
366
|
}
|
|
395
367
|
|
|
368
|
+
if (!hasProjectLocalPlugin(targetDir)) {
|
|
369
|
+
console.log(`
|
|
370
|
+
This repo does not contain a local Claude Code plugin generated by super kickoff.
|
|
371
|
+
|
|
372
|
+
For Codex, GitHub Copilot, Gemini CLI, Kilo Code, and user-level Claude Code
|
|
373
|
+
installs, refresh the user-level install instead:
|
|
374
|
+
|
|
375
|
+
super install --all --yes
|
|
376
|
+
|
|
377
|
+
If you intentionally want repo-local Claude Code plugin files, run:
|
|
378
|
+
|
|
379
|
+
super kickoff
|
|
380
|
+
`);
|
|
381
|
+
process.exitCode = 2;
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
396
385
|
const config = loadToolConfig(targetDir);
|
|
397
386
|
const selectedTools = ensurePluginTool(config.tools || [...DEFAULT_TOOLS]);
|
|
398
387
|
|
|
@@ -544,6 +533,13 @@ function loadToolConfig(targetDir) {
|
|
|
544
533
|
};
|
|
545
534
|
}
|
|
546
535
|
|
|
536
|
+
function hasProjectLocalPlugin(targetDir) {
|
|
537
|
+
return (
|
|
538
|
+
fs.existsSync(path.join(targetDir, CONFIG_FILE)) ||
|
|
539
|
+
fs.existsSync(path.join(targetDir, '.claude-plugin', 'plugin.json'))
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
547
543
|
/**
|
|
548
544
|
* Dispatch to the tool-specific generator.
|
|
549
545
|
*/
|
|
@@ -561,6 +557,10 @@ function showCompletionMessage(targetDir, tools, skillCount) {
|
|
|
561
557
|
|
|
562
558
|
Skills: ${skillCount} skills generated
|
|
563
559
|
|
|
560
|
+
Note: this is a repo-local Claude Code plugin only.
|
|
561
|
+
Codex, GitHub Copilot, Gemini CLI, Kilo Code, and user-level Claude Code
|
|
562
|
+
installs use: super install --all --yes
|
|
563
|
+
|
|
564
564
|
────────────────────────────────────────────────────────────
|
|
565
565
|
CLAUDE CODE
|
|
566
566
|
────────────────────────────────────────────────────────────
|
|
@@ -783,19 +783,32 @@ function runWatch(args) {
|
|
|
783
783
|
process.exit(1);
|
|
784
784
|
}
|
|
785
785
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
786
|
+
watchCommand(args, getCommandConfig(), createWatchCliModule());
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Build the tiny adapter used by `super sentinel`.
|
|
791
|
+
* It intentionally delegates through generateForTool(), the same path as
|
|
792
|
+
* kickoff/recharge, so regenerated plugin files keep the real package version,
|
|
793
|
+
* library prefix, and MCP launcher mode.
|
|
794
|
+
*
|
|
795
|
+
* @param {Object} [deps] - Test seams
|
|
796
|
+
* @param {Function} [deps.getSkillFilesFn] - Skill loader
|
|
797
|
+
* @param {Function} [deps.generateForToolFn] - Tool generator
|
|
798
|
+
* @returns {{syncProjectInternal: Function}} Watch command adapter
|
|
799
|
+
*/
|
|
800
|
+
function createWatchCliModule(deps = {}) {
|
|
801
|
+
const getSkillFilesFn = deps.getSkillFilesFn || getSkillFiles;
|
|
802
|
+
const generateForToolFn = deps.generateForToolFn || generateForTool;
|
|
803
|
+
|
|
804
|
+
return {
|
|
805
|
+
syncProjectInternal: async (targetDir, tools) => {
|
|
806
|
+
const skills = getSkillFilesFn();
|
|
789
807
|
for (const tool of tools) {
|
|
790
|
-
|
|
791
|
-
if (cfg && cfg.generate) {
|
|
792
|
-
cfg.generate(targetDir, skills, { packageDir: PACKAGE_DIR });
|
|
793
|
-
}
|
|
808
|
+
await generateForToolFn(tool, targetDir, skills);
|
|
794
809
|
}
|
|
795
810
|
},
|
|
796
811
|
};
|
|
797
|
-
|
|
798
|
-
watchCommand(args, getCommandConfig(), cliModule);
|
|
799
812
|
}
|
|
800
813
|
|
|
801
814
|
/**
|
|
@@ -823,6 +836,8 @@ module.exports = {
|
|
|
823
836
|
getUpgradeCommand,
|
|
824
837
|
getUpgradeRefreshSteps,
|
|
825
838
|
resetUpdateCheckStateAfterUpgrade,
|
|
839
|
+
createWatchCliModule,
|
|
840
|
+
getGenerationOptions,
|
|
826
841
|
AI_TOOLS,
|
|
827
842
|
SKILLS_DIR,
|
|
828
843
|
VERSION,
|
|
@@ -30,10 +30,10 @@ const DESKTOP_TEMPLATE_DIR = path.join(PACKAGE_DIR, 'desktop-extension');
|
|
|
30
30
|
* Bundle skills into the Desktop extension's skills/ directory.
|
|
31
31
|
*
|
|
32
32
|
* Handles both flat `src/content/skills/<name>.md` and folder-based
|
|
33
|
-
* `src/content/skills/<name>/SKILL.md` layouts by
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* `src/content/skills/<name>/SKILL.md` layouts by writing each skill as
|
|
34
|
+
* `<name>/SKILL.md`. Folder-based skills also get their runtime
|
|
35
|
+
* `references/` and `scripts/` subtrees copied into the MCPB, so prompts
|
|
36
|
+
* never point Claude Desktop at files missing from the installed extension.
|
|
37
37
|
*
|
|
38
38
|
* @param {string} skillsOutDir - Destination directory (created if missing)
|
|
39
39
|
* @param {string} packageDir - npm package root containing src/content/skills/
|
|
@@ -43,11 +43,63 @@ function bundleSkills(skillsOutDir, packageDir) {
|
|
|
43
43
|
fs.mkdirSync(skillsOutDir, { recursive: true });
|
|
44
44
|
const skills = loadSkills({ packageDir });
|
|
45
45
|
for (const skill of skills) {
|
|
46
|
-
|
|
46
|
+
const skillOutDir = path.join(skillsOutDir, skill.name);
|
|
47
|
+
fs.mkdirSync(skillOutDir, { recursive: true });
|
|
48
|
+
fs.writeFileSync(path.join(skillOutDir, 'SKILL.md'), skill.content);
|
|
49
|
+
|
|
50
|
+
if (skill.bundleDir) {
|
|
51
|
+
copyRuntimeTree(
|
|
52
|
+
path.join(skill.bundleDir, 'references'),
|
|
53
|
+
path.join(skillOutDir, 'references')
|
|
54
|
+
);
|
|
55
|
+
copyRuntimeTree(path.join(skill.bundleDir, 'scripts'), path.join(skillOutDir, 'scripts'));
|
|
56
|
+
}
|
|
47
57
|
}
|
|
48
58
|
return skills.map((s) => s.name);
|
|
49
59
|
}
|
|
50
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Copy runtime skill assets, excluding test/build/editor artifacts.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} source - Source file or directory
|
|
65
|
+
* @param {string} target - Destination file or directory
|
|
66
|
+
*/
|
|
67
|
+
function copyRuntimeTree(source, target) {
|
|
68
|
+
if (!fs.existsSync(source)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const stat = fs.statSync(source);
|
|
73
|
+
if (stat.isDirectory()) {
|
|
74
|
+
fs.mkdirSync(target, { recursive: true });
|
|
75
|
+
for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
|
|
76
|
+
copyRuntimeTree(path.join(source, entry.name), path.join(target, entry.name));
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!stat.isFile() || shouldSkipRuntimeFile(source)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
86
|
+
fs.copyFileSync(source, target);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} filePath - Runtime asset path
|
|
91
|
+
* @returns {boolean} True if this file should not ship in the MCPB
|
|
92
|
+
*/
|
|
93
|
+
function shouldSkipRuntimeFile(filePath) {
|
|
94
|
+
const base = path.basename(filePath);
|
|
95
|
+
return (
|
|
96
|
+
base.endsWith('.test.js') ||
|
|
97
|
+
base.endsWith('.spec.js') ||
|
|
98
|
+
base.endsWith('.bak') ||
|
|
99
|
+
base.endsWith('.tmp')
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
51
103
|
/**
|
|
52
104
|
* Build the .mcpb extension for Claude Desktop.
|
|
53
105
|
*
|
|
@@ -94,7 +146,7 @@ BI Agent Superpowers — Build Desktop Extension
|
|
|
94
146
|
|
|
95
147
|
// Bundle every skill (flat + folder-based) into temp/skills/
|
|
96
148
|
const bundledNames = bundleSkills(path.join(tmpDir, 'skills'), PACKAGE_DIR);
|
|
97
|
-
const skillFiles = bundledNames.map((n) => `${n}.md`);
|
|
149
|
+
const skillFiles = bundledNames.map((n) => `${n}/SKILL.md`);
|
|
98
150
|
console.log(` Bundled ${bundledNames.length} skills`);
|
|
99
151
|
|
|
100
152
|
// Patch template placeholder versions with the real package version
|
|
@@ -185,3 +237,5 @@ BI Agent Superpowers — Build Desktop Extension
|
|
|
185
237
|
|
|
186
238
|
module.exports = buildDesktop;
|
|
187
239
|
module.exports.bundleSkills = bundleSkills;
|
|
240
|
+
module.exports.copyRuntimeTree = copyRuntimeTree;
|
|
241
|
+
module.exports.shouldSkipRuntimeFile = shouldSkipRuntimeFile;
|
package/bin/commands/diff.js
CHANGED
|
@@ -13,6 +13,7 @@ const fs = require('fs');
|
|
|
13
13
|
const path = require('path');
|
|
14
14
|
const tui = require('../utils/tui');
|
|
15
15
|
const { readSkillDirectory, normalizeSkillName } = require('../lib/skills');
|
|
16
|
+
const { buildCommandMarkdown } = require('../lib/generators/claude-plugin');
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Generate a simple diff between two strings
|
|
@@ -113,6 +114,71 @@ function compareFiles(skillPath, generatedPath) {
|
|
|
113
114
|
};
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Compare a loaded skill against the content that should have been generated
|
|
119
|
+
* for a specific tool. This avoids false drift from generator-owned wrappers
|
|
120
|
+
* such as Claude command frontmatter, generated comments, and update-check
|
|
121
|
+
* preambles.
|
|
122
|
+
*
|
|
123
|
+
* @param {{name: string, path: string, content: string}} skill - Loaded source skill
|
|
124
|
+
* @param {string} generatedPath - Path to generated file
|
|
125
|
+
* @param {Object} [options] - Comparison options
|
|
126
|
+
* @param {string} [options.tool] - Tool id
|
|
127
|
+
* @param {string} [options.libraryPrefix] - Library prefix used by the generator
|
|
128
|
+
* @returns {Object} Comparison result
|
|
129
|
+
*/
|
|
130
|
+
function compareSkillToGenerated(skill, generatedPath, options = {}) {
|
|
131
|
+
if (!skill || !fs.existsSync(skill.path)) {
|
|
132
|
+
return {
|
|
133
|
+
skill: skill && skill.name ? skill.name : 'unknown',
|
|
134
|
+
status: 'missing-source',
|
|
135
|
+
message: 'Source skill file not found',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!fs.existsSync(generatedPath)) {
|
|
140
|
+
return {
|
|
141
|
+
skill: skill.name,
|
|
142
|
+
status: 'not-generated',
|
|
143
|
+
message: 'Generated file does not exist (will be created on sync)',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const generatedContent = fs.readFileSync(generatedPath, 'utf8');
|
|
148
|
+
const expectedContent = buildExpectedGeneratedContent(skill, options);
|
|
149
|
+
|
|
150
|
+
if (expectedContent === generatedContent) {
|
|
151
|
+
return {
|
|
152
|
+
skill: skill.name,
|
|
153
|
+
status: 'unchanged',
|
|
154
|
+
message: 'No changes',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const diff = generateDiff(generatedContent, expectedContent);
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
skill: skill.name,
|
|
162
|
+
status: 'changed',
|
|
163
|
+
diff,
|
|
164
|
+
sourcePath: skill.path,
|
|
165
|
+
generatedPath,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {{name: string, content: string}} skill - Loaded source skill
|
|
171
|
+
* @param {Object} options - Comparison options
|
|
172
|
+
* @returns {string} Expected generated output for the scan target
|
|
173
|
+
*/
|
|
174
|
+
function buildExpectedGeneratedContent(skill, options = {}) {
|
|
175
|
+
if (options.tool === 'claude-code') {
|
|
176
|
+
return buildCommandMarkdown(skill, options.libraryPrefix || 'library');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return skill.content;
|
|
180
|
+
}
|
|
181
|
+
|
|
116
182
|
/**
|
|
117
183
|
* Get generated file path for a skill based on tool
|
|
118
184
|
* @param {string} skillName - Skill name (without .md)
|
|
@@ -291,6 +357,7 @@ function diffCommand(args, config) {
|
|
|
291
357
|
// and `path.basename(...)` would return `SKILL`, breaking the diff.
|
|
292
358
|
const results = skillFiles.map((skillPath) => {
|
|
293
359
|
const skillName = skillNameByPath.get(skillPath) || path.basename(skillPath, '.md');
|
|
360
|
+
const skill = skillsByName.get(skillName);
|
|
294
361
|
const generatedPath = getGeneratedPath(skillName, options.tool, targetDir);
|
|
295
362
|
|
|
296
363
|
if (!generatedPath) {
|
|
@@ -301,7 +368,10 @@ function diffCommand(args, config) {
|
|
|
301
368
|
};
|
|
302
369
|
}
|
|
303
370
|
|
|
304
|
-
return
|
|
371
|
+
return compareSkillToGenerated(skill, generatedPath, {
|
|
372
|
+
tool: options.tool,
|
|
373
|
+
libraryPrefix: getLibraryPrefix(targetDir, config.packageDir),
|
|
374
|
+
});
|
|
305
375
|
});
|
|
306
376
|
|
|
307
377
|
// Display results
|
|
@@ -340,6 +410,21 @@ function diffCommand(args, config) {
|
|
|
340
410
|
module.exports = Object.assign(diffCommand, {
|
|
341
411
|
generateDiff,
|
|
342
412
|
compareFiles,
|
|
413
|
+
compareSkillToGenerated,
|
|
414
|
+
buildExpectedGeneratedContent,
|
|
343
415
|
getGeneratedPath,
|
|
344
416
|
parseArgs,
|
|
345
417
|
});
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Match the Claude plugin generator's library reference behavior.
|
|
421
|
+
*
|
|
422
|
+
* @param {string} targetDir - Target project directory
|
|
423
|
+
* @param {string} packageDir - Package root
|
|
424
|
+
* @returns {string} Library prefix used in generated markdown
|
|
425
|
+
*/
|
|
426
|
+
function getLibraryPrefix(targetDir, packageDir) {
|
|
427
|
+
return fs.existsSync(path.join(targetDir, 'library'))
|
|
428
|
+
? 'library'
|
|
429
|
+
: path.join(packageDir, 'library');
|
|
430
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Setup Command
|
|
3
3
|
* =================
|
|
4
|
-
* Configures the official Microsoft MCP servers for
|
|
5
|
-
* and legacy adapter formats.
|
|
4
|
+
* Configures the official Microsoft MCP servers for an existing project-local
|
|
5
|
+
* Claude Code plugin and legacy adapter formats.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* super mcp-setup
|
|
@@ -103,6 +103,13 @@ function loadConfiguredTools(targetDir) {
|
|
|
103
103
|
return ['claude-plugin'];
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
function hasLocalPluginMarker(targetDir) {
|
|
107
|
+
return (
|
|
108
|
+
fs.existsSync(path.join(targetDir, '.bi-superpowers.json')) ||
|
|
109
|
+
fs.existsSync(path.join(targetDir, '.claude-plugin', 'plugin.json'))
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
106
113
|
function readJson(filePath) {
|
|
107
114
|
if (!fs.existsSync(filePath)) {
|
|
108
115
|
return {};
|
|
@@ -157,8 +164,24 @@ function mcpSetupCommand(args, config) {
|
|
|
157
164
|
|
|
158
165
|
if (options.deprecatedFlags.length > 0) {
|
|
159
166
|
tui.warning(
|
|
160
|
-
`Deprecated flags ignored: ${options.deprecatedFlags.join(', ')}. MCP setup
|
|
167
|
+
`Deprecated flags ignored: ${options.deprecatedFlags.join(', ')}. MCP setup now targets local Claude Code plugin configs and uses the official Microsoft servers.`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!options.tool && !hasLocalPluginMarker(targetDir)) {
|
|
172
|
+
tui.warning('mcp-setup is only for project-local Claude Code plugin configs.');
|
|
173
|
+
tui.info(
|
|
174
|
+
'For Codex, GitHub Copilot, Gemini CLI, Kilo Code, and Claude Code user-level installs, run:'
|
|
175
|
+
);
|
|
176
|
+
tui.listItem('super install --all --yes');
|
|
177
|
+
tui.info(
|
|
178
|
+
'That writes user-level skills and MCP config under your home directory without creating files in this repo.'
|
|
179
|
+
);
|
|
180
|
+
tui.info(
|
|
181
|
+
'If you intentionally need a local Claude Code plugin, run `super kickoff` first or pass `--tool claude-plugin`.'
|
|
161
182
|
);
|
|
183
|
+
process.exitCode = 2;
|
|
184
|
+
return;
|
|
162
185
|
}
|
|
163
186
|
|
|
164
187
|
let configuredTools = loadConfiguredTools(targetDir);
|
package/bin/commands/watch.js
CHANGED
|
@@ -48,6 +48,42 @@ function parseArgs(args) {
|
|
|
48
48
|
return options;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Chokidar v4 no longer supports glob paths. Watch the skill root and filter
|
|
53
|
+
* relevant runtime/source files in-process so folder-based skills are covered.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} skillsDir - Directory containing skill sources
|
|
56
|
+
* @returns {string[]} Watch roots
|
|
57
|
+
*/
|
|
58
|
+
function getWatchRoots(skillsDir) {
|
|
59
|
+
return [skillsDir];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {string} changedPath - Changed file path
|
|
64
|
+
* @param {string} skillsDir - Watched skill root
|
|
65
|
+
* @returns {boolean} Whether the changed file should trigger regeneration
|
|
66
|
+
*/
|
|
67
|
+
function isRelevantSkillPath(changedPath, skillsDir) {
|
|
68
|
+
const relative = path.relative(skillsDir, changedPath);
|
|
69
|
+
if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const base = path.basename(changedPath);
|
|
74
|
+
if (
|
|
75
|
+
base.endsWith('.test.js') ||
|
|
76
|
+
base.endsWith('.spec.js') ||
|
|
77
|
+
base.endsWith('.bak') ||
|
|
78
|
+
base.endsWith('.tmp') ||
|
|
79
|
+
base.startsWith('.')
|
|
80
|
+
) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return ['.md', '.js', '.json', '.sh'].includes(path.extname(changedPath));
|
|
85
|
+
}
|
|
86
|
+
|
|
51
87
|
/**
|
|
52
88
|
* Main watch command handler
|
|
53
89
|
* @param {string[]} args - Command arguments
|
|
@@ -91,7 +127,7 @@ function watchCommand(args, config, cliModule) {
|
|
|
91
127
|
const pendingChanges = new Set();
|
|
92
128
|
|
|
93
129
|
// Create watcher
|
|
94
|
-
const watcher = chokidar.watch(
|
|
130
|
+
const watcher = chokidar.watch(getWatchRoots(skillsDir), {
|
|
95
131
|
persistent: true,
|
|
96
132
|
ignoreInitial: true,
|
|
97
133
|
awaitWriteFinish: {
|
|
@@ -106,7 +142,11 @@ function watchCommand(args, config, cliModule) {
|
|
|
106
142
|
* @param {string} eventType - Type of event (add, change, unlink)
|
|
107
143
|
*/
|
|
108
144
|
function handleChange(changedPath, _eventType) {
|
|
109
|
-
|
|
145
|
+
if (!isRelevantSkillPath(changedPath, skillsDir)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const filename = path.relative(skillsDir, changedPath);
|
|
110
150
|
pendingChanges.add(filename);
|
|
111
151
|
|
|
112
152
|
// Clear existing timer
|
|
@@ -157,7 +197,7 @@ function watchCommand(args, config, cliModule) {
|
|
|
157
197
|
* @param {string|null} specificTool - Specific tool or null for all
|
|
158
198
|
* @param {Object} cliModule - CLI module reference
|
|
159
199
|
*/
|
|
160
|
-
function regenerateConfigs(targetDir, specificTool, cliModule) {
|
|
200
|
+
async function regenerateConfigs(targetDir, specificTool, cliModule) {
|
|
161
201
|
const ora = require('ora');
|
|
162
202
|
const spinner = ora('Regenerating configs...').start();
|
|
163
203
|
|
|
@@ -193,7 +233,7 @@ function regenerateConfigs(targetDir, specificTool, cliModule) {
|
|
|
193
233
|
|
|
194
234
|
// Call the sync logic from CLI module
|
|
195
235
|
if (cliModule && typeof cliModule.syncProjectInternal === 'function') {
|
|
196
|
-
cliModule.syncProjectInternal(targetDir, tools);
|
|
236
|
+
await cliModule.syncProjectInternal(targetDir, tools);
|
|
197
237
|
spinner.succeed(`Regenerated configs for: ${tools.join(', ')}`);
|
|
198
238
|
} else {
|
|
199
239
|
// Fallback: just report what would be done
|
|
@@ -205,4 +245,9 @@ function regenerateConfigs(targetDir, specificTool, cliModule) {
|
|
|
205
245
|
}
|
|
206
246
|
}
|
|
207
247
|
|
|
208
|
-
module.exports = watchCommand
|
|
248
|
+
module.exports = Object.assign(watchCommand, {
|
|
249
|
+
parseArgs,
|
|
250
|
+
getWatchRoots,
|
|
251
|
+
isRelevantSkillPath,
|
|
252
|
+
regenerateConfigs,
|
|
253
|
+
});
|
package/bin/postinstall.js
CHANGED
|
@@ -36,7 +36,7 @@ Funciona con los 5 agentes:
|
|
|
36
36
|
/report-design — Generá reportes PBIR para Power BI Desktop (Windows)
|
|
37
37
|
|
|
38
38
|
2 MCP servers:
|
|
39
|
-
powerbi-modeling
|
|
39
|
+
powerbi-modeling-mcp — Conexión local a Power BI Desktop (XMLA)
|
|
40
40
|
microsoft-learn — Docs de Microsoft Learn en contexto
|
|
41
41
|
|
|
42
42
|
Documentation: https://github.com/luquimbo/bi-superpowers
|
package/bin/utils/mcp-detect.js
CHANGED
|
@@ -188,7 +188,7 @@ function getInstallInstructions() {
|
|
|
188
188
|
'Ir a Extensions (Ctrl+Shift+X)',
|
|
189
189
|
'Buscar "Power BI Modeling MCP"',
|
|
190
190
|
'Instalar la extensión de Microsoft',
|
|
191
|
-
'Ejecutar: super
|
|
191
|
+
'Ejecutar: super install --all --yes',
|
|
192
192
|
],
|
|
193
193
|
link: 'https://aka.ms/powerbi-modeling-mcp-vscode',
|
|
194
194
|
},
|
package/commands/bi-start.md
CHANGED
|
@@ -55,7 +55,7 @@ Interpret the single-line output:
|
|
|
55
55
|
```bash
|
|
56
56
|
super upgrade
|
|
57
57
|
```
|
|
58
|
-
|
|
58
|
+
After it finishes, remind: _"Corré `super install --all --yes` para refrescar la instalación user-level de todos los agentes. Solo si además mantenés un plugin local de Claude Code generado con `super kickoff`, corré `super recharge` dentro de ese repo."_
|
|
59
59
|
|
|
60
60
|
On `no` — respect it, continue to PHASE 1 silently. The update-state.json already tracks the user's snooze per `update-check.js` semantics.
|
|
61
61
|
|
|
@@ -86,7 +86,7 @@ Do these detections in order:
|
|
|
86
86
|
```
|
|
87
87
|
(or equivalent). `$pbiDesktopRunning = true` if present.
|
|
88
88
|
|
|
89
|
-
4. **MCP configured**: look for
|
|
89
|
+
4. **MCP configured**: look first for `powerbi-modeling-mcp` in the agent's user-level config file (`~/.claude.json`, `~/.codex/config.toml`, etc). Only check project-root `.mcp.json` when the user explicitly says they use a local Claude Code plugin. Keep the check shallow — no need to deep-diff.
|
|
90
90
|
|
|
91
91
|
### Emit the context in 3-4 lines max
|
|
92
92
|
|
|
@@ -180,7 +180,7 @@ Stop. Don't hover. The user will tell you what they want next.
|
|
|
180
180
|
- **Project analysis or setup**: that's `/project-kickoff`. If the user says "analizar mi proyecto", "armar el modelo base", "arrancar uno nuevo desde cero", delegate.
|
|
181
181
|
- **MCP wiring details**: that's `/pbi-connect`. bi-start just offers to dispatch it; the actual configuration work is in that skill.
|
|
182
182
|
- **Report authoring**: that's `/report-design`. Same pattern.
|
|
183
|
-
- **Running the update**: bi-start offers + dispatches `super upgrade`; the actual refresh path after eso (`/plugin update bi-superpowers`, `super install --yes`, o `super recharge`) is owned by `/bin/cli.js`.
|
|
183
|
+
- **Running the update**: bi-start offers + dispatches `super upgrade`; the actual refresh path after eso (`/plugin update bi-superpowers`, `super install --all --yes`, o `super recharge` only for local Claude Code plugins) is owned by `/bin/cli.js`.
|
|
184
184
|
|
|
185
185
|
## Related Skills
|
|
186
186
|
|