feat(install): clean up skill directories from _bmad after IDE install

Skills are self-contained in IDE directories, so _bmad/ only needs
module-level files (config.yaml, _config/). After all IDE setups
complete, remove skill directories from _bmad/ via skill-manifest.csv.
Also cleans up skill dirs left by older installer versions.
This commit is contained in:
Alex Verkhovsky 2026-04-01 14:21:14 -07:00
parent 5d01549ea2
commit 6527a5f28a
1 changed files with 31 additions and 0 deletions

View File

@ -132,6 +132,10 @@ class Installer {
await this._setupIdes(config, allModules, paths, addResult, previousSkillIds); await this._setupIdes(config, allModules, paths, addResult, previousSkillIds);
// Skills are now in IDE directories — remove redundant copies from _bmad/.
// Also cleans up skill dirs left by older installer versions.
await this._cleanupSkillDirs(paths.bmadDir);
const restoreResult = await this._restoreUserFiles(paths, updateState); const restoreResult = await this._restoreUserFiles(paths, updateState);
// Render consolidated summary // Render consolidated summary
@ -413,6 +417,33 @@ class Installer {
} }
} }
/**
* Remove skill directories from _bmad/ after IDE installation.
* Skills are self-contained in IDE directories, so _bmad/ only needs
* module-level files (config.yaml, _config/, etc.).
* Also cleans up skill dirs left by older installer versions.
* @param {string} bmadDir - BMAD installation directory
*/
async _cleanupSkillDirs(bmadDir) {
const csv = require('csv-parse/sync');
const csvPath = path.join(bmadDir, '_config', 'skill-manifest.csv');
if (!(await fs.pathExists(csvPath))) return;
const csvContent = await fs.readFile(csvPath, 'utf8');
const records = csv.parse(csvContent, { columns: true, skip_empty_lines: true });
const bmadFolderName = path.basename(bmadDir);
const bmadPrefix = bmadFolderName + '/';
for (const record of records) {
if (!record.path) continue;
const relativePath = record.path.startsWith(bmadPrefix) ? record.path.slice(bmadPrefix.length) : record.path;
const sourceDir = path.dirname(path.join(bmadDir, relativePath));
if (await fs.pathExists(sourceDir)) {
await fs.remove(sourceDir);
}
}
}
/** /**
* Restore custom and modified files that were backed up before the update. * Restore custom and modified files that were backed up before the update.
* No-op for fresh installs (updateState is null). * No-op for fresh installs (updateState is null).