@clfhhc/bmad-methods-skills 0.0.2 → 0.0.5
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/README.md +7 -3
- package/bin/bmad-skills.js +150 -35
- package/config.json +2 -8
- package/convert.js +29 -28
- package/docs/PLAN.md +523 -0
- package/docs/development.md +51 -0
- package/package.json +21 -7
- package/skills/bootstrap-bmad-skills/SKILL.md +17 -41
- package/src/converters/agent-converter.js +36 -32
- package/src/converters/workflow-converter.js +69 -56
- package/src/utils/bmad-fetcher.js +15 -33
- package/src/utils/file-finder.js +29 -23
- package/src/utils/path-rewriter.js +17 -6
- package/src/utils/resource-migrator.js +84 -0
- package/src/utils/skill-writer.js +10 -10
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# BMAD-Methods-Skills
|
|
2
2
|
|
|
3
|
+
[](https://github.com/clfhhc/BMAD-Methods-Skills/actions/workflows/release.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@clfhhc/bmad-methods-skills)
|
|
5
|
+
|
|
3
6
|
Automatically convert BMAD-METHOD agents and workflows to Claude Skills format.
|
|
4
7
|
|
|
5
8
|
## Distribution (New Projects)
|
|
@@ -7,13 +10,14 @@ Automatically convert BMAD-METHOD agents and workflows to Claude Skills format.
|
|
|
7
10
|
To install the BMAD bootstrap skill into a new project, you can use `npx`:
|
|
8
11
|
|
|
9
12
|
```bash
|
|
10
|
-
npx @clfhhc/bmad-methods-skills init
|
|
13
|
+
npx @clfhhc/bmad-methods-skills init --bootstrap
|
|
11
14
|
```
|
|
12
15
|
|
|
13
16
|
This will:
|
|
14
17
|
1. Detect your AI tool (.agent, .cursor, or .claude)
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
18
|
+
2. Automatically fetch, convert, and install the complete BMAD method suite
|
|
19
|
+
3. Install `bootstrap-bmad-skills` and `enhance-bmad-skills` for future maintenance
|
|
20
|
+
4. Enable the `BS` command as a manual backup workflow
|
|
17
21
|
|
|
18
22
|
## Documentation
|
|
19
23
|
|
package/bin/bmad-skills.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
3
|
import path from 'node:path';
|
|
5
4
|
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import
|
|
5
|
+
import fs from 'fs-extra';
|
|
7
6
|
|
|
8
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
8
|
const __dirname = path.dirname(__filename);
|
|
@@ -17,7 +16,12 @@ async function run() {
|
|
|
17
16
|
await init(args);
|
|
18
17
|
} else if (command === 'install') {
|
|
19
18
|
await install(args);
|
|
20
|
-
} else if (
|
|
19
|
+
} else if (
|
|
20
|
+
command === '--help' ||
|
|
21
|
+
command === '-h' ||
|
|
22
|
+
args.includes('--help') ||
|
|
23
|
+
args.includes('-h')
|
|
24
|
+
) {
|
|
21
25
|
printHelp();
|
|
22
26
|
} else {
|
|
23
27
|
// Proxy to convert.js logic
|
|
@@ -25,13 +29,11 @@ async function run() {
|
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
32
|
/**
|
|
31
33
|
* Install specific skills from a source directory to the project's skill directory
|
|
32
34
|
*/
|
|
33
35
|
async function install(args) {
|
|
34
|
-
const sourceArg = args.find(a => a.startsWith('--from='))?.split('=')[1];
|
|
36
|
+
const sourceArg = args.find((a) => a.startsWith('--from='))?.split('=')[1];
|
|
35
37
|
const force = args.includes('--force');
|
|
36
38
|
|
|
37
39
|
if (!sourceArg) {
|
|
@@ -55,7 +57,7 @@ async function install(args) {
|
|
|
55
57
|
// Get skills from source
|
|
56
58
|
const skills = await fs.readdir(sourcePath);
|
|
57
59
|
const validSkills = [];
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
for (const skill of skills) {
|
|
60
62
|
if ((await fs.stat(path.join(sourcePath, skill))).isDirectory()) {
|
|
61
63
|
validSkills.push(skill);
|
|
@@ -68,18 +70,18 @@ async function install(args) {
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
console.log(`\nFound ${validSkills.length} skills to install.`);
|
|
71
|
-
|
|
73
|
+
|
|
72
74
|
// Install
|
|
73
75
|
for (const skillName of validSkills) {
|
|
74
76
|
await installSkill(
|
|
75
|
-
skillName,
|
|
76
|
-
path.join(sourcePath, skillName),
|
|
77
|
+
skillName,
|
|
78
|
+
path.join(sourcePath, skillName),
|
|
77
79
|
path.join(process.cwd(), toolInfo.path, skillName),
|
|
78
80
|
force
|
|
79
81
|
);
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
console.log(
|
|
84
|
+
console.log('\n✅ Installation complete.');
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
async function init(args) {
|
|
@@ -88,44 +90,140 @@ async function init(args) {
|
|
|
88
90
|
const toolInfo = await detectTool(args);
|
|
89
91
|
if (!toolInfo) return;
|
|
90
92
|
|
|
93
|
+
// Check for bootstrap flag
|
|
94
|
+
const isBootstrap = args.includes('--bootstrap');
|
|
95
|
+
|
|
96
|
+
if (isBootstrap) {
|
|
97
|
+
console.log('🔄 Bootstrapping full BMAD suite...');
|
|
98
|
+
|
|
99
|
+
// 1. Run conversion
|
|
100
|
+
const tempDir = '.temp/converted-skills-bootstrap';
|
|
101
|
+
console.log(`\n--- Step 1: Fetching & Converting (${tempDir}) ---`);
|
|
102
|
+
process.env.BMAD_OUTPUT_DIR = tempDir; // Pass specific output dir to convert.js
|
|
103
|
+
|
|
104
|
+
// Create synthetic args for convert.js
|
|
105
|
+
// We filter out init-specific args to avoid confusion, but keep repo/branch overrides
|
|
106
|
+
const convertArgs = args.filter(
|
|
107
|
+
(a) =>
|
|
108
|
+
!['init', '--bootstrap', '--force', '--tool'].some((x) => a.includes(x))
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// Temporarily override argv for the imported module
|
|
112
|
+
const originalArgv = process.argv;
|
|
113
|
+
process.argv = [
|
|
114
|
+
process.argv[0],
|
|
115
|
+
process.argv[1],
|
|
116
|
+
...convertArgs,
|
|
117
|
+
'--output-dir',
|
|
118
|
+
tempDir,
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const { spawn } = await import('node:child_process');
|
|
123
|
+
const binPath = fileURLToPath(import.meta.url); // this file
|
|
124
|
+
|
|
125
|
+
await new Promise((resolve, reject) => {
|
|
126
|
+
// Run self without command -> trigger convert logic
|
|
127
|
+
const child = spawn(
|
|
128
|
+
process.execPath,
|
|
129
|
+
[binPath, ...convertArgs, '--output-dir', tempDir],
|
|
130
|
+
{
|
|
131
|
+
stdio: 'inherit',
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
child.on('close', (code) => {
|
|
135
|
+
if (code === 0) resolve();
|
|
136
|
+
else reject(new Error(`Conversion failed with code ${code}`));
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error(`❌ Bootstrap conversion failed: ${error.message}`);
|
|
141
|
+
process.argv = originalArgv; // Restore
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
process.argv = originalArgv; // Restore
|
|
145
|
+
|
|
146
|
+
// 2. Install
|
|
147
|
+
console.log(`\n--- Step 2: Installing to ${toolInfo.name} ---`);
|
|
148
|
+
await install([
|
|
149
|
+
'install',
|
|
150
|
+
`--from=${tempDir}`,
|
|
151
|
+
`--tool=${toolInfo.name.toLowerCase()}`, // Ensure generic name match
|
|
152
|
+
'--force', // Always force in bootstrap mode? Or respect args? Let's use force for bootstrap convenience
|
|
153
|
+
]);
|
|
154
|
+
|
|
155
|
+
// 3. Install bundled skills (bootstrap-bmad-skills, enhance-bmad-skills)
|
|
156
|
+
// We reuse the logic from the standard init, but silence it slightly or just run it
|
|
157
|
+
const skillsDir = path.join(pkgRoot, 'skills');
|
|
158
|
+
if (await fs.pathExists(skillsDir)) {
|
|
159
|
+
const skills = await fs.readdir(skillsDir);
|
|
160
|
+
for (const skill of skills) {
|
|
161
|
+
if ((await fs.stat(path.join(skillsDir, skill))).isDirectory()) {
|
|
162
|
+
await installSkill(
|
|
163
|
+
skill,
|
|
164
|
+
path.join(skillsDir, skill),
|
|
165
|
+
path.join(process.cwd(), toolInfo.path, skill),
|
|
166
|
+
true
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Cleanup
|
|
173
|
+
try {
|
|
174
|
+
await fs.remove('.temp'); // Remove generic temp if used
|
|
175
|
+
// Note: we used specific temp dir, removing that
|
|
176
|
+
if (tempDir.startsWith('.temp')) await fs.remove('.temp');
|
|
177
|
+
} catch (_e) {
|
|
178
|
+
/* ignore */
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
console.log('\n✨ Bootstrap functionality complete!');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// STANDARD INIT (Bootstrap skills only)
|
|
91
186
|
console.log(`📦 Installing Bootstrap Skills for ${toolInfo.name}...`);
|
|
92
187
|
|
|
93
188
|
// Dynamically find skills in package
|
|
94
189
|
const skillsDir = path.join(pkgRoot, 'skills');
|
|
95
190
|
if (!(await fs.pathExists(skillsDir))) {
|
|
96
|
-
|
|
97
|
-
|
|
191
|
+
console.error('❌ Critical Error: Package skills directory not found.');
|
|
192
|
+
return;
|
|
98
193
|
}
|
|
99
194
|
|
|
100
195
|
const skills = await fs.readdir(skillsDir);
|
|
101
196
|
const skillsToInstall = [];
|
|
102
|
-
|
|
197
|
+
|
|
103
198
|
for (const skill of skills) {
|
|
104
199
|
// Only install directories as skills
|
|
105
200
|
if ((await fs.stat(path.join(skillsDir, skill))).isDirectory()) {
|
|
106
|
-
|
|
201
|
+
skillsToInstall.push(skill);
|
|
107
202
|
}
|
|
108
203
|
}
|
|
109
204
|
|
|
110
205
|
if (skillsToInstall.length === 0) {
|
|
111
|
-
|
|
112
|
-
|
|
206
|
+
console.warn('⚠️ No skills found in package to install.');
|
|
207
|
+
return;
|
|
113
208
|
}
|
|
114
|
-
|
|
209
|
+
|
|
115
210
|
const force = args.includes('--force');
|
|
116
211
|
|
|
117
212
|
try {
|
|
118
213
|
for (const skillName of skillsToInstall) {
|
|
119
214
|
const sourceDir = path.join(skillsDir, skillName);
|
|
120
215
|
const targetDir = path.resolve(process.cwd(), toolInfo.path, skillName);
|
|
121
|
-
|
|
216
|
+
|
|
122
217
|
await installSkill(skillName, sourceDir, targetDir, force);
|
|
123
218
|
}
|
|
124
|
-
|
|
219
|
+
|
|
125
220
|
console.log(`\n✅ Successfully initialized in: ${toolInfo.path}/`);
|
|
126
221
|
console.log('\nNext steps:');
|
|
127
222
|
console.log(`1. Open your AI chat (${toolInfo.name}).`);
|
|
128
|
-
console.log(
|
|
223
|
+
console.log(
|
|
224
|
+
'2. Run "npx @clfhhc/bmad-methods-skills init --bootstrap" to auto-install everything.'
|
|
225
|
+
);
|
|
226
|
+
console.log(' OR Type "BS" in chat for the guided workflow.');
|
|
129
227
|
} catch (error) {
|
|
130
228
|
console.error(`\n❌ Installation failed: ${error.message}`);
|
|
131
229
|
}
|
|
@@ -138,14 +236,14 @@ async function installSkill(name, source, target, force) {
|
|
|
138
236
|
if (await fs.pathExists(target)) {
|
|
139
237
|
if (!force) {
|
|
140
238
|
console.warn(` ⚠ Skill '${name}' already exists. Skipping.`);
|
|
141
|
-
|
|
239
|
+
console.warn(' (Use --force to overwrite)');
|
|
142
240
|
return;
|
|
143
241
|
}
|
|
144
242
|
console.log(` ↻ Updating ${name}...`);
|
|
145
243
|
} else {
|
|
146
244
|
console.log(` + Installing ${name}...`);
|
|
147
245
|
}
|
|
148
|
-
|
|
246
|
+
|
|
149
247
|
await fs.ensureDir(path.dirname(target));
|
|
150
248
|
await fs.copy(source, target, { overwrite: true });
|
|
151
249
|
}
|
|
@@ -154,29 +252,45 @@ async function installSkill(name, source, target, force) {
|
|
|
154
252
|
* Helper to detect AI tool
|
|
155
253
|
*/
|
|
156
254
|
async function detectTool(args) {
|
|
157
|
-
const toolArg = args.find(a => a.startsWith('--tool='))?.split('=')[1];
|
|
255
|
+
const toolArg = args.find((a) => a.startsWith('--tool='))?.split('=')[1];
|
|
158
256
|
const force = args.includes('--force');
|
|
159
257
|
|
|
160
258
|
const tools = [
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
259
|
+
{
|
|
260
|
+
name: 'Antigravity',
|
|
261
|
+
path: '.agent/skills',
|
|
262
|
+
active: await fs.pathExists('.agent'),
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: 'Cursor',
|
|
266
|
+
path: '.cursor/skills',
|
|
267
|
+
active: await fs.pathExists('.cursor'),
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: 'Claude Code (Local)',
|
|
271
|
+
path: '.claude/skills',
|
|
272
|
+
active: await fs.pathExists('.claude'),
|
|
273
|
+
},
|
|
164
274
|
];
|
|
165
275
|
|
|
166
|
-
let selectedTool = tools.find(t => t.active);
|
|
167
|
-
|
|
276
|
+
let selectedTool = tools.find((t) => t.active);
|
|
277
|
+
|
|
168
278
|
if (toolArg) {
|
|
169
|
-
selectedTool = tools.find(t =>
|
|
279
|
+
selectedTool = tools.find((t) =>
|
|
280
|
+
t.name.toLowerCase().includes(toolArg.toLowerCase())
|
|
281
|
+
);
|
|
170
282
|
}
|
|
171
283
|
|
|
172
284
|
if (!selectedTool) {
|
|
173
285
|
if (force) {
|
|
174
|
-
|
|
175
|
-
|
|
286
|
+
// Default to antigravity if forced and not found
|
|
287
|
+
return tools[0];
|
|
176
288
|
}
|
|
177
|
-
|
|
289
|
+
|
|
178
290
|
console.log('❌ No AI tool directory detected (.agent, .cursor, .claude).');
|
|
179
|
-
console.log(
|
|
291
|
+
console.log(
|
|
292
|
+
' Use --tool=<name> to force installation or ensure you are in the project root.'
|
|
293
|
+
);
|
|
180
294
|
console.log(' Available tools: antigravity, cursor, claude');
|
|
181
295
|
return null;
|
|
182
296
|
}
|
|
@@ -196,6 +310,7 @@ Commands:
|
|
|
196
310
|
Options (for init/install):
|
|
197
311
|
--tool=<name> Specify tool (antigravity, cursor, claude)
|
|
198
312
|
--force Overwrite existing skills / Force installation
|
|
313
|
+
--bootstrap Automatically fetch, convert, and install full suite
|
|
199
314
|
--from=<path> (install only) Source directory containing skills
|
|
200
315
|
|
|
201
316
|
Options (for conversion):
|
|
@@ -211,7 +326,7 @@ Options (for conversion):
|
|
|
211
326
|
`);
|
|
212
327
|
}
|
|
213
328
|
|
|
214
|
-
run().catch(err => {
|
|
329
|
+
run().catch((err) => {
|
|
215
330
|
console.error(err);
|
|
216
331
|
process.exit(1);
|
|
217
332
|
});
|
package/config.json
CHANGED
|
@@ -4,14 +4,8 @@
|
|
|
4
4
|
"outputDir": "./skills",
|
|
5
5
|
"tempDir": "./.temp/bmad-method",
|
|
6
6
|
"modules": ["bmm", "bmb", "cis", "core"],
|
|
7
|
-
"agentPaths": [
|
|
8
|
-
|
|
9
|
-
"src/modules/*/agents"
|
|
10
|
-
],
|
|
11
|
-
"workflowPaths": [
|
|
12
|
-
"src/core/workflows",
|
|
13
|
-
"src/modules/*/workflows"
|
|
14
|
-
],
|
|
7
|
+
"agentPaths": ["src/core/agents", "src/modules/*/agents"],
|
|
8
|
+
"workflowPaths": ["src/core/workflows", "src/modules/*/workflows"],
|
|
15
9
|
"enhancements": {
|
|
16
10
|
"optional": {
|
|
17
11
|
"addExamples": true,
|
package/convert.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import
|
|
5
|
-
import { findAgentsAndWorkflows } from './src/utils/file-finder.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
6
4
|
import { convertAgentToSkill } from './src/converters/agent-converter.js';
|
|
7
5
|
import { convertWorkflowToSkill } from './src/converters/workflow-converter.js';
|
|
6
|
+
import { fetchBmadRepo } from './src/utils/bmad-fetcher.js';
|
|
7
|
+
import { findAgentsAndWorkflows } from './src/utils/file-finder.js';
|
|
8
|
+
import { migrateResources } from './src/utils/resource-migrator.js';
|
|
8
9
|
import { writeSkill } from './src/utils/skill-writer.js';
|
|
9
10
|
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -29,7 +30,7 @@ function parseArgs() {
|
|
|
29
30
|
|
|
30
31
|
for (let i = 0; i < args.length; i++) {
|
|
31
32
|
const arg = args[i];
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
if (arg === '--output-dir' && i + 1 < args.length) {
|
|
34
35
|
options.outputDir = args[++i];
|
|
35
36
|
} else if (arg === '--repo' && i + 1 < args.length) {
|
|
@@ -167,7 +168,8 @@ try {
|
|
|
167
168
|
config.enhancements.optional.addBestPractices = cliOptions.addBestPractices;
|
|
168
169
|
}
|
|
169
170
|
if (cliOptions.addTroubleshooting !== null) {
|
|
170
|
-
config.enhancements.optional.addTroubleshooting =
|
|
171
|
+
config.enhancements.optional.addTroubleshooting =
|
|
172
|
+
cliOptions.addTroubleshooting;
|
|
171
173
|
}
|
|
172
174
|
if (cliOptions.addRelatedSkills !== null) {
|
|
173
175
|
config.enhancements.optional.addRelatedSkills = cliOptions.addRelatedSkills;
|
|
@@ -199,7 +201,7 @@ async function main() {
|
|
|
199
201
|
const bmadRoot = await fetchBmadRepo(
|
|
200
202
|
config.bmadRepo,
|
|
201
203
|
config.bmadBranch,
|
|
202
|
-
path.resolve(process.cwd(), config.tempDir)
|
|
204
|
+
path.resolve(process.cwd(), config.tempDir)
|
|
203
205
|
);
|
|
204
206
|
console.log(`✓ Repository ready at: ${bmadRoot}\n`);
|
|
205
207
|
|
|
@@ -208,14 +210,14 @@ async function main() {
|
|
|
208
210
|
const { agents, workflows } = await findAgentsAndWorkflows(
|
|
209
211
|
bmadRoot,
|
|
210
212
|
config.agentPaths,
|
|
211
|
-
config.workflowPaths
|
|
213
|
+
config.workflowPaths
|
|
212
214
|
);
|
|
213
215
|
|
|
214
216
|
stats.agents.total = agents.length;
|
|
215
217
|
stats.workflows.total = workflows.length;
|
|
216
218
|
|
|
217
219
|
console.log(
|
|
218
|
-
`✓ Found ${agents.length} agents and ${workflows.length} workflows\n
|
|
220
|
+
`✓ Found ${agents.length} agents and ${workflows.length} workflows\n`
|
|
219
221
|
);
|
|
220
222
|
|
|
221
223
|
// Step 3: Prepare output directory
|
|
@@ -237,12 +239,7 @@ async function main() {
|
|
|
237
239
|
...agentOptions,
|
|
238
240
|
currentModule: agent.module,
|
|
239
241
|
});
|
|
240
|
-
await writeSkill(
|
|
241
|
-
outputDir,
|
|
242
|
-
agent.module,
|
|
243
|
-
agent.name,
|
|
244
|
-
skillContent,
|
|
245
|
-
);
|
|
242
|
+
await writeSkill(outputDir, agent.module, agent.name, skillContent);
|
|
246
243
|
stats.agents.converted++;
|
|
247
244
|
console.log(` ✓ ${agent.module}/${agent.name}`);
|
|
248
245
|
} catch (error) {
|
|
@@ -252,9 +249,7 @@ async function main() {
|
|
|
252
249
|
path: agent.path,
|
|
253
250
|
error: error.message,
|
|
254
251
|
});
|
|
255
|
-
console.error(
|
|
256
|
-
` ✗ ${agent.module}/${agent.name}: ${error.message}`,
|
|
257
|
-
);
|
|
252
|
+
console.error(` ✗ ${agent.module}/${agent.name}: ${error.message}`);
|
|
258
253
|
}
|
|
259
254
|
}
|
|
260
255
|
console.log();
|
|
@@ -274,14 +269,14 @@ async function main() {
|
|
|
274
269
|
{
|
|
275
270
|
...workflowOptions,
|
|
276
271
|
isMarkdown: workflow.isMarkdown || false,
|
|
277
|
-
}
|
|
272
|
+
}
|
|
278
273
|
);
|
|
279
274
|
await writeSkill(
|
|
280
275
|
outputDir,
|
|
281
276
|
workflow.module,
|
|
282
277
|
workflow.name,
|
|
283
278
|
skillContent,
|
|
284
|
-
{ workflowDir: workflow.workflowDir }
|
|
279
|
+
{ workflowDir: workflow.workflowDir }
|
|
285
280
|
);
|
|
286
281
|
stats.workflows.converted++;
|
|
287
282
|
console.log(` ✓ ${workflow.module}/${workflow.name}`);
|
|
@@ -293,14 +288,17 @@ async function main() {
|
|
|
293
288
|
error: error.message,
|
|
294
289
|
});
|
|
295
290
|
console.error(
|
|
296
|
-
` ✗ ${workflow.module}/${workflow.name}: ${error.message}
|
|
291
|
+
` ✗ ${workflow.module}/${workflow.name}: ${error.message}`
|
|
297
292
|
);
|
|
298
293
|
}
|
|
299
294
|
}
|
|
300
295
|
console.log();
|
|
301
296
|
}
|
|
302
297
|
|
|
303
|
-
// Step 6:
|
|
298
|
+
// Step 6: Migrate auxiliary resources
|
|
299
|
+
await migrateResources(bmadRoot, outputDir);
|
|
300
|
+
|
|
301
|
+
// Step 7: Generate summary
|
|
304
302
|
await printSummary();
|
|
305
303
|
} catch (error) {
|
|
306
304
|
console.error(`\n❌ Fatal error: ${error.message}`);
|
|
@@ -325,8 +323,7 @@ async function printSummary() {
|
|
|
325
323
|
console.log(` Errors: ${stats.workflows.errors}`);
|
|
326
324
|
console.log();
|
|
327
325
|
|
|
328
|
-
const totalConverted =
|
|
329
|
-
stats.agents.converted + stats.workflows.converted;
|
|
326
|
+
const totalConverted = stats.agents.converted + stats.workflows.converted;
|
|
330
327
|
const totalErrors = stats.agents.errors + stats.workflows.errors;
|
|
331
328
|
|
|
332
329
|
if (totalErrors > 0) {
|
|
@@ -340,19 +337,23 @@ async function printSummary() {
|
|
|
340
337
|
|
|
341
338
|
console.log(`✅ Successfully converted ${totalConverted} skills`);
|
|
342
339
|
console.log(
|
|
343
|
-
`📁 Output directory: ${path.resolve(process.cwd(), config.outputDir)}
|
|
340
|
+
`📁 Output directory: ${path.resolve(process.cwd(), config.outputDir)}`
|
|
344
341
|
);
|
|
345
|
-
|
|
342
|
+
|
|
346
343
|
// Show configuration info
|
|
347
344
|
if (config.outputDir !== './skills') {
|
|
348
345
|
console.log('\n💡 Note: Output directory is not the default (./skills)');
|
|
349
346
|
console.log(' This directory is not version controlled.');
|
|
350
347
|
console.log(' To use default settings, run without --output-dir flag.');
|
|
351
348
|
}
|
|
352
|
-
|
|
349
|
+
|
|
353
350
|
if (config.enhancements.identityCharLimit !== null) {
|
|
354
|
-
console.log(
|
|
355
|
-
|
|
351
|
+
console.log(
|
|
352
|
+
`\n💡 Note: Identity character limit is set to ${config.enhancements.identityCharLimit}`
|
|
353
|
+
);
|
|
354
|
+
console.log(
|
|
355
|
+
' Default behavior (no limit) is recommended for better content.'
|
|
356
|
+
);
|
|
356
357
|
}
|
|
357
358
|
|
|
358
359
|
// Print per-module breakdown
|