|
| 1 | +import { execSync } from 'child_process'; |
1 | 2 | import fs from 'fs'; |
2 | 3 | import path from 'path'; |
3 | 4 |
|
4 | 5 | import { |
| 6 | + BoilerplateSkill, |
5 | 7 | DEFAULT_TEMPLATE_REPO, |
6 | 8 | DEFAULT_TEMPLATE_TOOL_NAME, |
7 | 9 | inspectTemplate, |
@@ -275,6 +277,38 @@ interface InitContext { |
275 | 277 | createWorkspace?: boolean; |
276 | 278 | } |
277 | 279 |
|
| 280 | +function installSkills(skills: BoilerplateSkill[], cwd: string): void { |
| 281 | + const failed: string[] = []; |
| 282 | + |
| 283 | + for (const entry of skills) { |
| 284 | + const source = entry.source.includes('://') |
| 285 | + ? entry.source |
| 286 | + : `https://github.com/${entry.source}`; |
| 287 | + |
| 288 | + for (const skill of entry.skills) { |
| 289 | + const cmd = `npx --yes skills add ${source} --skill ${skill} --yes`; |
| 290 | + try { |
| 291 | + execSync(cmd, { |
| 292 | + cwd, |
| 293 | + stdio: ['pipe', 'inherit', 'inherit'], |
| 294 | + timeout: 120_000, |
| 295 | + }); |
| 296 | + } catch { |
| 297 | + failed.push(` npx skills add ${source} --skill ${skill}`); |
| 298 | + } |
| 299 | + } |
| 300 | + } |
| 301 | + |
| 302 | + if (failed.length > 0) { |
| 303 | + process.stdout.write('\n⚠️ Some skills could not be installed automatically.\n'); |
| 304 | + process.stdout.write('Run the following commands manually:\n\n'); |
| 305 | + for (const cmd of failed) { |
| 306 | + process.stdout.write(`${cmd}\n`); |
| 307 | + } |
| 308 | + process.stdout.write('\n'); |
| 309 | + } |
| 310 | +} |
| 311 | + |
278 | 312 | async function handleWorkspaceInit( |
279 | 313 | argv: Partial<Record<string, any>>, |
280 | 314 | prompter: Inquirerer, |
@@ -329,6 +363,19 @@ async function handleWorkspaceInit( |
329 | 363 | process.stdout.write('\n'); |
330 | 364 | } |
331 | 365 |
|
| 366 | + // Install skills declared in .boilerplate.json |
| 367 | + const templateInfo = inspectTemplate({ |
| 368 | + fromPath: ctx.fromPath, |
| 369 | + templateRepo: ctx.templateRepo, |
| 370 | + branch: ctx.branch, |
| 371 | + dir: ctx.dir, |
| 372 | + cwd: ctx.cwd, |
| 373 | + }); |
| 374 | + if (templateInfo.config?.skills?.length) { |
| 375 | + process.stdout.write('\n📦 Installing skills...\n\n'); |
| 376 | + installSkills(templateInfo.config.skills, targetPath); |
| 377 | + } |
| 378 | + |
332 | 379 | const relPath = path.relative(process.cwd(), targetPath); |
333 | 380 | process.stdout.write(`\n✨ Enjoy!\n\ncd ./${relPath}\n`); |
334 | 381 |
|
@@ -620,6 +667,20 @@ async function handleModuleInit( |
620 | 667 | process.stdout.write('\n'); |
621 | 668 | } |
622 | 669 |
|
| 670 | + // Install skills declared in .boilerplate.json |
| 671 | + const moduleTemplateInfo = inspectTemplate({ |
| 672 | + fromPath: ctx.fromPath, |
| 673 | + templateRepo: ctx.templateRepo, |
| 674 | + branch: ctx.branch, |
| 675 | + dir: ctx.dir, |
| 676 | + cwd: ctx.cwd, |
| 677 | + }); |
| 678 | + if (moduleTemplateInfo.config?.skills?.length) { |
| 679 | + const skillsCwd = project.workspacePath || modulePath; |
| 680 | + process.stdout.write('\n📦 Installing skills...\n\n'); |
| 681 | + installSkills(moduleTemplateInfo.config.skills, skillsCwd); |
| 682 | + } |
| 683 | + |
623 | 684 | const relPath = path.relative(process.cwd(), modulePath); |
624 | 685 | process.stdout.write(`\n✨ Enjoy!\n\ncd ./${relPath}\n`); |
625 | 686 |
|
|
0 commit comments