@clfhhc/bmad-methods-skills 0.0.2 → 0.0.3
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/bin/bmad-skills.js +87 -3
- package/convert.js +5 -1
- package/package.json +1 -1
- package/skills/bootstrap-bmad-skills/SKILL.md +17 -41
- package/src/utils/path-rewriter.js +11 -0
- package/src/utils/resource-migrator.js +65 -0
package/bin/bmad-skills.js
CHANGED
|
@@ -79,7 +79,7 @@ async function install(args) {
|
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
console.log(
|
|
82
|
+
console.log('\n✅ Installation complete.');
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
async function init(args) {
|
|
@@ -88,6 +88,88 @@ async function init(args) {
|
|
|
88
88
|
const toolInfo = await detectTool(args);
|
|
89
89
|
if (!toolInfo) return;
|
|
90
90
|
|
|
91
|
+
// Check for bootstrap flag
|
|
92
|
+
const isBootstrap = args.includes('--bootstrap');
|
|
93
|
+
|
|
94
|
+
if (isBootstrap) {
|
|
95
|
+
console.log('🔄 Bootstrapping full BMAD suite...');
|
|
96
|
+
|
|
97
|
+
// 1. Run conversion
|
|
98
|
+
const tempDir = '.temp/converted-skills-bootstrap';
|
|
99
|
+
console.log(`\n--- Step 1: Fetching & Converting (${tempDir}) ---`);
|
|
100
|
+
process.env.BMAD_OUTPUT_DIR = tempDir; // Pass specific output dir to convert.js
|
|
101
|
+
|
|
102
|
+
// Create synthetic args for convert.js
|
|
103
|
+
// We filter out init-specific args to avoid confusion, but keep repo/branch overrides
|
|
104
|
+
const convertArgs = args.filter(a =>
|
|
105
|
+
!['init', '--bootstrap', '--force', '--tool'].some(x => a.includes(x))
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Temporarily override argv for the imported module
|
|
109
|
+
const originalArgv = process.argv;
|
|
110
|
+
process.argv = [process.argv[0], process.argv[1], ...convertArgs, '--output-dir', tempDir];
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
// Import runs the main function automatically if we aren't careful?
|
|
114
|
+
// Wait, convert.js runs main() at the end. We should probably refactor convert.js to export main
|
|
115
|
+
// but simpler hack: just run it as a child process if import is messy,
|
|
116
|
+
// OR rely on dynamic import executing top-level code.
|
|
117
|
+
// Dynamic import executes top-level code ONCE. If we imported it before, it won't run again.
|
|
118
|
+
// Safe bet: spawn a clean process.
|
|
119
|
+
const { spawn } = await import('node:child_process');
|
|
120
|
+
const binPath = fileURLToPath(import.meta.url); // this file
|
|
121
|
+
|
|
122
|
+
await new Promise((resolve, reject) => {
|
|
123
|
+
// Run self without command -> trigger convert logic
|
|
124
|
+
const child = spawn(process.execPath, [binPath, ...convertArgs, '--output-dir', tempDir], {
|
|
125
|
+
stdio: 'inherit'
|
|
126
|
+
});
|
|
127
|
+
child.on('close', (code) => {
|
|
128
|
+
if (code === 0) resolve();
|
|
129
|
+
else reject(new Error(`Conversion failed with code ${code}`));
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(`❌ Bootstrap conversion failed: ${error.message}`);
|
|
135
|
+
process.argv = originalArgv; // Restore
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
process.argv = originalArgv; // Restore
|
|
139
|
+
|
|
140
|
+
// 2. Install
|
|
141
|
+
console.log(`\n--- Step 2: Installing to ${toolInfo.name} ---`);
|
|
142
|
+
await install([
|
|
143
|
+
'install',
|
|
144
|
+
`--from=${tempDir}`,
|
|
145
|
+
`--tool=${toolInfo.name.toLowerCase()}`, // Ensure generic name match
|
|
146
|
+
'--force' // Always force in bootstrap mode? Or respect args? Let's use force for bootstrap convenience
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
// 3. Install bundled skills (bootstrap-bmad-skills, enhance-bmad-skills)
|
|
150
|
+
// We reuse the logic from the standard init, but silence it slightly or just run it
|
|
151
|
+
const skillsDir = path.join(pkgRoot, 'skills');
|
|
152
|
+
if (await fs.pathExists(skillsDir)) {
|
|
153
|
+
const skills = await fs.readdir(skillsDir);
|
|
154
|
+
for (const skill of skills) {
|
|
155
|
+
if ((await fs.stat(path.join(skillsDir, skill))).isDirectory()) {
|
|
156
|
+
await installSkill(skill, path.join(skillsDir, skill), path.join(process.cwd(), toolInfo.path, skill), true);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Cleanup
|
|
162
|
+
try {
|
|
163
|
+
await fs.remove('.temp'); // Remove generic temp if used
|
|
164
|
+
// Note: we used specific temp dir, removing that
|
|
165
|
+
if (tempDir.startsWith('.temp')) await fs.remove('.temp');
|
|
166
|
+
} catch (e) { /* ignore */ }
|
|
167
|
+
|
|
168
|
+
console.log('\n✨ Bootstrap functionality complete!');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// STANDARD INIT (Bootstrap skills only)
|
|
91
173
|
console.log(`📦 Installing Bootstrap Skills for ${toolInfo.name}...`);
|
|
92
174
|
|
|
93
175
|
// Dynamically find skills in package
|
|
@@ -125,7 +207,8 @@ async function init(args) {
|
|
|
125
207
|
console.log(`\n✅ Successfully initialized in: ${toolInfo.path}/`);
|
|
126
208
|
console.log('\nNext steps:');
|
|
127
209
|
console.log(`1. Open your AI chat (${toolInfo.name}).`);
|
|
128
|
-
console.log('2.
|
|
210
|
+
console.log('2. Run "npx @clfhhc/bmad-methods-skills init --bootstrap" to auto-install everything.');
|
|
211
|
+
console.log(' OR Type "BS" in chat for the guided workflow.');
|
|
129
212
|
} catch (error) {
|
|
130
213
|
console.error(`\n❌ Installation failed: ${error.message}`);
|
|
131
214
|
}
|
|
@@ -138,7 +221,7 @@ async function installSkill(name, source, target, force) {
|
|
|
138
221
|
if (await fs.pathExists(target)) {
|
|
139
222
|
if (!force) {
|
|
140
223
|
console.warn(` ⚠ Skill '${name}' already exists. Skipping.`);
|
|
141
|
-
|
|
224
|
+
console.warn(' (Use --force to overwrite)');
|
|
142
225
|
return;
|
|
143
226
|
}
|
|
144
227
|
console.log(` ↻ Updating ${name}...`);
|
|
@@ -196,6 +279,7 @@ Commands:
|
|
|
196
279
|
Options (for init/install):
|
|
197
280
|
--tool=<name> Specify tool (antigravity, cursor, claude)
|
|
198
281
|
--force Overwrite existing skills / Force installation
|
|
282
|
+
--bootstrap Automatically fetch, convert, and install full suite
|
|
199
283
|
--from=<path> (install only) Source directory containing skills
|
|
200
284
|
|
|
201
285
|
Options (for conversion):
|
package/convert.js
CHANGED
|
@@ -6,6 +6,7 @@ import { findAgentsAndWorkflows } from './src/utils/file-finder.js';
|
|
|
6
6
|
import { convertAgentToSkill } from './src/converters/agent-converter.js';
|
|
7
7
|
import { convertWorkflowToSkill } from './src/converters/workflow-converter.js';
|
|
8
8
|
import { writeSkill } from './src/utils/skill-writer.js';
|
|
9
|
+
import { migrateResources } from './src/utils/resource-migrator.js';
|
|
9
10
|
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = path.dirname(__filename);
|
|
@@ -300,7 +301,10 @@ async function main() {
|
|
|
300
301
|
console.log();
|
|
301
302
|
}
|
|
302
303
|
|
|
303
|
-
// Step 6:
|
|
304
|
+
// Step 6: Migrate auxiliary resources
|
|
305
|
+
await migrateResources(bmadRoot, outputDir);
|
|
306
|
+
|
|
307
|
+
// Step 7: Generate summary
|
|
304
308
|
await printSummary();
|
|
305
309
|
} catch (error) {
|
|
306
310
|
console.error(`\n❌ Fatal error: ${error.message}`);
|
package/package.json
CHANGED
|
@@ -15,52 +15,28 @@ This skill guides the user through fetching, converting, enhancing, and installi
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
### Step 1: Automated Bootstrap (Recommended)
|
|
19
|
+
Run the automated bootstrap command to fetch, convert, and install the full BMAD method suite.
|
|
20
|
+
1. **Run**: `npx @clfhhc/bmad-methods-skills init --bootstrap`
|
|
21
|
+
2. **Verify**: Check that skills are installed in the tool directory (e.g., `.agent/skills`).
|
|
19
22
|
|
|
20
|
-
### Step
|
|
21
|
-
|
|
22
|
-
- [ ] Claude Code
|
|
23
|
-
- [ ] Cursor
|
|
24
|
-
- [ ] Antigravity
|
|
25
|
-
- [ ] Other (Specify)
|
|
23
|
+
### Step 2: Manual Workflow (Alternative)
|
|
24
|
+
If custom configuration is needed, follow these steps:
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- **Global**: Skills will be available across all projects for that tool.
|
|
30
|
-
- **Project-Specific**: Skills will be limited to the current repository.
|
|
26
|
+
**2.1 Fetch & Convert**
|
|
27
|
+
Run `npx @clfhhc/bmad-methods-skills --output-dir .temp/converted-skills` to fetch the `main` branch and convert agents/workflows.
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
**2.2 Apply Enhancements**
|
|
30
|
+
1. **Scan Paths**: Check for `{project-root}` references.
|
|
31
|
+
2. **Adapt Paths**: Adjust paths for your specific installation scope.
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
**2.3 Install Skills**
|
|
34
|
+
Run the `install` command to move skills to their final destination.
|
|
35
|
+
- Run `npx @clfhhc/bmad-methods-skills install --from .temp/converted-skills --tool [TOOL] --force`
|
|
36
|
+
- Replace `[TOOL]` with `antigravity`, `cursor`, or `claude`.
|
|
37
37
|
|
|
38
|
-
### Step
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
1. **Scan Paths**: Use the `enhance-bmad-skills` (`SP`) command to scan the converted skills for `{project-root}` references.
|
|
42
|
-
2. **Adapt Paths**: Propose path adaptations (relative vs absolute) based on the target installation type.
|
|
43
|
-
- If **Global**: Prefer absolute paths or relative to a fixed global root.
|
|
44
|
-
- If **Project-Specific**: Prefer relative paths within the project.
|
|
45
|
-
|
|
46
|
-
### Step 5: Install Skills
|
|
47
|
-
Run the `install` command to move the enhanced skills to their final destination.
|
|
48
|
-
|
|
49
|
-
1. **Install**: Run `npx @clfhhc/bmad-methods-skills install --from .temp/converted-skills --tool [TOOL] --force`
|
|
50
|
-
- Replace `[TOOL]` with `antigravity`, `cursor`, or `claude`.
|
|
51
|
-
- Use `--force` to overwrite if you are sure.
|
|
52
|
-
|
|
53
|
-
| Tool | Scope | Destination |
|
|
54
|
-
|------|-------|-------------|
|
|
55
|
-
| **Claude Code** | Global | `~/.claude/skills/` |
|
|
56
|
-
| **Claude Code** | Local | `./.claude/skills/` |
|
|
57
|
-
| **Cursor** | Local | `./.cursor/skills/` |
|
|
58
|
-
| **Antigravity** | Local | `./.agent/skills/` |
|
|
59
|
-
|
|
60
|
-
*Note: The CLI will handle directory creation and copying.*
|
|
61
|
-
|
|
62
|
-
### Step 6: Verify
|
|
63
|
-
Ensure all file paths in the `SKILL.md` files are correct and that any referenced `data/` or `knowledge/` folders were moved correctly.
|
|
38
|
+
### Step 3: Verify
|
|
39
|
+
Ensure all file paths in the `SKILL.md` files are correct and that `data/` or `knowledge/` folders were moved correctly (automated in Step 1).
|
|
64
40
|
|
|
65
41
|
---
|
|
66
42
|
|
|
@@ -148,6 +148,17 @@ export function rewriteBmadPaths(content, _currentModule = 'bmm') {
|
|
|
148
148
|
`${relativePrefix}/bmm/tea/tea-index.csv`
|
|
149
149
|
);
|
|
150
150
|
|
|
151
|
+
// Rewrite documentation-standards.md references (migrated to tech-writer/data)
|
|
152
|
+
// {project-root}/_bmad/bmm/data/documentation-standards.md -> ../../bmm/tech-writer/data/documentation-standards.md
|
|
153
|
+
// But wait, if we are IN tech-writer, it should be ./data/documentation-standards.md
|
|
154
|
+
// The relativePrefix logic handles ../.. but we might prefer a direct replacement here
|
|
155
|
+
// since it's a specific file.
|
|
156
|
+
// Let's rely on the generic ../..bmm/tech-writer/data approach which works from anywhere.
|
|
157
|
+
result = result.replace(
|
|
158
|
+
/\{project-root\}\/_bmad\/bmm\/data\/documentation-standards\.md/g,
|
|
159
|
+
`${relativePrefix}/bmm/tech-writer/data/documentation-standards.md`
|
|
160
|
+
);
|
|
161
|
+
|
|
151
162
|
// Rewrite _memory sidecar references (these are runtime, mark as placeholder)
|
|
152
163
|
result = result.replace(
|
|
153
164
|
/\{project-root\}\/_bmad\/_memory\/([^/\s'"]+)/g,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Migrates specific data and knowledge resources from BMAD repo to skills output
|
|
6
|
+
* @param {string} bmadRoot - Root of the fetched BMAD repo
|
|
7
|
+
* @param {string} outputDir - Root of the skills output directory
|
|
8
|
+
*/
|
|
9
|
+
export async function migrateResources(bmadRoot, outputDir) {
|
|
10
|
+
console.log('📦 Migrating auxiliary resources...');
|
|
11
|
+
|
|
12
|
+
const migrations = [
|
|
13
|
+
{
|
|
14
|
+
// Tech Writer: documentation-standards.md
|
|
15
|
+
// From: src/modules/bmm/data/documentation-standards.md
|
|
16
|
+
// To: bmm/tech-writer/data/documentation-standards.md
|
|
17
|
+
src: path.join('src', 'modules', 'bmm', 'data', 'documentation-standards.md'),
|
|
18
|
+
dest: path.join('bmm', 'tech-writer', 'data', 'documentation-standards.md'),
|
|
19
|
+
name: 'Documentation Standards',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
// TEA: tea-index.csv
|
|
23
|
+
// From: src/modules/bmm/testarch/tea-index.csv
|
|
24
|
+
// To: bmm/tea/tea-index.csv
|
|
25
|
+
src: path.join('src', 'modules', 'bmm', 'testarch', 'tea-index.csv'),
|
|
26
|
+
dest: path.join('bmm', 'tea', 'tea-index.csv'),
|
|
27
|
+
name: 'TEA Index',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
// TEA: knowledge directory
|
|
31
|
+
// From: src/modules/bmm/testarch/knowledge/
|
|
32
|
+
// To: bmm/tea/knowledge/
|
|
33
|
+
src: path.join('src', 'modules', 'bmm', 'testarch', 'knowledge'),
|
|
34
|
+
dest: path.join('bmm', 'tea', 'knowledge'),
|
|
35
|
+
name: 'TEA Knowledge Base',
|
|
36
|
+
isDirectory: true,
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
let migratedCount = 0;
|
|
41
|
+
|
|
42
|
+
for (const migration of migrations) {
|
|
43
|
+
try {
|
|
44
|
+
const srcPath = path.join(bmadRoot, migration.src);
|
|
45
|
+
const destPath = path.join(outputDir, migration.dest);
|
|
46
|
+
|
|
47
|
+
if (await fs.pathExists(srcPath)) {
|
|
48
|
+
await fs.ensureDir(path.dirname(destPath));
|
|
49
|
+
await fs.copy(srcPath, destPath, { overwrite: true });
|
|
50
|
+
console.log(` ✓ Migrated ${migration.name}`);
|
|
51
|
+
migratedCount++;
|
|
52
|
+
} else {
|
|
53
|
+
console.warn(` ⚠️ Source not found for ${migration.name}: ${migration.src}`);
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error(` ✗ Failed to migrate ${migration.name}: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(` ✓ Migrated ${migratedCount} resources\n`);
|
|
61
|
+
if (migratedCount < migrations.length) {
|
|
62
|
+
console.warn(' ⚠️ Some resources were not found. This may happen if the BMAD repository structure has changed.');
|
|
63
|
+
console.warn(' Please check if a newer version of @clfhhc/bmad-methods-skills is available.');
|
|
64
|
+
}
|
|
65
|
+
}
|