maestro-bundle 1.1.0 → 1.2.0
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/package.json +1 -1
- package/src/cli.mjs +95 -45
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -69,9 +69,9 @@ const EDITORS = {
|
|
|
69
69
|
},
|
|
70
70
|
cursor: {
|
|
71
71
|
name: "Cursor",
|
|
72
|
-
instructionsFile: null, // Cursor lê AGENTS.md
|
|
73
|
-
skillsDir:
|
|
74
|
-
rulesDir:
|
|
72
|
+
instructionsFile: null, // Cursor lê AGENTS.md na raiz
|
|
73
|
+
skillsDir: ".cursor/skills", // Skills como SKILL.md (mesmo formato do Claude)
|
|
74
|
+
rulesDir: null, // Não usar rules, usar skills
|
|
75
75
|
needsAgentsMd: true, // Cursor lê AGENTS.md na raiz
|
|
76
76
|
},
|
|
77
77
|
codex: {
|
|
@@ -116,8 +116,8 @@ function showHelp() {
|
|
|
116
116
|
}
|
|
117
117
|
console.log("");
|
|
118
118
|
console.log(chalk.dim(" Editores:"));
|
|
119
|
-
console.log(` ${chalk.yellow("claude".padEnd(12))} CLAUDE.md + .claude/skills
|
|
120
|
-
console.log(` ${chalk.yellow("cursor".padEnd(12))} AGENTS.md + .cursor/
|
|
119
|
+
console.log(` ${chalk.yellow("claude".padEnd(12))} CLAUDE.md + .claude/skills/<nome>/SKILL.md`);
|
|
120
|
+
console.log(` ${chalk.yellow("cursor".padEnd(12))} AGENTS.md + .cursor/skills/<nome>/SKILL.md`);
|
|
121
121
|
console.log(` ${chalk.yellow("codex".padEnd(12))} AGENTS.md (tudo em um arquivo)`);
|
|
122
122
|
console.log(` ${chalk.yellow("copilot".padEnd(12))} .github/copilot-instructions.md + .github/instructions/`);
|
|
123
123
|
console.log(` ${chalk.yellow("windsurf".padEnd(12))} .windsurfrules (tudo em um arquivo)`);
|
|
@@ -205,21 +205,7 @@ function installForEditor(editorKey, agentsMd, skills, targetDir) {
|
|
|
205
205
|
for (const skill of skills) {
|
|
206
206
|
const content = readFileSync(join(skill.dir, "SKILL.md"), "utf-8");
|
|
207
207
|
|
|
208
|
-
if (editorKey === "
|
|
209
|
-
// Cursor: .mdc com frontmatter (description + globs)
|
|
210
|
-
// Extrair frontmatter existente e converter
|
|
211
|
-
const parsed = parseFrontmatter(content);
|
|
212
|
-
const cursorContent = [
|
|
213
|
-
"---",
|
|
214
|
-
`description: "${parsed.description || skill.name}"`,
|
|
215
|
-
`alwaysApply: false`,
|
|
216
|
-
"---",
|
|
217
|
-
"",
|
|
218
|
-
parsed.body,
|
|
219
|
-
].join("\n");
|
|
220
|
-
writeFileSync(join(rulesPath, `${skill.name}.mdc`), cursorContent);
|
|
221
|
-
|
|
222
|
-
} else if (editorKey === "copilot") {
|
|
208
|
+
if (editorKey === "copilot") {
|
|
223
209
|
// Copilot: .instructions.md
|
|
224
210
|
writeFileSync(join(rulesPath, `${skill.name}.instructions.md`), content);
|
|
225
211
|
|
|
@@ -324,38 +310,97 @@ async function main() {
|
|
|
324
310
|
}
|
|
325
311
|
spinner2.succeed(`${skills.length} skills canônicas em skills/`);
|
|
326
312
|
|
|
327
|
-
// 3.
|
|
328
|
-
const spinner3 = ora("Instalando
|
|
329
|
-
const specSrc = join(bundleDir, ".spec");
|
|
330
|
-
ensureDir(join(targetDir, ".spec"));
|
|
331
|
-
copyDir(specSrc, join(targetDir, ".spec"));
|
|
332
|
-
spinner3.succeed(".spec/constitution.md instalado");
|
|
333
|
-
|
|
334
|
-
// 4. References
|
|
335
|
-
const spinner4 = ora("Instalando references").start();
|
|
313
|
+
// 3. References
|
|
314
|
+
const spinner3 = ora("Instalando references").start();
|
|
336
315
|
const refsSrc = join(bundleDir, "references");
|
|
337
316
|
ensureDir(join(targetDir, "references"));
|
|
338
317
|
if (existsSync(refsSrc)) {
|
|
339
318
|
copyDir(refsSrc, join(targetDir, "references"));
|
|
340
319
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
//
|
|
344
|
-
|
|
320
|
+
spinner3.succeed("references/ pronto");
|
|
321
|
+
|
|
322
|
+
// 4. GitHub Spec Kit — instalar CLI + inicializar no projeto
|
|
323
|
+
// Mapear editor para flag --ai do specify
|
|
324
|
+
const aiFlags = {
|
|
325
|
+
claude: "claude",
|
|
326
|
+
cursor: "cursor",
|
|
327
|
+
codex: "codex",
|
|
328
|
+
copilot: "copilot",
|
|
329
|
+
windsurf: "windsurf",
|
|
330
|
+
};
|
|
331
|
+
// Usar o primeiro editor como --ai (ou claude como default)
|
|
332
|
+
const primaryEditor = editorsToInstall[0];
|
|
333
|
+
const aiFlag = aiFlags[primaryEditor] || "claude";
|
|
334
|
+
|
|
335
|
+
// 4a. Instalar specify-cli se não tiver
|
|
336
|
+
const spinner4 = ora("Verificando GitHub Spec Kit (specify-cli)").start();
|
|
337
|
+
let specifyInstalled = false;
|
|
345
338
|
try {
|
|
346
339
|
execSync("specify --version", { stdio: "ignore" });
|
|
347
|
-
|
|
340
|
+
specifyInstalled = true;
|
|
341
|
+
spinner4.succeed("specify-cli já instalado");
|
|
348
342
|
} catch {
|
|
349
|
-
|
|
350
|
-
const
|
|
343
|
+
spinner4.info("specify-cli não encontrado");
|
|
344
|
+
const spinner4b = ora("Instalando specify-cli...").start();
|
|
351
345
|
try {
|
|
352
346
|
execSync("uv tool install specify-cli --from git+https://github.com/github/spec-kit.git", {
|
|
353
347
|
stdio: "ignore", timeout: 120000,
|
|
354
348
|
});
|
|
355
|
-
|
|
349
|
+
specifyInstalled = true;
|
|
350
|
+
spinner4b.succeed("specify-cli instalado");
|
|
356
351
|
} catch {
|
|
357
|
-
|
|
358
|
-
|
|
352
|
+
try {
|
|
353
|
+
execSync("pip install specify-cli", { stdio: "ignore", timeout: 60000 });
|
|
354
|
+
specifyInstalled = true;
|
|
355
|
+
spinner4b.succeed("specify-cli instalado via pip");
|
|
356
|
+
} catch {
|
|
357
|
+
spinner4b.warn("Não foi possível instalar. Instale manualmente:");
|
|
358
|
+
console.log(chalk.dim(" uv tool install specify-cli --from git+https://github.com/github/spec-kit.git"));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// 4b. Rodar specify init no projeto para criar .specify/ e registrar /speckit.* commands
|
|
364
|
+
if (specifyInstalled) {
|
|
365
|
+
const spinner4c = ora(`Inicializando Spec Kit no projeto (--ai ${aiFlag})`).start();
|
|
366
|
+
const specifyEnv = { ...process.env, PYTHONIOENCODING: "utf-8", PYTHONUTF8: "1" };
|
|
367
|
+
let specInitOk = false;
|
|
368
|
+
const initCmds = [
|
|
369
|
+
`specify init --here --ai ${aiFlag}`,
|
|
370
|
+
`specify init . --ai ${aiFlag}`,
|
|
371
|
+
`specify init --here --ai ${aiFlag} --no-git`,
|
|
372
|
+
];
|
|
373
|
+
for (const cmd of initCmds) {
|
|
374
|
+
try {
|
|
375
|
+
execSync(cmd, { stdio: "ignore", timeout: 30000, cwd: targetDir, env: specifyEnv });
|
|
376
|
+
specInitOk = true;
|
|
377
|
+
break;
|
|
378
|
+
} catch { /* try next */ }
|
|
379
|
+
}
|
|
380
|
+
if (specInitOk) {
|
|
381
|
+
spinner4c.succeed(`Spec Kit inicializado (/speckit.* commands disponíveis)`);
|
|
382
|
+
} else {
|
|
383
|
+
spinner4c.warn("Inicialize manualmente no terminal:");
|
|
384
|
+
console.log(chalk.dim(` cd ${targetDir}`));
|
|
385
|
+
console.log(chalk.dim(` specify init --here --ai ${aiFlag}`));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// 4c. Copiar constitution.md do bundle para dentro do .specify/memory/
|
|
389
|
+
const specifyMemoryDir = join(targetDir, ".specify", "memory");
|
|
390
|
+
const bundleConstitution = join(bundleDir, ".spec", "constitution.md");
|
|
391
|
+
if (existsSync(bundleConstitution)) {
|
|
392
|
+
ensureDir(specifyMemoryDir);
|
|
393
|
+
const constitutionDest = join(specifyMemoryDir, "constitution.md");
|
|
394
|
+
// Append os princípios do bundle ao constitution gerado pelo specify
|
|
395
|
+
if (existsSync(constitutionDest)) {
|
|
396
|
+
const existing = readFileSync(constitutionDest, "utf-8");
|
|
397
|
+
const bundleContent = readFileSync(bundleConstitution, "utf-8");
|
|
398
|
+
writeFileSync(constitutionDest, existing + "\n\n---\n\n" + bundleContent);
|
|
399
|
+
} else {
|
|
400
|
+
cpSync(bundleConstitution, constitutionDest);
|
|
401
|
+
}
|
|
402
|
+
const spinner4d = ora("Constitution do bundle integrado ao Spec Kit").start();
|
|
403
|
+
spinner4d.succeed("Constitution do bundle integrado ao Spec Kit");
|
|
359
404
|
}
|
|
360
405
|
}
|
|
361
406
|
|
|
@@ -373,7 +418,7 @@ async function main() {
|
|
|
373
418
|
console.log(` ${chalk.cyan(".claude/skills/")} (${skills.length} skills com SKILL.md)`);
|
|
374
419
|
} else if (editorKey === "cursor") {
|
|
375
420
|
console.log(` ${chalk.cyan("AGENTS.md")} (instruções gerais)`);
|
|
376
|
-
console.log(` ${chalk.cyan(".cursor/
|
|
421
|
+
console.log(` ${chalk.cyan(".cursor/skills/")} (${skills.length} skills com SKILL.md)`);
|
|
377
422
|
} else if (editorKey === "codex") {
|
|
378
423
|
console.log(` ${chalk.cyan("AGENTS.md")} (tudo em um arquivo)`);
|
|
379
424
|
} else if (editorKey === "copilot") {
|
|
@@ -384,12 +429,17 @@ async function main() {
|
|
|
384
429
|
}
|
|
385
430
|
}
|
|
386
431
|
console.log(` ${chalk.cyan("skills/")} (${skills.length} canônicas para Deep Agents)`);
|
|
387
|
-
console.log(` ${chalk.cyan(".
|
|
432
|
+
console.log(` ${chalk.cyan(".specify/")} (GitHub Spec Kit — /speckit.* commands)`);
|
|
433
|
+
console.log("");
|
|
434
|
+
console.log(" Comandos SDD disponíveis no editor:");
|
|
435
|
+
console.log(` ${chalk.cyan("/speckit.constitution")} — Definir princípios do projeto`);
|
|
436
|
+
console.log(` ${chalk.cyan("/speckit.specify")} — Especificar O QUE e POR QUÊ`);
|
|
437
|
+
console.log(` ${chalk.cyan("/speckit.plan")} — Planejar arquitetura e stack`);
|
|
438
|
+
console.log(` ${chalk.cyan("/speckit.tasks")} — Quebrar em tasks atômicas`);
|
|
439
|
+
console.log(` ${chalk.cyan("/speckit.implement")} — Executar as tasks`);
|
|
388
440
|
console.log("");
|
|
389
|
-
console.log("
|
|
390
|
-
console.log("
|
|
391
|
-
console.log(" 2. O agente já conhece os padrões");
|
|
392
|
-
console.log(` 3. Nova demanda? ${chalk.cyan("/speckit.specify")}`);
|
|
441
|
+
console.log(" Próximo passo:");
|
|
442
|
+
console.log(" Abra o projeto no editor AI e use " + chalk.cyan("/speckit.specify") + " para começar");
|
|
393
443
|
console.log("");
|
|
394
444
|
}
|
|
395
445
|
|