@nimbuslab/cli 0.11.0 → 0.13.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/dist/index.js CHANGED
@@ -150,7 +150,7 @@ var require_src = __commonJS((exports, module) => {
150
150
  var require_package = __commonJS((exports, module) => {
151
151
  module.exports = {
152
152
  name: "@nimbuslab/cli",
153
- version: "0.11.0",
153
+ version: "0.13.0",
154
154
  description: "CLI para criar projetos nimbuslab",
155
155
  type: "module",
156
156
  bin: {
@@ -192,7 +192,7 @@ var require_package = __commonJS((exports, module) => {
192
192
  });
193
193
 
194
194
  // src/index.ts
195
- var import_picocolors7 = __toESM(require_picocolors(), 1);
195
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
196
196
 
197
197
  // node_modules/@clack/core/dist/index.mjs
198
198
  var import_sisteransi = __toESM(require_src(), 1);
@@ -833,6 +833,29 @@ ${import_picocolors2.default.gray(d2)} ${t}
833
833
 
834
834
  `);
835
835
  };
836
+ var M2 = { message: (t = "", { symbol: n = import_picocolors2.default.gray(o) } = {}) => {
837
+ const r2 = [`${import_picocolors2.default.gray(o)}`];
838
+ if (t) {
839
+ const [i, ...s] = t.split(`
840
+ `);
841
+ r2.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
842
+ }
843
+ process.stdout.write(`${r2.join(`
844
+ `)}
845
+ `);
846
+ }, info: (t) => {
847
+ M2.message(t, { symbol: import_picocolors2.default.blue(q) });
848
+ }, success: (t) => {
849
+ M2.message(t, { symbol: import_picocolors2.default.green(D) });
850
+ }, step: (t) => {
851
+ M2.message(t, { symbol: import_picocolors2.default.green(C) });
852
+ }, warn: (t) => {
853
+ M2.message(t, { symbol: import_picocolors2.default.yellow(U) });
854
+ }, warning: (t) => {
855
+ M2.warn(t);
856
+ }, error: (t) => {
857
+ M2.message(t, { symbol: import_picocolors2.default.red(K2) });
858
+ } };
836
859
  var J2 = `${import_picocolors2.default.gray(o)} `;
837
860
  var Y2 = ({ indicator: t = "dots" } = {}) => {
838
861
  const n = V2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], r2 = V2 ? 80 : 120, i = process.env.CI === "true";
@@ -2328,8 +2351,123 @@ function printUpgradePlan(name, plan) {
2328
2351
  console.log();
2329
2352
  }
2330
2353
 
2331
- // src/commands/lola.ts
2354
+ // src/commands/update.ts
2332
2355
  var import_picocolors6 = __toESM(require_picocolors(), 1);
2356
+ import { execSync, spawnSync } from "child_process";
2357
+ var PACKAGE_NAME = "@nimbuslab/cli";
2358
+ async function getAvailableVersions() {
2359
+ try {
2360
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`);
2361
+ if (!res.ok)
2362
+ return [];
2363
+ const data = await res.json();
2364
+ return Object.keys(data.versions || {}).reverse();
2365
+ } catch {
2366
+ return [];
2367
+ }
2368
+ }
2369
+ async function getLatestVersion() {
2370
+ try {
2371
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`);
2372
+ if (!res.ok)
2373
+ return null;
2374
+ const data = await res.json();
2375
+ return data.version || null;
2376
+ } catch {
2377
+ return null;
2378
+ }
2379
+ }
2380
+ function getCurrentVersion() {
2381
+ try {
2382
+ const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
2383
+ encoding: "utf-8",
2384
+ shell: true
2385
+ });
2386
+ if (result.stdout) {
2387
+ const data = JSON.parse(result.stdout);
2388
+ return data.dependencies?.[PACKAGE_NAME]?.version || "unknown";
2389
+ }
2390
+ } catch {}
2391
+ return "unknown";
2392
+ }
2393
+ async function update(args) {
2394
+ const flag = args[0];
2395
+ if (flag === "--list" || flag === "-l") {
2396
+ Ie(import_picocolors6.default.cyan("Vers\xF5es dispon\xEDveis"));
2397
+ const spinner2 = Y2();
2398
+ spinner2.start("Buscando vers\xF5es...");
2399
+ const versions = await getAvailableVersions();
2400
+ spinner2.stop("Vers\xF5es encontradas");
2401
+ if (versions.length === 0) {
2402
+ M2.error("N\xE3o foi poss\xEDvel buscar as vers\xF5es");
2403
+ return;
2404
+ }
2405
+ const current = getCurrentVersion();
2406
+ console.log();
2407
+ console.log(import_picocolors6.default.bold("\xDAltimas 10 vers\xF5es:"));
2408
+ versions.slice(0, 10).forEach((v2, i) => {
2409
+ const isCurrent = v2 === current;
2410
+ const prefix = isCurrent ? import_picocolors6.default.green("\u2192 ") : " ";
2411
+ const suffix = isCurrent ? import_picocolors6.default.dim(" (instalada)") : "";
2412
+ const isLatest = i === 0 ? import_picocolors6.default.yellow(" (latest)") : "";
2413
+ console.log(`${prefix}${v2}${suffix}${isLatest}`);
2414
+ });
2415
+ console.log();
2416
+ console.log(import_picocolors6.default.dim(`Total: ${versions.length} vers\xF5es`));
2417
+ console.log(import_picocolors6.default.dim(`Instalar vers\xE3o espec\xEDfica: nimbus update <vers\xE3o>`));
2418
+ return;
2419
+ }
2420
+ const targetVersion = flag || "latest";
2421
+ const isSpecificVersion = flag && flag !== "latest";
2422
+ Ie(import_picocolors6.default.cyan(`Atualizando ${PACKAGE_NAME}`));
2423
+ const spinner = Y2();
2424
+ spinner.start("Verificando vers\xE3o atual...");
2425
+ const currentVersion = getCurrentVersion();
2426
+ spinner.stop(`Vers\xE3o atual: ${currentVersion}`);
2427
+ if (!isSpecificVersion) {
2428
+ spinner.start("Verificando \xFAltima vers\xE3o...");
2429
+ const latest = await getLatestVersion();
2430
+ spinner.stop(`\xDAltima vers\xE3o: ${latest || "desconhecida"}`);
2431
+ if (latest && latest === currentVersion) {
2432
+ M2.success("Voc\xEA j\xE1 est\xE1 na \xFAltima vers\xE3o!");
2433
+ return;
2434
+ }
2435
+ }
2436
+ const versionText = isSpecificVersion ? targetVersion : "latest";
2437
+ const confirmUpdate = await ye({
2438
+ message: `Atualizar para ${versionText}?`,
2439
+ initialValue: true
2440
+ });
2441
+ if (pD(confirmUpdate) || !confirmUpdate) {
2442
+ xe("Atualiza\xE7\xE3o cancelada");
2443
+ return;
2444
+ }
2445
+ spinner.start("Atualizando...");
2446
+ try {
2447
+ const packageSpec = isSpecificVersion ? `${PACKAGE_NAME}@${targetVersion}` : PACKAGE_NAME;
2448
+ execSync(`npm install -g ${packageSpec}`, {
2449
+ stdio: "pipe",
2450
+ encoding: "utf-8"
2451
+ });
2452
+ spinner.stop("Atualiza\xE7\xE3o conclu\xEDda!");
2453
+ const newVersion = getCurrentVersion();
2454
+ M2.success(`${PACKAGE_NAME} atualizado: ${currentVersion} \u2192 ${newVersion}`);
2455
+ Se(import_picocolors6.default.green("Pronto!"));
2456
+ } catch (error) {
2457
+ spinner.stop("Erro na atualiza\xE7\xE3o");
2458
+ const err = error;
2459
+ M2.error("Falha ao atualizar");
2460
+ if (err.stderr) {
2461
+ console.log(import_picocolors6.default.dim(err.stderr));
2462
+ }
2463
+ console.log();
2464
+ console.log(import_picocolors6.default.yellow("Tente manualmente:"));
2465
+ console.log(import_picocolors6.default.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
2466
+ }
2467
+ }
2468
+
2469
+ // src/commands/lola.ts
2470
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
2333
2471
  import { existsSync as existsSync2 } from "fs";
2334
2472
  import { join as join3 } from "path";
2335
2473
  var LOLA_DIR = join3(process.env.HOME || "~", ".lola");
@@ -2337,40 +2475,40 @@ var LOLA_REPO = "git@github.com:nimbuslab/lola.git";
2337
2475
  var USER_MEMORY = join3(process.env.HOME || "~", ".claude", "USER_MEMORY.md");
2338
2476
  async function installLola() {
2339
2477
  console.log();
2340
- console.log(import_picocolors6.default.cyan(" Lola - Code Agent da nimbuslab"));
2341
- console.log(import_picocolors6.default.dim(" ==============================="));
2478
+ console.log(import_picocolors7.default.cyan(" Lola - Code Agent da nimbuslab"));
2479
+ console.log(import_picocolors7.default.dim(" ==============================="));
2342
2480
  console.log();
2343
2481
  const isUpdate = existsSync2(LOLA_DIR);
2344
2482
  if (isUpdate) {
2345
- console.log(import_picocolors6.default.dim(` Lola ja instalada em ${LOLA_DIR}`));
2346
- console.log(import_picocolors6.default.cyan(" Atualizando..."));
2483
+ console.log(import_picocolors7.default.dim(` Lola ja instalada em ${LOLA_DIR}`));
2484
+ console.log(import_picocolors7.default.cyan(" Atualizando..."));
2347
2485
  const result = Bun.spawnSync(["git", "pull", "--quiet"], {
2348
2486
  cwd: LOLA_DIR,
2349
2487
  stdout: "inherit",
2350
2488
  stderr: "inherit"
2351
2489
  });
2352
2490
  if (result.exitCode !== 0) {
2353
- console.log(import_picocolors6.default.red(" Erro ao atualizar Lola"));
2491
+ console.log(import_picocolors7.default.red(" Erro ao atualizar Lola"));
2354
2492
  process.exit(1);
2355
2493
  }
2356
- console.log(import_picocolors6.default.green(" Atualizado!"));
2494
+ console.log(import_picocolors7.default.green(" Atualizado!"));
2357
2495
  } else {
2358
- console.log(import_picocolors6.default.cyan(` Instalando Lola em ${LOLA_DIR}...`));
2496
+ console.log(import_picocolors7.default.cyan(` Instalando Lola em ${LOLA_DIR}...`));
2359
2497
  const result = Bun.spawnSync(["git", "clone", "--quiet", LOLA_REPO, LOLA_DIR], {
2360
2498
  stdout: "inherit",
2361
2499
  stderr: "inherit"
2362
2500
  });
2363
2501
  if (result.exitCode !== 0) {
2364
- console.log(import_picocolors6.default.red(" Erro ao clonar repositorio"));
2365
- console.log(import_picocolors6.default.dim(" Verifique se tem acesso ao repo nimbuslab/lola"));
2502
+ console.log(import_picocolors7.default.red(" Erro ao clonar repositorio"));
2503
+ console.log(import_picocolors7.default.dim(" Verifique se tem acesso ao repo nimbuslab/lola"));
2366
2504
  process.exit(1);
2367
2505
  }
2368
- console.log(import_picocolors6.default.green(" Instalado!"));
2506
+ console.log(import_picocolors7.default.green(" Instalado!"));
2369
2507
  }
2370
2508
  const claudeDir = join3(process.env.HOME || "~", ".claude");
2371
2509
  if (!existsSync2(USER_MEMORY)) {
2372
2510
  console.log();
2373
- console.log(import_picocolors6.default.cyan(" Criando USER_MEMORY.md..."));
2511
+ console.log(import_picocolors7.default.cyan(" Criando USER_MEMORY.md..."));
2374
2512
  await Bun.$`mkdir -p ${claudeDir}`;
2375
2513
  const content = `# User Memory
2376
2514
 
@@ -2393,29 +2531,29 @@ lola_profile: millennial
2393
2531
  ---
2394
2532
  `;
2395
2533
  await Bun.write(USER_MEMORY, content);
2396
- console.log(import_picocolors6.default.green(" USER_MEMORY.md criado!"));
2534
+ console.log(import_picocolors7.default.green(" USER_MEMORY.md criado!"));
2397
2535
  }
2398
2536
  console.log();
2399
- console.log(import_picocolors6.default.green(" Instalacao concluida!"));
2537
+ console.log(import_picocolors7.default.green(" Instalacao concluida!"));
2400
2538
  console.log();
2401
- console.log(import_picocolors6.default.bold(" Para usar a Lola:"));
2402
- console.log(import_picocolors6.default.dim(" lola ") + import_picocolors6.default.white("# Iniciar sessao"));
2403
- console.log(import_picocolors6.default.dim(' lola suggest "x" ') + import_picocolors6.default.white("# Sugerir melhoria"));
2539
+ console.log(import_picocolors7.default.bold(" Para usar a Lola:"));
2540
+ console.log(import_picocolors7.default.dim(" lola ") + import_picocolors7.default.white("# Iniciar sessao"));
2541
+ console.log(import_picocolors7.default.dim(' lola suggest "x" ') + import_picocolors7.default.white("# Sugerir melhoria"));
2404
2542
  console.log();
2405
- console.log(import_picocolors6.default.bold(" Para mudar perfil, edite ~/.claude/USER_MEMORY.md:"));
2406
- console.log(import_picocolors6.default.dim(" lola_profile: millennial|genz|profissional|nerd|chill"));
2543
+ console.log(import_picocolors7.default.bold(" Para mudar perfil, edite ~/.claude/USER_MEMORY.md:"));
2544
+ console.log(import_picocolors7.default.dim(" lola_profile: millennial|genz|profissional|nerd|chill"));
2407
2545
  console.log();
2408
2546
  }
2409
2547
  async function suggestImprovement(message) {
2410
2548
  if (!message) {
2411
- console.log(import_picocolors6.default.red(" Erro: forne\xE7a uma mensagem"));
2412
- console.log(import_picocolors6.default.dim(' Uso: nimbus lola suggest "sua sugestao aqui"'));
2549
+ console.log(import_picocolors7.default.red(" Erro: forne\xE7a uma mensagem"));
2550
+ console.log(import_picocolors7.default.dim(' Uso: nimbus lola suggest "sua sugestao aqui"'));
2413
2551
  process.exit(1);
2414
2552
  }
2415
2553
  const ghCheck = Bun.spawnSync(["which", "gh"]);
2416
2554
  if (ghCheck.exitCode !== 0) {
2417
- console.log(import_picocolors6.default.red(" Erro: GitHub CLI (gh) nao encontrado"));
2418
- console.log(import_picocolors6.default.dim(" Instale: https://cli.github.com"));
2555
+ console.log(import_picocolors7.default.red(" Erro: GitHub CLI (gh) nao encontrado"));
2556
+ console.log(import_picocolors7.default.dim(" Instale: https://cli.github.com"));
2419
2557
  process.exit(1);
2420
2558
  }
2421
2559
  const authCheck = Bun.spawnSync(["gh", "auth", "status"], {
@@ -2423,8 +2561,8 @@ async function suggestImprovement(message) {
2423
2561
  stderr: "pipe"
2424
2562
  });
2425
2563
  if (authCheck.exitCode !== 0) {
2426
- console.log(import_picocolors6.default.red(" Erro: GitHub CLI nao autenticado"));
2427
- console.log(import_picocolors6.default.dim(" Execute: gh auth login"));
2564
+ console.log(import_picocolors7.default.red(" Erro: GitHub CLI nao autenticado"));
2565
+ console.log(import_picocolors7.default.dim(" Execute: gh auth login"));
2428
2566
  process.exit(1);
2429
2567
  }
2430
2568
  const gitUser = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" });
@@ -2432,7 +2570,7 @@ async function suggestImprovement(message) {
2432
2570
  const userName = gitUser.stdout.toString().trim() || "Dev";
2433
2571
  const userEmail = gitEmail.stdout.toString().trim() || "";
2434
2572
  console.log();
2435
- console.log(import_picocolors6.default.cyan(" Criando sugestao..."));
2573
+ console.log(import_picocolors7.default.cyan(" Criando sugestao..."));
2436
2574
  const date = new Date().toISOString().split("T")[0];
2437
2575
  const body = `## Sugestao
2438
2576
 
@@ -2464,11 +2602,11 @@ ${message}
2464
2602
  stderr: "inherit"
2465
2603
  });
2466
2604
  if (result.exitCode !== 0) {
2467
- console.log(import_picocolors6.default.red(" Erro ao criar issue"));
2605
+ console.log(import_picocolors7.default.red(" Erro ao criar issue"));
2468
2606
  process.exit(1);
2469
2607
  }
2470
2608
  console.log();
2471
- console.log(import_picocolors6.default.green(" Sugestao enviada! Hugo vai revisar."));
2609
+ console.log(import_picocolors7.default.green(" Sugestao enviada! Hugo vai revisar."));
2472
2610
  console.log();
2473
2611
  }
2474
2612
  var PROFILES = {
@@ -2500,18 +2638,18 @@ var PROFILES = {
2500
2638
  };
2501
2639
  async function onboardDev() {
2502
2640
  console.log();
2503
- console.log(import_picocolors6.default.cyan(" Lola - Onboarding"));
2504
- console.log(import_picocolors6.default.dim(" ================="));
2641
+ console.log(import_picocolors7.default.cyan(" Lola - Onboarding"));
2642
+ console.log(import_picocolors7.default.dim(" ================="));
2505
2643
  console.log();
2506
2644
  if (!existsSync2(LOLA_DIR)) {
2507
- console.log(import_picocolors6.default.yellow(" Lola nao instalada. Instalando primeiro..."));
2645
+ console.log(import_picocolors7.default.yellow(" Lola nao instalada. Instalando primeiro..."));
2508
2646
  console.log();
2509
2647
  await installLola();
2510
2648
  console.log();
2511
2649
  }
2512
2650
  const gitUser = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" });
2513
2651
  const defaultName = gitUser.stdout.toString().trim() || "";
2514
- Ie(import_picocolors6.default.bgCyan(import_picocolors6.default.black(" Bem-vindo a nimbuslab! ")));
2652
+ Ie(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" Bem-vindo a nimbuslab! ")));
2515
2653
  const devName = await he({
2516
2654
  message: "Qual seu nome?",
2517
2655
  placeholder: "Seu nome",
@@ -2565,18 +2703,165 @@ lola_profile: ${profile}
2565
2703
  ---
2566
2704
  `;
2567
2705
  await Bun.write(USER_MEMORY, content);
2568
- Se(import_picocolors6.default.green("Onboarding concluido!"));
2706
+ Se(import_picocolors7.default.green("Onboarding concluido!"));
2569
2707
  console.log();
2570
- console.log(import_picocolors6.default.bold(" Resumo:"));
2571
- console.log(import_picocolors6.default.dim(" Nome: ") + import_picocolors6.default.white(devName));
2572
- console.log(import_picocolors6.default.dim(" Perfil: ") + import_picocolors6.default.white(PROFILES[profile].label));
2708
+ console.log(import_picocolors7.default.bold(" Resumo:"));
2709
+ console.log(import_picocolors7.default.dim(" Nome: ") + import_picocolors7.default.white(devName));
2710
+ console.log(import_picocolors7.default.dim(" Perfil: ") + import_picocolors7.default.white(PROFILES[profile].label));
2573
2711
  console.log();
2574
- console.log(import_picocolors6.default.bold(" Proximos passos:"));
2575
- console.log(import_picocolors6.default.dim(" 1. ") + import_picocolors6.default.white("lola") + import_picocolors6.default.dim(" - Iniciar sessao com a Lola"));
2576
- console.log(import_picocolors6.default.dim(" 2. ") + import_picocolors6.default.white("nimbus create meu-projeto --fast") + import_picocolors6.default.dim(" - Criar projeto"));
2577
- console.log(import_picocolors6.default.dim(" 3. ") + import_picocolors6.default.white('lola suggest "sua ideia"') + import_picocolors6.default.dim(" - Sugerir melhoria"));
2712
+ console.log(import_picocolors7.default.bold(" Proximos passos:"));
2713
+ console.log(import_picocolors7.default.dim(" 1. ") + import_picocolors7.default.white("lola") + import_picocolors7.default.dim(" - Iniciar sessao com a Lola"));
2714
+ console.log(import_picocolors7.default.dim(" 2. ") + import_picocolors7.default.white("nimbus create meu-projeto --fast") + import_picocolors7.default.dim(" - Criar projeto"));
2715
+ console.log(import_picocolors7.default.dim(" 3. ") + import_picocolors7.default.white('lola suggest "sua ideia"') + import_picocolors7.default.dim(" - Sugerir melhoria"));
2578
2716
  console.log();
2579
- console.log(import_picocolors6.default.dim(" Docs: ~/.lola/README.md"));
2717
+ console.log(import_picocolors7.default.dim(" Docs: ~/.lola/README.md"));
2718
+ console.log();
2719
+ }
2720
+ var QUIZ_QUESTIONS = [
2721
+ {
2722
+ question: "Quais sao os 4 valores da nimbuslab?",
2723
+ options: [
2724
+ { value: "a", label: "Velocidade, Qualidade, Preco, Entrega" },
2725
+ { value: "b", label: "Cocriacao, Inovacao, Evolucao, Humanizacao" },
2726
+ { value: "c", label: "Codigo, Design, Marketing, Vendas" },
2727
+ { value: "d", label: "Agil, Lean, Scrum, Kanban" }
2728
+ ],
2729
+ correct: "b",
2730
+ explanation: "Cocriacao (construimos junto), Inovacao (buscamos o novo), Evolucao (aprendizado continuo), Humanizacao (tecnologia a servico das pessoas)."
2731
+ },
2732
+ {
2733
+ question: "Quais sao os 4 pilares da filosofia fast?",
2734
+ options: [
2735
+ { value: "a", label: "Analise, Planejamento, Execucao, Documentacao" },
2736
+ { value: "b", label: "Design, Codigo, Teste, Deploy" },
2737
+ { value: "c", label: "Briefing, Prototipo, Desenvolvimento, Lancamento" },
2738
+ { value: "d", label: "Discovery, Definition, Development, Delivery" }
2739
+ ],
2740
+ correct: "a",
2741
+ explanation: "Filosofia fast: 1. Analise (entender), 2. Planejamento (definir caminho), 3. Execucao (implementar), 4. Documentacao (registrar)."
2742
+ },
2743
+ {
2744
+ question: "Qual package manager a nimbuslab usa como padrao?",
2745
+ options: [
2746
+ { value: "a", label: "npm" },
2747
+ { value: "b", label: "yarn" },
2748
+ { value: "c", label: "pnpm" },
2749
+ { value: "d", label: "bun" }
2750
+ ],
2751
+ correct: "d",
2752
+ explanation: "Bun e o package manager padrao. Mais rapido e com menos dependencias."
2753
+ },
2754
+ {
2755
+ question: "Qual o estilo padrao do shadcn/ui na nimbuslab?",
2756
+ options: [
2757
+ { value: "a", label: "new-york" },
2758
+ { value: "b", label: "default" },
2759
+ { value: "c", label: "minimal" },
2760
+ { value: "d", label: "custom" }
2761
+ ],
2762
+ correct: "b",
2763
+ explanation: "Usamos o estilo 'default' do shadcn/ui. Nunca 'new-york'."
2764
+ },
2765
+ {
2766
+ question: "Em projetos externos (stealth mode), a Lola deve:",
2767
+ options: [
2768
+ { value: "a", label: "Sempre mencionar a nimbuslab nos commits" },
2769
+ { value: "b", label: "Usar assinatura 'Co-authored-by: Lola'" },
2770
+ { value: "c", label: "Nunca mencionar nimbuslab, Lola ou IA" },
2771
+ { value: "d", label: "Adicionar badge da nimbuslab no README" }
2772
+ ],
2773
+ correct: "c",
2774
+ explanation: "Stealth mode: commits sem mencao a nimbuslab/Lola/IA. O cliente nao precisa saber dos bastidores."
2775
+ },
2776
+ {
2777
+ question: "Qual a versao minima do Next.js usada na stack nimbuslab?",
2778
+ options: [
2779
+ { value: "a", label: "Next.js 13" },
2780
+ { value: "b", label: "Next.js 14" },
2781
+ { value: "c", label: "Next.js 15" },
2782
+ { value: "d", label: "Next.js 16" }
2783
+ ],
2784
+ correct: "d",
2785
+ explanation: "Stack atual: Next.js 16+ com App Router e Turbopack."
2786
+ },
2787
+ {
2788
+ question: "Quem pode aprovar e mergear mudancas no repositorio da Lola?",
2789
+ options: [
2790
+ { value: "a", label: "Qualquer dev da nimbuslab" },
2791
+ { value: "b", label: "Apenas o Hugo" },
2792
+ { value: "c", label: "Qualquer pessoa com acesso ao repo" },
2793
+ { value: "d", label: "A propria Lola via automacao" }
2794
+ ],
2795
+ correct: "b",
2796
+ explanation: "Apenas o Hugo pode aprovar e mergear. Devs sugerem via 'lola suggest', Hugo revisa."
2797
+ },
2798
+ {
2799
+ question: "Em commits da nimbuslab, qual o idioma correto?",
2800
+ options: [
2801
+ { value: "a", label: "Ingles" },
2802
+ { value: "b", label: "Portugues (BR)" },
2803
+ { value: "c", label: "Depende do projeto" },
2804
+ { value: "d", label: "Spanglish" }
2805
+ ],
2806
+ correct: "b",
2807
+ explanation: "Commits e PRs em Portugues (BR). Codigo e comentarios em Ingles."
2808
+ }
2809
+ ];
2810
+ async function runQuiz() {
2811
+ console.log();
2812
+ console.log(import_picocolors7.default.cyan(" Quiz nimbuslab"));
2813
+ console.log(import_picocolors7.default.dim(" =============="));
2814
+ console.log();
2815
+ console.log(import_picocolors7.default.dim(" Teste seus conhecimentos sobre a nimbuslab!"));
2816
+ console.log(import_picocolors7.default.dim(" 8 perguntas sobre valores, filosofia e stack."));
2817
+ console.log();
2818
+ let score = 0;
2819
+ const results = [];
2820
+ for (let i = 0;i < QUIZ_QUESTIONS.length; i++) {
2821
+ const q2 = QUIZ_QUESTIONS[i];
2822
+ const answer = await ve({
2823
+ message: `${i + 1}. ${q2.question}`,
2824
+ options: q2.options
2825
+ });
2826
+ if (pD(answer)) {
2827
+ xe("Quiz cancelado");
2828
+ process.exit(0);
2829
+ }
2830
+ const isCorrect = answer === q2.correct;
2831
+ if (isCorrect) {
2832
+ score++;
2833
+ console.log(import_picocolors7.default.green(" Correto!"));
2834
+ } else {
2835
+ console.log(import_picocolors7.default.red(" Incorreto."));
2836
+ }
2837
+ console.log(import_picocolors7.default.dim(` ${q2.explanation}`));
2838
+ console.log();
2839
+ results.push({
2840
+ question: q2.question,
2841
+ correct: isCorrect,
2842
+ explanation: q2.explanation
2843
+ });
2844
+ }
2845
+ const percentage = Math.round(score / QUIZ_QUESTIONS.length * 100);
2846
+ const passed = percentage >= 75;
2847
+ console.log(import_picocolors7.default.bold(" Resultado:"));
2848
+ console.log();
2849
+ if (passed) {
2850
+ console.log(import_picocolors7.default.green(` ${score}/${QUIZ_QUESTIONS.length} (${percentage}%) - Aprovado!`));
2851
+ console.log();
2852
+ if (percentage === 100) {
2853
+ console.log(import_picocolors7.default.cyan(" Perfeito! Voce conhece bem a nimbuslab."));
2854
+ } else {
2855
+ console.log(import_picocolors7.default.cyan(" Muito bem! Voce esta pronto para trabalhar."));
2856
+ }
2857
+ } else {
2858
+ console.log(import_picocolors7.default.yellow(` ${score}/${QUIZ_QUESTIONS.length} (${percentage}%) - Precisa revisar`));
2859
+ console.log();
2860
+ console.log(import_picocolors7.default.dim(" Revise os conceitos em:"));
2861
+ console.log(import_picocolors7.default.dim(" ~/.lola/core/values.md"));
2862
+ console.log(import_picocolors7.default.dim(" ~/.lola/core/philosophy.md"));
2863
+ console.log(import_picocolors7.default.dim(" ~/.lola/modules/stack.md"));
2864
+ }
2580
2865
  console.log();
2581
2866
  }
2582
2867
  async function lola(args) {
@@ -2585,39 +2870,43 @@ async function lola(args) {
2585
2870
  await installLola();
2586
2871
  } else if (subcommand === "onboard") {
2587
2872
  await onboardDev();
2873
+ } else if (subcommand === "quiz") {
2874
+ await runQuiz();
2588
2875
  } else if (subcommand === "suggest") {
2589
2876
  const message = args.slice(1).join(" ");
2590
2877
  await suggestImprovement(message);
2591
2878
  } else if (subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
2592
2879
  showLolaHelp();
2593
2880
  } else {
2594
- console.log(import_picocolors6.default.red(` Subcomando desconhecido: ${subcommand}`));
2881
+ console.log(import_picocolors7.default.red(` Subcomando desconhecido: ${subcommand}`));
2595
2882
  showLolaHelp();
2596
2883
  process.exit(1);
2597
2884
  }
2598
2885
  }
2599
2886
  function showLolaHelp() {
2600
2887
  console.log();
2601
- console.log(import_picocolors6.default.bold(" Lola - Code Agent da nimbuslab"));
2888
+ console.log(import_picocolors7.default.bold(" Lola - Code Agent da nimbuslab"));
2602
2889
  console.log();
2603
- console.log(import_picocolors6.default.bold(" Uso:") + " nimbus lola [subcomando]");
2890
+ console.log(import_picocolors7.default.bold(" Uso:") + " nimbus lola [subcomando]");
2604
2891
  console.log();
2605
- console.log(import_picocolors6.default.bold(" Subcomandos:"));
2606
- console.log(import_picocolors6.default.dim(" install ") + import_picocolors6.default.white("Instalar/atualizar Lola"));
2607
- console.log(import_picocolors6.default.dim(" sync ") + import_picocolors6.default.white("Alias para install"));
2608
- console.log(import_picocolors6.default.dim(" onboard ") + import_picocolors6.default.white("Configurar perfil (novos devs)"));
2609
- console.log(import_picocolors6.default.dim(' suggest "msg" ') + import_picocolors6.default.white("Sugerir melhoria (cria issue)"));
2610
- console.log(import_picocolors6.default.dim(" help ") + import_picocolors6.default.white("Mostrar esta ajuda"));
2892
+ console.log(import_picocolors7.default.bold(" Subcomandos:"));
2893
+ console.log(import_picocolors7.default.dim(" install ") + import_picocolors7.default.white("Instalar/atualizar Lola"));
2894
+ console.log(import_picocolors7.default.dim(" sync ") + import_picocolors7.default.white("Alias para install"));
2895
+ console.log(import_picocolors7.default.dim(" onboard ") + import_picocolors7.default.white("Configurar perfil (novos devs)"));
2896
+ console.log(import_picocolors7.default.dim(" quiz ") + import_picocolors7.default.white("Quiz sobre a nimbuslab"));
2897
+ console.log(import_picocolors7.default.dim(' suggest "msg" ') + import_picocolors7.default.white("Sugerir melhoria (cria issue)"));
2898
+ console.log(import_picocolors7.default.dim(" help ") + import_picocolors7.default.white("Mostrar esta ajuda"));
2611
2899
  console.log();
2612
- console.log(import_picocolors6.default.bold(" Exemplos:"));
2613
- console.log(import_picocolors6.default.dim(" $ nimbus lola install"));
2614
- console.log(import_picocolors6.default.dim(" $ nimbus lola onboard"));
2615
- console.log(import_picocolors6.default.dim(' $ nimbus lola suggest "adicionar suporte a X"'));
2900
+ console.log(import_picocolors7.default.bold(" Exemplos:"));
2901
+ console.log(import_picocolors7.default.dim(" $ nimbus lola install"));
2902
+ console.log(import_picocolors7.default.dim(" $ nimbus lola onboard"));
2903
+ console.log(import_picocolors7.default.dim(" $ nimbus lola quiz"));
2904
+ console.log(import_picocolors7.default.dim(' $ nimbus lola suggest "adicionar suporte a X"'));
2616
2905
  console.log();
2617
2906
  }
2618
2907
 
2619
2908
  // src/index.ts
2620
- var PACKAGE_NAME = "@nimbuslab/cli";
2909
+ var PACKAGE_NAME2 = "@nimbuslab/cli";
2621
2910
  var pkg = await Promise.resolve().then(() => __toESM(require_package(), 1));
2622
2911
  var CURRENT_VERSION = pkg.version;
2623
2912
  var LOGO = `
@@ -2631,7 +2920,7 @@ async function checkForUpdates() {
2631
2920
  try {
2632
2921
  const controller = new AbortController;
2633
2922
  const timeout = setTimeout(() => controller.abort(), 3000);
2634
- const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
2923
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME2}/latest`, {
2635
2924
  signal: controller.signal
2636
2925
  });
2637
2926
  clearTimeout(timeout);
@@ -2650,23 +2939,23 @@ async function checkForUpdates() {
2650
2939
  function showUpdateNotice(latestVersion) {
2651
2940
  const current = CURRENT_VERSION;
2652
2941
  const latest = latestVersion;
2653
- const command = `bun add -g ${PACKAGE_NAME}`;
2654
- const line1 = ` New version available: ${current} \u2192 ${latest}`;
2655
- const line2 = ` Update with: ${command}`;
2942
+ const command = "nimbus update";
2943
+ const line1 = ` Nova vers\xE3o dispon\xEDvel: ${current} \u2192 ${latest}`;
2944
+ const line2 = ` Atualize com: ${command}`;
2656
2945
  const maxLen = Math.max(line1.length, line2.length);
2657
2946
  const border = "\u2500".repeat(maxLen + 2);
2658
- console.log(import_picocolors7.default.yellow(` \u250C${border}\u2510`));
2659
- console.log(import_picocolors7.default.yellow(` \u2502`) + import_picocolors7.default.white(line1.padEnd(maxLen + 1)) + import_picocolors7.default.yellow(`\u2502`));
2660
- console.log(import_picocolors7.default.yellow(` \u2502`) + import_picocolors7.default.cyan(line2.padEnd(maxLen + 1)) + import_picocolors7.default.yellow(`\u2502`));
2661
- console.log(import_picocolors7.default.yellow(` \u2514${border}\u2518`));
2947
+ console.log(import_picocolors8.default.yellow(` \u250C${border}\u2510`));
2948
+ console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.white(line1.padEnd(maxLen + 1)) + import_picocolors8.default.yellow(`\u2502`));
2949
+ console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.cyan(line2.padEnd(maxLen + 1)) + import_picocolors8.default.yellow(`\u2502`));
2950
+ console.log(import_picocolors8.default.yellow(` \u2514${border}\u2518`));
2662
2951
  console.log();
2663
2952
  }
2664
2953
  async function main() {
2665
2954
  const args = process.argv.slice(2);
2666
2955
  const command = args[0];
2667
- console.log(import_picocolors7.default.cyan(LOGO));
2668
- console.log(import_picocolors7.default.white(" nimbuslab CLI"));
2669
- console.log(import_picocolors7.default.dim(" Create awesome projects"));
2956
+ console.log(import_picocolors8.default.cyan(LOGO));
2957
+ console.log(import_picocolors8.default.white(" nimbuslab CLI"));
2958
+ console.log(import_picocolors8.default.dim(" Create awesome projects"));
2670
2959
  console.log();
2671
2960
  const latestVersion = await checkForUpdates();
2672
2961
  if (latestVersion) {
@@ -2678,6 +2967,8 @@ async function main() {
2678
2967
  await analyze(args.slice(1));
2679
2968
  } else if (command === "upgrade") {
2680
2969
  await upgrade(args.slice(1));
2970
+ } else if (command === "update") {
2971
+ await update(args.slice(1));
2681
2972
  } else if (command === "lola") {
2682
2973
  await lola(args.slice(1));
2683
2974
  } else if (command === "help" || command === "--help" || command === "-h") {
@@ -2685,58 +2976,64 @@ async function main() {
2685
2976
  } else if (command === "version" || command === "--version" || command === "-v") {
2686
2977
  showVersion();
2687
2978
  } else {
2688
- console.log(import_picocolors7.default.red(`Unknown command: ${command}`));
2979
+ console.log(import_picocolors8.default.red(`Comando desconhecido: ${command}`));
2689
2980
  showHelp();
2690
2981
  process.exit(1);
2691
2982
  }
2692
2983
  }
2693
2984
  function showHelp() {
2694
2985
  console.log(`
2695
- ${import_picocolors7.default.bold("Usage:")} nimbus [command] [options]
2986
+ ${import_picocolors8.default.bold("Uso:")} nimbus [comando] [op\xE7\xF5es]
2696
2987
 
2697
- ${import_picocolors7.default.bold("Commands:")}
2698
- create [name] Create a new project
2699
- analyze [dir] Analyze project stack
2700
- upgrade [target] Upgrade dependencies
2701
- lola [action] Lola - Code Agent
2702
- help Show this help
2703
- version Show version
2988
+ ${import_picocolors8.default.bold("Comandos:")}
2989
+ create [nome] Criar novo projeto
2990
+ analyze [dir] Analisar stack do projeto
2991
+ upgrade [alvo] Atualizar depend\xEAncias
2992
+ update [vers\xE3o] Atualizar o CLI
2993
+ lola [a\xE7\xE3o] Lola - Code Agent
2994
+ help Mostrar esta ajuda
2995
+ version Mostrar vers\xE3o
2704
2996
 
2705
- ${import_picocolors7.default.bold("Templates:")}
2997
+ ${import_picocolors8.default.bold("Templates:")}
2706
2998
  --landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
2707
2999
  --app Web app (Landing + Better Auth + Drizzle)
2708
3000
  --turborepo Monorepo (Turborepo + apps/packages)
2709
3001
 
2710
- ${import_picocolors7.default.bold("Analyze & Upgrade:")}
2711
- analyze . Detect stack and show recommendations
2712
- analyze --json Output as JSON
2713
- upgrade --plan Show upgrade plan
2714
- upgrade next Upgrade Next.js
2715
- upgrade tailwind Upgrade Tailwind CSS
3002
+ ${import_picocolors8.default.bold("Analyze & Upgrade:")}
3003
+ analyze . Detectar stack e mostrar recomenda\xE7\xF5es
3004
+ analyze --json Output em JSON
3005
+ upgrade --plan Mostrar plano de upgrade
3006
+ upgrade next Atualizar Next.js
3007
+ upgrade tailwind Atualizar Tailwind CSS
3008
+
3009
+ ${import_picocolors8.default.bold("Update (CLI):")}
3010
+ update Atualizar para \xFAltima vers\xE3o
3011
+ update 0.11.0 Instalar vers\xE3o espec\xEDfica
3012
+ update --list Listar vers\xF5es dispon\xEDveis
2716
3013
 
2717
- ${import_picocolors7.default.bold("Options:")}
2718
- -y, --yes Accept defaults
2719
- --no-git Don't initialize Git
2720
- --no-install Don't install dependencies
2721
- --template <url> Use custom template
3014
+ ${import_picocolors8.default.bold("Op\xE7\xF5es:")}
3015
+ -y, --yes Aceitar padr\xF5es
3016
+ --no-git N\xE3o inicializar Git
3017
+ --no-install N\xE3o instalar depend\xEAncias
3018
+ --template <url> Usar template customizado
2722
3019
 
2723
- ${import_picocolors7.default.bold("Lola (Code Agent):")}
2724
- lola install Install/update Lola
2725
- lola suggest Suggest improvement (creates issue)
3020
+ ${import_picocolors8.default.bold("Lola (Code Agent):")}
3021
+ lola install Instalar/atualizar Lola
3022
+ lola suggest Sugerir melhoria (cria issue)
2726
3023
 
2727
- ${import_picocolors7.default.bold("Examples:")}
2728
- ${import_picocolors7.default.dim("$")} nimbus create my-landing --landing
2729
- ${import_picocolors7.default.dim("$")} nimbus create my-app --app
2730
- ${import_picocolors7.default.dim("$")} nimbus analyze ./my-project
2731
- ${import_picocolors7.default.dim("$")} nimbus upgrade --plan
2732
- ${import_picocolors7.default.dim("$")} nimbus lola install
2733
- ${import_picocolors7.default.dim("$")} nimbus lola suggest "add support for X"
3024
+ ${import_picocolors8.default.bold("Exemplos:")}
3025
+ ${import_picocolors8.default.dim("$")} nimbus create my-landing --landing
3026
+ ${import_picocolors8.default.dim("$")} nimbus create my-app --app
3027
+ ${import_picocolors8.default.dim("$")} nimbus analyze ./my-project
3028
+ ${import_picocolors8.default.dim("$")} nimbus upgrade --plan
3029
+ ${import_picocolors8.default.dim("$")} nimbus update
3030
+ ${import_picocolors8.default.dim("$")} nimbus lola install
2734
3031
  `);
2735
3032
  }
2736
3033
  function showVersion() {
2737
- console.log(`${PACKAGE_NAME} v${CURRENT_VERSION}`);
3034
+ console.log(`${PACKAGE_NAME2} v${CURRENT_VERSION}`);
2738
3035
  }
2739
3036
  main().catch((err) => {
2740
- console.error(import_picocolors7.default.red("Erro:"), err.message);
3037
+ console.error(import_picocolors8.default.red("Erro:"), err.message);
2741
3038
  process.exit(1);
2742
3039
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbuslab/cli",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "CLI para criar projetos nimbuslab",
5
5
  "type": "module",
6
6
  "bin": {
@@ -293,6 +293,173 @@ lola_profile: ${profile}
293
293
  console.log()
294
294
  }
295
295
 
296
+ // Quiz sobre a nimbuslab
297
+ interface QuizQuestion {
298
+ question: string
299
+ options: { value: string; label: string }[]
300
+ correct: string
301
+ explanation: string
302
+ }
303
+
304
+ const QUIZ_QUESTIONS: QuizQuestion[] = [
305
+ {
306
+ question: "Quais sao os 4 valores da nimbuslab?",
307
+ options: [
308
+ { value: "a", label: "Velocidade, Qualidade, Preco, Entrega" },
309
+ { value: "b", label: "Cocriacao, Inovacao, Evolucao, Humanizacao" },
310
+ { value: "c", label: "Codigo, Design, Marketing, Vendas" },
311
+ { value: "d", label: "Agil, Lean, Scrum, Kanban" },
312
+ ],
313
+ correct: "b",
314
+ explanation: "Cocriacao (construimos junto), Inovacao (buscamos o novo), Evolucao (aprendizado continuo), Humanizacao (tecnologia a servico das pessoas).",
315
+ },
316
+ {
317
+ question: "Quais sao os 4 pilares da filosofia fast?",
318
+ options: [
319
+ { value: "a", label: "Analise, Planejamento, Execucao, Documentacao" },
320
+ { value: "b", label: "Design, Codigo, Teste, Deploy" },
321
+ { value: "c", label: "Briefing, Prototipo, Desenvolvimento, Lancamento" },
322
+ { value: "d", label: "Discovery, Definition, Development, Delivery" },
323
+ ],
324
+ correct: "a",
325
+ explanation: "Filosofia fast: 1. Analise (entender), 2. Planejamento (definir caminho), 3. Execucao (implementar), 4. Documentacao (registrar).",
326
+ },
327
+ {
328
+ question: "Qual package manager a nimbuslab usa como padrao?",
329
+ options: [
330
+ { value: "a", label: "npm" },
331
+ { value: "b", label: "yarn" },
332
+ { value: "c", label: "pnpm" },
333
+ { value: "d", label: "bun" },
334
+ ],
335
+ correct: "d",
336
+ explanation: "Bun e o package manager padrao. Mais rapido e com menos dependencias.",
337
+ },
338
+ {
339
+ question: "Qual o estilo padrao do shadcn/ui na nimbuslab?",
340
+ options: [
341
+ { value: "a", label: "new-york" },
342
+ { value: "b", label: "default" },
343
+ { value: "c", label: "minimal" },
344
+ { value: "d", label: "custom" },
345
+ ],
346
+ correct: "b",
347
+ explanation: "Usamos o estilo 'default' do shadcn/ui. Nunca 'new-york'.",
348
+ },
349
+ {
350
+ question: "Em projetos externos (stealth mode), a Lola deve:",
351
+ options: [
352
+ { value: "a", label: "Sempre mencionar a nimbuslab nos commits" },
353
+ { value: "b", label: "Usar assinatura 'Co-authored-by: Lola'" },
354
+ { value: "c", label: "Nunca mencionar nimbuslab, Lola ou IA" },
355
+ { value: "d", label: "Adicionar badge da nimbuslab no README" },
356
+ ],
357
+ correct: "c",
358
+ explanation: "Stealth mode: commits sem mencao a nimbuslab/Lola/IA. O cliente nao precisa saber dos bastidores.",
359
+ },
360
+ {
361
+ question: "Qual a versao minima do Next.js usada na stack nimbuslab?",
362
+ options: [
363
+ { value: "a", label: "Next.js 13" },
364
+ { value: "b", label: "Next.js 14" },
365
+ { value: "c", label: "Next.js 15" },
366
+ { value: "d", label: "Next.js 16" },
367
+ ],
368
+ correct: "d",
369
+ explanation: "Stack atual: Next.js 16+ com App Router e Turbopack.",
370
+ },
371
+ {
372
+ question: "Quem pode aprovar e mergear mudancas no repositorio da Lola?",
373
+ options: [
374
+ { value: "a", label: "Qualquer dev da nimbuslab" },
375
+ { value: "b", label: "Apenas o Hugo" },
376
+ { value: "c", label: "Qualquer pessoa com acesso ao repo" },
377
+ { value: "d", label: "A propria Lola via automacao" },
378
+ ],
379
+ correct: "b",
380
+ explanation: "Apenas o Hugo pode aprovar e mergear. Devs sugerem via 'lola suggest', Hugo revisa.",
381
+ },
382
+ {
383
+ question: "Em commits da nimbuslab, qual o idioma correto?",
384
+ options: [
385
+ { value: "a", label: "Ingles" },
386
+ { value: "b", label: "Portugues (BR)" },
387
+ { value: "c", label: "Depende do projeto" },
388
+ { value: "d", label: "Spanglish" },
389
+ ],
390
+ correct: "b",
391
+ explanation: "Commits e PRs em Portugues (BR). Codigo e comentarios em Ingles.",
392
+ },
393
+ ]
394
+
395
+ async function runQuiz(): Promise<void> {
396
+ console.log()
397
+ console.log(pc.cyan(" Quiz nimbuslab"))
398
+ console.log(pc.dim(" =============="))
399
+ console.log()
400
+ console.log(pc.dim(" Teste seus conhecimentos sobre a nimbuslab!"))
401
+ console.log(pc.dim(" 8 perguntas sobre valores, filosofia e stack."))
402
+ console.log()
403
+
404
+ let score = 0
405
+ const results: { question: string; correct: boolean; explanation: string }[] = []
406
+
407
+ for (let i = 0; i < QUIZ_QUESTIONS.length; i++) {
408
+ const q = QUIZ_QUESTIONS[i]!
409
+
410
+ const answer = await p.select({
411
+ message: `${i + 1}. ${q.question}`,
412
+ options: q.options,
413
+ })
414
+
415
+ if (p.isCancel(answer)) {
416
+ p.cancel("Quiz cancelado")
417
+ process.exit(0)
418
+ }
419
+
420
+ const isCorrect = answer === q.correct
421
+ if (isCorrect) {
422
+ score++
423
+ console.log(pc.green(" Correto!"))
424
+ } else {
425
+ console.log(pc.red(" Incorreto."))
426
+ }
427
+ console.log(pc.dim(` ${q.explanation}`))
428
+ console.log()
429
+
430
+ results.push({
431
+ question: q.question,
432
+ correct: isCorrect,
433
+ explanation: q.explanation,
434
+ })
435
+ }
436
+
437
+ // Resultado final
438
+ const percentage = Math.round((score / QUIZ_QUESTIONS.length) * 100)
439
+ const passed = percentage >= 75
440
+
441
+ console.log(pc.bold(" Resultado:"))
442
+ console.log()
443
+
444
+ if (passed) {
445
+ console.log(pc.green(` ${score}/${QUIZ_QUESTIONS.length} (${percentage}%) - Aprovado!`))
446
+ console.log()
447
+ if (percentage === 100) {
448
+ console.log(pc.cyan(" Perfeito! Voce conhece bem a nimbuslab."))
449
+ } else {
450
+ console.log(pc.cyan(" Muito bem! Voce esta pronto para trabalhar."))
451
+ }
452
+ } else {
453
+ console.log(pc.yellow(` ${score}/${QUIZ_QUESTIONS.length} (${percentage}%) - Precisa revisar`))
454
+ console.log()
455
+ console.log(pc.dim(" Revise os conceitos em:"))
456
+ console.log(pc.dim(" ~/.lola/core/values.md"))
457
+ console.log(pc.dim(" ~/.lola/core/philosophy.md"))
458
+ console.log(pc.dim(" ~/.lola/modules/stack.md"))
459
+ }
460
+ console.log()
461
+ }
462
+
296
463
  export async function lola(args: string[]) {
297
464
  const subcommand = args[0]
298
465
 
@@ -300,6 +467,8 @@ export async function lola(args: string[]) {
300
467
  await installLola()
301
468
  } else if (subcommand === "onboard") {
302
469
  await onboardDev()
470
+ } else if (subcommand === "quiz") {
471
+ await runQuiz()
303
472
  } else if (subcommand === "suggest") {
304
473
  const message = args.slice(1).join(" ")
305
474
  await suggestImprovement(message)
@@ -322,12 +491,14 @@ function showLolaHelp() {
322
491
  console.log(pc.dim(" install ") + pc.white("Instalar/atualizar Lola"))
323
492
  console.log(pc.dim(" sync ") + pc.white("Alias para install"))
324
493
  console.log(pc.dim(" onboard ") + pc.white("Configurar perfil (novos devs)"))
494
+ console.log(pc.dim(" quiz ") + pc.white("Quiz sobre a nimbuslab"))
325
495
  console.log(pc.dim(" suggest \"msg\" ") + pc.white("Sugerir melhoria (cria issue)"))
326
496
  console.log(pc.dim(" help ") + pc.white("Mostrar esta ajuda"))
327
497
  console.log()
328
498
  console.log(pc.bold(" Exemplos:"))
329
499
  console.log(pc.dim(" $ nimbus lola install"))
330
500
  console.log(pc.dim(" $ nimbus lola onboard"))
501
+ console.log(pc.dim(" $ nimbus lola quiz"))
331
502
  console.log(pc.dim(" $ nimbus lola suggest \"adicionar suporte a X\""))
332
503
  console.log()
333
504
  }
@@ -0,0 +1,152 @@
1
+ import * as p from "@clack/prompts"
2
+ import pc from "picocolors"
3
+ import { execSync, spawnSync } from "child_process"
4
+
5
+ const PACKAGE_NAME = "@nimbuslab/cli"
6
+
7
+ async function getAvailableVersions(): Promise<string[]> {
8
+ try {
9
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`)
10
+ if (!res.ok) return []
11
+ const data = await res.json() as { versions?: Record<string, unknown> }
12
+ return Object.keys(data.versions || {}).reverse()
13
+ } catch {
14
+ return []
15
+ }
16
+ }
17
+
18
+ async function getLatestVersion(): Promise<string | null> {
19
+ try {
20
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`)
21
+ if (!res.ok) return null
22
+ const data = await res.json() as { version?: string }
23
+ return data.version || null
24
+ } catch {
25
+ return null
26
+ }
27
+ }
28
+
29
+ function getCurrentVersion(): string {
30
+ try {
31
+ const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
32
+ encoding: "utf-8",
33
+ shell: true,
34
+ })
35
+ if (result.stdout) {
36
+ const data = JSON.parse(result.stdout)
37
+ return data.dependencies?.[PACKAGE_NAME]?.version || "unknown"
38
+ }
39
+ } catch {
40
+ // ignore
41
+ }
42
+ return "unknown"
43
+ }
44
+
45
+ export async function update(args: string[]) {
46
+ const flag = args[0]
47
+
48
+ // nimbus update --list
49
+ if (flag === "--list" || flag === "-l") {
50
+ p.intro(pc.cyan("Versões disponíveis"))
51
+
52
+ const spinner = p.spinner()
53
+ spinner.start("Buscando versões...")
54
+
55
+ const versions = await getAvailableVersions()
56
+ spinner.stop("Versões encontradas")
57
+
58
+ if (versions.length === 0) {
59
+ p.log.error("Não foi possível buscar as versões")
60
+ return
61
+ }
62
+
63
+ const current = getCurrentVersion()
64
+
65
+ console.log()
66
+ console.log(pc.bold("Últimas 10 versões:"))
67
+ versions.slice(0, 10).forEach((v, i) => {
68
+ const isCurrent = v === current
69
+ const prefix = isCurrent ? pc.green("→ ") : " "
70
+ const suffix = isCurrent ? pc.dim(" (instalada)") : ""
71
+ const isLatest = i === 0 ? pc.yellow(" (latest)") : ""
72
+ console.log(`${prefix}${v}${suffix}${isLatest}`)
73
+ })
74
+ console.log()
75
+ console.log(pc.dim(`Total: ${versions.length} versões`))
76
+ console.log(pc.dim(`Instalar versão específica: nimbus update <versão>`))
77
+ return
78
+ }
79
+
80
+ // nimbus update [version]
81
+ const targetVersion = flag || "latest"
82
+ const isSpecificVersion = flag && flag !== "latest"
83
+
84
+ p.intro(pc.cyan(`Atualizando ${PACKAGE_NAME}`))
85
+
86
+ const spinner = p.spinner()
87
+
88
+ // Verificar versão atual
89
+ spinner.start("Verificando versão atual...")
90
+ const currentVersion = getCurrentVersion()
91
+ spinner.stop(`Versão atual: ${currentVersion}`)
92
+
93
+ // Verificar versão alvo
94
+ if (!isSpecificVersion) {
95
+ spinner.start("Verificando última versão...")
96
+ const latest = await getLatestVersion()
97
+ spinner.stop(`Última versão: ${latest || "desconhecida"}`)
98
+
99
+ if (latest && latest === currentVersion) {
100
+ p.log.success("Você já está na última versão!")
101
+ return
102
+ }
103
+ }
104
+
105
+ // Confirmar
106
+ const versionText = isSpecificVersion ? targetVersion : "latest"
107
+ const confirmUpdate = await p.confirm({
108
+ message: `Atualizar para ${versionText}?`,
109
+ initialValue: true,
110
+ })
111
+
112
+ if (p.isCancel(confirmUpdate) || !confirmUpdate) {
113
+ p.cancel("Atualização cancelada")
114
+ return
115
+ }
116
+
117
+ // Executar update
118
+ spinner.start("Atualizando...")
119
+
120
+ try {
121
+ const packageSpec = isSpecificVersion
122
+ ? `${PACKAGE_NAME}@${targetVersion}`
123
+ : PACKAGE_NAME
124
+
125
+ // Usar npm para instalação global (mais estável que bun)
126
+ execSync(`npm install -g ${packageSpec}`, {
127
+ stdio: "pipe",
128
+ encoding: "utf-8",
129
+ })
130
+
131
+ spinner.stop("Atualização concluída!")
132
+
133
+ // Verificar nova versão
134
+ const newVersion = getCurrentVersion()
135
+
136
+ p.log.success(`${PACKAGE_NAME} atualizado: ${currentVersion} → ${newVersion}`)
137
+ p.outro(pc.green("Pronto!"))
138
+ } catch (error) {
139
+ spinner.stop("Erro na atualização")
140
+
141
+ const err = error as Error & { stderr?: string }
142
+ p.log.error("Falha ao atualizar")
143
+
144
+ if (err.stderr) {
145
+ console.log(pc.dim(err.stderr))
146
+ }
147
+
148
+ console.log()
149
+ console.log(pc.yellow("Tente manualmente:"))
150
+ console.log(pc.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`))
151
+ }
152
+ }
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import pc from "picocolors"
5
5
  import { create } from "./commands/create"
6
6
  import { analyze } from "./commands/analyze"
7
7
  import { upgrade } from "./commands/upgrade"
8
+ import { update } from "./commands/update"
8
9
  import { lola } from "./commands/lola"
9
10
 
10
11
  const PACKAGE_NAME = "@nimbuslab/cli"
@@ -48,10 +49,10 @@ async function checkForUpdates(): Promise<string | null> {
48
49
  function showUpdateNotice(latestVersion: string) {
49
50
  const current = CURRENT_VERSION
50
51
  const latest = latestVersion
51
- const command = `bun add -g ${PACKAGE_NAME}`
52
+ const command = "nimbus update"
52
53
 
53
- const line1 = ` New version available: ${current} → ${latest}`
54
- const line2 = ` Update with: ${command}`
54
+ const line1 = ` Nova versão disponível: ${current} → ${latest}`
55
+ const line2 = ` Atualize com: ${command}`
55
56
 
56
57
  const maxLen = Math.max(line1.length, line2.length)
57
58
  const border = "─".repeat(maxLen + 2)
@@ -84,6 +85,8 @@ async function main() {
84
85
  await analyze(args.slice(1))
85
86
  } else if (command === "upgrade") {
86
87
  await upgrade(args.slice(1))
88
+ } else if (command === "update") {
89
+ await update(args.slice(1))
87
90
  } else if (command === "lola") {
88
91
  await lola(args.slice(1))
89
92
  } else if (command === "help" || command === "--help" || command === "-h") {
@@ -91,7 +94,7 @@ async function main() {
91
94
  } else if (command === "version" || command === "--version" || command === "-v") {
92
95
  showVersion()
93
96
  } else {
94
- console.log(pc.red(`Unknown command: ${command}`))
97
+ console.log(pc.red(`Comando desconhecido: ${command}`))
95
98
  showHelp()
96
99
  process.exit(1)
97
100
  }
@@ -99,15 +102,16 @@ async function main() {
99
102
 
100
103
  function showHelp() {
101
104
  console.log(`
102
- ${pc.bold("Usage:")} nimbus [command] [options]
105
+ ${pc.bold("Uso:")} nimbus [comando] [opções]
103
106
 
104
- ${pc.bold("Commands:")}
105
- create [name] Create a new project
106
- analyze [dir] Analyze project stack
107
- upgrade [target] Upgrade dependencies
108
- lola [action] Lola - Code Agent
109
- help Show this help
110
- version Show version
107
+ ${pc.bold("Comandos:")}
108
+ create [nome] Criar novo projeto
109
+ analyze [dir] Analisar stack do projeto
110
+ upgrade [alvo] Atualizar dependências
111
+ update [versão] Atualizar o CLI
112
+ lola [ação] Lola - Code Agent
113
+ help Mostrar esta ajuda
114
+ version Mostrar versão
111
115
 
112
116
  ${pc.bold("Templates:")}
113
117
  --landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
@@ -115,29 +119,34 @@ ${pc.bold("Templates:")}
115
119
  --turborepo Monorepo (Turborepo + apps/packages)
116
120
 
117
121
  ${pc.bold("Analyze & Upgrade:")}
118
- analyze . Detect stack and show recommendations
119
- analyze --json Output as JSON
120
- upgrade --plan Show upgrade plan
121
- upgrade next Upgrade Next.js
122
- upgrade tailwind Upgrade Tailwind CSS
123
-
124
- ${pc.bold("Options:")}
125
- -y, --yes Accept defaults
126
- --no-git Don't initialize Git
127
- --no-install Don't install dependencies
128
- --template <url> Use custom template
122
+ analyze . Detectar stack e mostrar recomendações
123
+ analyze --json Output em JSON
124
+ upgrade --plan Mostrar plano de upgrade
125
+ upgrade next Atualizar Next.js
126
+ upgrade tailwind Atualizar Tailwind CSS
127
+
128
+ ${pc.bold("Update (CLI):")}
129
+ update Atualizar para última versão
130
+ update 0.11.0 Instalar versão específica
131
+ update --list Listar versões disponíveis
132
+
133
+ ${pc.bold("Opções:")}
134
+ -y, --yes Aceitar padrões
135
+ --no-git Não inicializar Git
136
+ --no-install Não instalar dependências
137
+ --template <url> Usar template customizado
129
138
 
130
139
  ${pc.bold("Lola (Code Agent):")}
131
- lola install Install/update Lola
132
- lola suggest Suggest improvement (creates issue)
140
+ lola install Instalar/atualizar Lola
141
+ lola suggest Sugerir melhoria (cria issue)
133
142
 
134
- ${pc.bold("Examples:")}
143
+ ${pc.bold("Exemplos:")}
135
144
  ${pc.dim("$")} nimbus create my-landing --landing
136
145
  ${pc.dim("$")} nimbus create my-app --app
137
146
  ${pc.dim("$")} nimbus analyze ./my-project
138
147
  ${pc.dim("$")} nimbus upgrade --plan
148
+ ${pc.dim("$")} nimbus update
139
149
  ${pc.dim("$")} nimbus lola install
140
- ${pc.dim("$")} nimbus lola suggest "add support for X"
141
150
  `)
142
151
  }
143
152