@nimbuslab/cli 0.16.2 → 0.16.4

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.16.2",
153
+ version: "0.16.4",
154
154
  description: "CLI para criar projetos nimbuslab",
155
155
  type: "module",
156
156
  bin: {
@@ -161,7 +161,14 @@ var require_package = __commonJS((exports, module) => {
161
161
  build: "bun build src/index.ts --outdir dist --target bun",
162
162
  typecheck: "tsc --noEmit"
163
163
  },
164
- keywords: ["nimbuslab", "cli", "nextjs", "fast", "landing-page", "saas"],
164
+ keywords: [
165
+ "nimbuslab",
166
+ "cli",
167
+ "nextjs",
168
+ "fast",
169
+ "landing-page",
170
+ "saas"
171
+ ],
165
172
  author: {
166
173
  name: "nimbuslab",
167
174
  email: "contato@nimbuslab.com.br",
@@ -2360,9 +2367,55 @@ function printUpgradePlan(name, plan) {
2360
2367
  var import_picocolors6 = __toESM(require_picocolors(), 1);
2361
2368
  import { execSync, spawnSync } from "child_process";
2362
2369
  var PACKAGE_NAME = "@nimbuslab/cli";
2370
+ function hasBunInstall() {
2371
+ try {
2372
+ const result = spawnSync("bun", ["pm", "ls", "-g"], {
2373
+ encoding: "utf-8",
2374
+ shell: true,
2375
+ timeout: 5000
2376
+ });
2377
+ return !!(result.stdout && result.stdout.includes(PACKAGE_NAME));
2378
+ } catch {
2379
+ return false;
2380
+ }
2381
+ }
2382
+ function hasNpmInstall() {
2383
+ try {
2384
+ const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
2385
+ encoding: "utf-8",
2386
+ shell: true,
2387
+ timeout: 5000
2388
+ });
2389
+ if (result.stdout) {
2390
+ const data = JSON.parse(result.stdout);
2391
+ return !!data.dependencies?.[PACKAGE_NAME];
2392
+ }
2393
+ } catch {}
2394
+ return false;
2395
+ }
2396
+ function cleanupDuplicateInstalls() {
2397
+ const hasNpm = hasNpmInstall();
2398
+ const hasBun = hasBunInstall();
2399
+ if (hasNpm && hasBun) {
2400
+ try {
2401
+ execSync("bun remove -g @nimbuslab/cli", { stdio: "pipe", encoding: "utf-8" });
2402
+ return {
2403
+ cleaned: true,
2404
+ message: "Instalacao duplicada removida do bun (usando npm)"
2405
+ };
2406
+ } catch {
2407
+ return {
2408
+ cleaned: false,
2409
+ message: "Falha ao remover instalacao duplicada do bun"
2410
+ };
2411
+ }
2412
+ }
2413
+ return { cleaned: false, message: "" };
2414
+ }
2363
2415
  function isUsingFnm() {
2364
2416
  const fnmDir = process.env.FNM_DIR || process.env.FNM_MULTISHELL_PATH;
2365
- const whichNode = spawnSync("which", ["node"], { encoding: "utf-8", shell: true });
2417
+ const checkCmd = process.platform === "win32" ? "where" : "which";
2418
+ const whichNode = spawnSync(checkCmd, ["node"], { encoding: "utf-8", shell: true });
2366
2419
  return !!(fnmDir || whichNode.stdout && whichNode.stdout.includes("fnm"));
2367
2420
  }
2368
2421
  async function getAvailableVersions() {
@@ -2478,6 +2531,13 @@ async function update(args) {
2478
2531
  const isSpecificVersion = flag && flag !== "latest" && !flag.startsWith("-");
2479
2532
  Ie(import_picocolors6.default.cyan(`Atualizando ${PACKAGE_NAME}`));
2480
2533
  const spinner = Y2();
2534
+ spinner.start("Verificando instalacoes...");
2535
+ const cleanup = cleanupDuplicateInstalls();
2536
+ if (cleanup.cleaned) {
2537
+ spinner.stop(import_picocolors6.default.yellow(cleanup.message));
2538
+ } else {
2539
+ spinner.stop("OK");
2540
+ }
2481
2541
  spinner.start("Detectando package manager...");
2482
2542
  const detectedPm = detectPackageManager2();
2483
2543
  const pm = detectedPm === "unknown" ? "npm" : detectedPm;
@@ -2564,18 +2624,19 @@ var LOLA_MEMORY_URL = "https://lola.nimbuslab.com.br/sse";
2564
2624
  var LOLA_MEMORY_NAME = "lola-memory";
2565
2625
  var GEMINI_DIR = join3(HOME, ".gemini");
2566
2626
  var GEMINI_SETTINGS = join3(GEMINI_DIR, "GEMINI.md");
2627
+ var CHECK_CMD = process.platform === "win32" ? "where" : "which";
2567
2628
  function hasClaudeCLI() {
2568
- const result = Bun.spawnSync(["which", "claude"], { stdout: "pipe" });
2629
+ const result = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" });
2569
2630
  return result.exitCode === 0;
2570
2631
  }
2571
2632
  function hasGeminiCLI() {
2572
- const result = Bun.spawnSync(["which", "gemini"], { stdout: "pipe" });
2633
+ const result = Bun.spawnSync([CHECK_CMD, "gemini"], { stdout: "pipe", stderr: "pipe" });
2573
2634
  return result.exitCode === 0;
2574
2635
  }
2575
2636
  async function installLolaMemoryMCP() {
2576
2637
  console.log();
2577
2638
  console.log(import_picocolors7.default.cyan(" Configurando lola-memory MCP..."));
2578
- const claudeCheck = Bun.spawnSync(["which", "claude"], { stdout: "pipe" });
2639
+ const claudeCheck = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" });
2579
2640
  if (claudeCheck.exitCode !== 0) {
2580
2641
  console.log(import_picocolors7.default.yellow(" Claude CLI nao encontrado, pulando MCP"));
2581
2642
  console.log(import_picocolors7.default.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"));
@@ -2765,7 +2826,7 @@ async function suggestImprovement(message) {
2765
2826
  console.log(import_picocolors7.default.dim(' Uso: nimbus lola suggest "sua sugestao aqui"'));
2766
2827
  process.exit(1);
2767
2828
  }
2768
- const ghCheck = Bun.spawnSync(["which", "gh"]);
2829
+ const ghCheck = Bun.spawnSync([CHECK_CMD, "gh"], { stderr: "pipe" });
2769
2830
  if (ghCheck.exitCode !== 0) {
2770
2831
  console.log(import_picocolors7.default.red(" Erro: GitHub CLI (gh) nao encontrado"));
2771
2832
  console.log(import_picocolors7.default.dim(" Instale: https://cli.github.com"));
@@ -3336,9 +3397,20 @@ lola_profile: millennial
3336
3397
  console.log();
3337
3398
  console.log(import_picocolors7.default.green(" Claude configurado!"));
3338
3399
  }
3400
+ var SUBCOMMAND_ALIASES = {
3401
+ i: "install",
3402
+ s: "suggest",
3403
+ o: "onboard",
3404
+ q: "quiz",
3405
+ h: "help",
3406
+ sync: "install",
3407
+ "--help": "help",
3408
+ "-h": "help"
3409
+ };
3339
3410
  async function lola(args) {
3340
- const subcommand = args[0];
3341
- if (!subcommand || subcommand === "install" || subcommand === "sync") {
3411
+ const rawSubcommand = args[0];
3412
+ const subcommand = rawSubcommand ? SUBCOMMAND_ALIASES[rawSubcommand] || rawSubcommand : null;
3413
+ if (!subcommand || subcommand === "install") {
3342
3414
  await installInteractive();
3343
3415
  } else if (subcommand === "onboard") {
3344
3416
  await onboardDev();
@@ -3347,10 +3419,10 @@ async function lola(args) {
3347
3419
  } else if (subcommand === "suggest") {
3348
3420
  const message = args.slice(1).join(" ");
3349
3421
  await suggestImprovement(message);
3350
- } else if (subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
3422
+ } else if (subcommand === "help") {
3351
3423
  showLolaHelp();
3352
3424
  } else {
3353
- console.log(import_picocolors7.default.red(` Subcomando desconhecido: ${subcommand}`));
3425
+ console.log(import_picocolors7.default.red(` Subcomando desconhecido: ${rawSubcommand}`));
3354
3426
  showLolaHelp();
3355
3427
  process.exit(1);
3356
3428
  }
@@ -3362,18 +3434,17 @@ function showLolaHelp() {
3362
3434
  console.log(import_picocolors7.default.bold(" Uso:") + " nimbus lola [subcomando]");
3363
3435
  console.log();
3364
3436
  console.log(import_picocolors7.default.bold(" Subcomandos:"));
3365
- console.log(import_picocolors7.default.dim(" install ") + import_picocolors7.default.white("Instalar/atualizar Lola + MCP"));
3366
- console.log(import_picocolors7.default.dim(" sync ") + import_picocolors7.default.white("Alias para install"));
3367
- console.log(import_picocolors7.default.dim(" onboard ") + import_picocolors7.default.white("Configurar perfil (novos devs)"));
3368
- console.log(import_picocolors7.default.dim(" quiz ") + import_picocolors7.default.white("Quiz sobre a nimbuslab"));
3369
- console.log(import_picocolors7.default.dim(' suggest "msg" ') + import_picocolors7.default.white("Sugerir melhoria (cria issue)"));
3370
- console.log(import_picocolors7.default.dim(" help ") + import_picocolors7.default.white("Mostrar esta ajuda"));
3437
+ console.log(import_picocolors7.default.dim(" install, i ") + import_picocolors7.default.white("Instalar/atualizar Lola + MCP"));
3438
+ console.log(import_picocolors7.default.dim(" onboard, o ") + import_picocolors7.default.white("Configurar perfil (novos devs)"));
3439
+ console.log(import_picocolors7.default.dim(" quiz, q ") + import_picocolors7.default.white("Quiz sobre a nimbuslab"));
3440
+ console.log(import_picocolors7.default.dim(" suggest, s ") + import_picocolors7.default.white("Sugerir melhoria (cria issue)"));
3441
+ console.log(import_picocolors7.default.dim(" help, h ") + import_picocolors7.default.white("Mostrar esta ajuda"));
3371
3442
  console.log();
3372
3443
  console.log(import_picocolors7.default.bold(" Exemplos:"));
3373
- console.log(import_picocolors7.default.dim(" $ nimbus lola install"));
3374
- console.log(import_picocolors7.default.dim(" $ nimbus lola onboard"));
3375
- console.log(import_picocolors7.default.dim(" $ nimbus lola quiz"));
3376
- console.log(import_picocolors7.default.dim(' $ nimbus lola suggest "adicionar suporte a X"'));
3444
+ console.log(import_picocolors7.default.dim(" $ nimbus lola i"));
3445
+ console.log(import_picocolors7.default.dim(" $ nimbus lola o"));
3446
+ console.log(import_picocolors7.default.dim(" $ nimbus lola q"));
3447
+ console.log(import_picocolors7.default.dim(' $ nimbus lola s "adicionar suporte a X"'));
3377
3448
  console.log();
3378
3449
  console.log(import_picocolors7.default.bold(" lola-memory (dentro do Claude):"));
3379
3450
  console.log(import_picocolors7.default.dim(' remember "query" ') + import_picocolors7.default.white("Buscar conhecimento"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbuslab/cli",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "description": "CLI para criar projetos nimbuslab",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,14 @@
11
11
  "build": "bun build src/index.ts --outdir dist --target bun",
12
12
  "typecheck": "tsc --noEmit"
13
13
  },
14
- "keywords": ["nimbuslab", "cli", "nextjs", "fast", "landing-page", "saas"],
14
+ "keywords": [
15
+ "nimbuslab",
16
+ "cli",
17
+ "nextjs",
18
+ "fast",
19
+ "landing-page",
20
+ "saas"
21
+ ],
15
22
  "author": {
16
23
  "name": "nimbuslab",
17
24
  "email": "contato@nimbuslab.com.br",
@@ -18,14 +18,17 @@ const GEMINI_SETTINGS = join(GEMINI_DIR, "GEMINI.md")
18
18
  // Tipos de agent
19
19
  type AgentType = "claude" | "gemini" | "all"
20
20
 
21
+ // Comando para verificar executavel (which no Unix, where no Windows)
22
+ const CHECK_CMD = process.platform === "win32" ? "where" : "which"
23
+
21
24
  // Helpers de detecção
22
25
  function hasClaudeCLI(): boolean {
23
- const result = Bun.spawnSync(["which", "claude"], { stdout: "pipe" })
26
+ const result = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" })
24
27
  return result.exitCode === 0
25
28
  }
26
29
 
27
30
  function hasGeminiCLI(): boolean {
28
- const result = Bun.spawnSync(["which", "gemini"], { stdout: "pipe" })
31
+ const result = Bun.spawnSync([CHECK_CMD, "gemini"], { stdout: "pipe", stderr: "pipe" })
29
32
  return result.exitCode === 0
30
33
  }
31
34
 
@@ -34,7 +37,7 @@ async function installLolaMemoryMCP(): Promise<void> {
34
37
  console.log(pc.cyan(" Configurando lola-memory MCP..."))
35
38
 
36
39
  // Verificar se claude CLI existe
37
- const claudeCheck = Bun.spawnSync(["which", "claude"], { stdout: "pipe" })
40
+ const claudeCheck = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" })
38
41
  if (claudeCheck.exitCode !== 0) {
39
42
  console.log(pc.yellow(" Claude CLI nao encontrado, pulando MCP"))
40
43
  console.log(pc.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"))
@@ -287,7 +290,7 @@ async function suggestImprovement(message: string): Promise<void> {
287
290
  }
288
291
 
289
292
  // Verificar gh cli
290
- const ghCheck = Bun.spawnSync(["which", "gh"])
293
+ const ghCheck = Bun.spawnSync([CHECK_CMD, "gh"], { stderr: "pipe" })
291
294
  if (ghCheck.exitCode !== 0) {
292
295
  console.log(pc.red(" Erro: GitHub CLI (gh) nao encontrado"))
293
296
  console.log(pc.dim(" Instale: https://cli.github.com"))
@@ -964,10 +967,23 @@ lola_profile: millennial
964
967
  console.log(pc.green(" Claude configurado!"))
965
968
  }
966
969
 
970
+ // Aliases para subcomandos
971
+ const SUBCOMMAND_ALIASES: Record<string, string> = {
972
+ i: "install",
973
+ s: "suggest",
974
+ o: "onboard",
975
+ q: "quiz",
976
+ h: "help",
977
+ sync: "install",
978
+ "--help": "help",
979
+ "-h": "help",
980
+ }
981
+
967
982
  export async function lola(args: string[]) {
968
- const subcommand = args[0]
983
+ const rawSubcommand = args[0]
984
+ const subcommand = rawSubcommand ? (SUBCOMMAND_ALIASES[rawSubcommand] || rawSubcommand) : null
969
985
 
970
- if (!subcommand || subcommand === "install" || subcommand === "sync") {
986
+ if (!subcommand || subcommand === "install") {
971
987
  await installInteractive()
972
988
  } else if (subcommand === "onboard") {
973
989
  await onboardDev()
@@ -976,10 +992,10 @@ export async function lola(args: string[]) {
976
992
  } else if (subcommand === "suggest") {
977
993
  const message = args.slice(1).join(" ")
978
994
  await suggestImprovement(message)
979
- } else if (subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
995
+ } else if (subcommand === "help") {
980
996
  showLolaHelp()
981
997
  } else {
982
- console.log(pc.red(` Subcomando desconhecido: ${subcommand}`))
998
+ console.log(pc.red(` Subcomando desconhecido: ${rawSubcommand}`))
983
999
  showLolaHelp()
984
1000
  process.exit(1)
985
1001
  }
@@ -992,18 +1008,17 @@ function showLolaHelp() {
992
1008
  console.log(pc.bold(" Uso:") + " nimbus lola [subcomando]")
993
1009
  console.log()
994
1010
  console.log(pc.bold(" Subcomandos:"))
995
- console.log(pc.dim(" install ") + pc.white("Instalar/atualizar Lola + MCP"))
996
- console.log(pc.dim(" sync ") + pc.white("Alias para install"))
997
- console.log(pc.dim(" onboard ") + pc.white("Configurar perfil (novos devs)"))
998
- console.log(pc.dim(" quiz ") + pc.white("Quiz sobre a nimbuslab"))
999
- console.log(pc.dim(" suggest \"msg\" ") + pc.white("Sugerir melhoria (cria issue)"))
1000
- console.log(pc.dim(" help ") + pc.white("Mostrar esta ajuda"))
1011
+ console.log(pc.dim(" install, i ") + pc.white("Instalar/atualizar Lola + MCP"))
1012
+ console.log(pc.dim(" onboard, o ") + pc.white("Configurar perfil (novos devs)"))
1013
+ console.log(pc.dim(" quiz, q ") + pc.white("Quiz sobre a nimbuslab"))
1014
+ console.log(pc.dim(" suggest, s ") + pc.white("Sugerir melhoria (cria issue)"))
1015
+ console.log(pc.dim(" help, h ") + pc.white("Mostrar esta ajuda"))
1001
1016
  console.log()
1002
1017
  console.log(pc.bold(" Exemplos:"))
1003
- console.log(pc.dim(" $ nimbus lola install"))
1004
- console.log(pc.dim(" $ nimbus lola onboard"))
1005
- console.log(pc.dim(" $ nimbus lola quiz"))
1006
- console.log(pc.dim(" $ nimbus lola suggest \"adicionar suporte a X\""))
1018
+ console.log(pc.dim(" $ nimbus lola i"))
1019
+ console.log(pc.dim(" $ nimbus lola o"))
1020
+ console.log(pc.dim(" $ nimbus lola q"))
1021
+ console.log(pc.dim(" $ nimbus lola s \"adicionar suporte a X\""))
1007
1022
  console.log()
1008
1023
  console.log(pc.bold(" lola-memory (dentro do Claude):"))
1009
1024
  console.log(pc.dim(" remember \"query\" ") + pc.white("Buscar conhecimento"))
@@ -6,10 +6,68 @@ const PACKAGE_NAME = "@nimbuslab/cli"
6
6
 
7
7
  type PackageManager = "bun" | "npm" | "unknown"
8
8
 
9
+ // Verifica se existe instalacao no bun global
10
+ function hasBunInstall(): boolean {
11
+ try {
12
+ const result = spawnSync("bun", ["pm", "ls", "-g"], {
13
+ encoding: "utf-8",
14
+ shell: true,
15
+ timeout: 5000,
16
+ })
17
+ return !!(result.stdout && result.stdout.includes(PACKAGE_NAME))
18
+ } catch {
19
+ return false
20
+ }
21
+ }
22
+
23
+ // Verifica se existe instalacao no npm global
24
+ function hasNpmInstall(): boolean {
25
+ try {
26
+ const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
27
+ encoding: "utf-8",
28
+ shell: true,
29
+ timeout: 5000,
30
+ })
31
+ if (result.stdout) {
32
+ const data = JSON.parse(result.stdout)
33
+ return !!data.dependencies?.[PACKAGE_NAME]
34
+ }
35
+ } catch {
36
+ // ignore
37
+ }
38
+ return false
39
+ }
40
+
41
+ // Remove instalacao duplicada para evitar conflitos
42
+ // Prioriza npm (fnm/nvm), remove bun se tiver npm
43
+ function cleanupDuplicateInstalls(): { cleaned: boolean; message: string } {
44
+ const hasNpm = hasNpmInstall()
45
+ const hasBun = hasBunInstall()
46
+
47
+ if (hasNpm && hasBun) {
48
+ // Tem nos dois - remover do bun (prioriza npm)
49
+ try {
50
+ execSync("bun remove -g @nimbuslab/cli", { stdio: "pipe", encoding: "utf-8" })
51
+ return {
52
+ cleaned: true,
53
+ message: "Instalacao duplicada removida do bun (usando npm)",
54
+ }
55
+ } catch {
56
+ return {
57
+ cleaned: false,
58
+ message: "Falha ao remover instalacao duplicada do bun",
59
+ }
60
+ }
61
+ }
62
+
63
+ return { cleaned: false, message: "" }
64
+ }
65
+
9
66
  // Detecta se está usando fnm (Fast Node Manager)
10
67
  function isUsingFnm(): boolean {
11
68
  const fnmDir = process.env.FNM_DIR || process.env.FNM_MULTISHELL_PATH
12
- const whichNode = spawnSync("which", ["node"], { encoding: "utf-8", shell: true })
69
+ const checkCmd = process.platform === "win32" ? "where" : "which"
70
+ const whichNode = spawnSync(checkCmd, ["node"], { encoding: "utf-8", shell: true })
13
71
  return !!(fnmDir || (whichNode.stdout && whichNode.stdout.includes("fnm")))
14
72
  }
15
73
 
@@ -160,6 +218,15 @@ export async function update(args: string[]) {
160
218
 
161
219
  const spinner = p.spinner()
162
220
 
221
+ // Limpar instalacoes duplicadas automaticamente
222
+ spinner.start("Verificando instalacoes...")
223
+ const cleanup = cleanupDuplicateInstalls()
224
+ if (cleanup.cleaned) {
225
+ spinner.stop(pc.yellow(cleanup.message))
226
+ } else {
227
+ spinner.stop("OK")
228
+ }
229
+
163
230
  // Detectar package manager
164
231
  spinner.start("Detectando package manager...")
165
232
  const detectedPm = detectPackageManager()