@nimbuslab/cli 0.14.0 → 0.16.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.
@@ -11,6 +11,24 @@ const USER_MEMORY = join(HOME, ".claude", "USER_MEMORY.md")
11
11
  const LOLA_MEMORY_URL = "https://lola.nimbuslab.com.br/sse"
12
12
  const LOLA_MEMORY_NAME = "lola-memory"
13
13
 
14
+ // Gemini CLI
15
+ const GEMINI_DIR = join(HOME, ".gemini")
16
+ const GEMINI_SETTINGS = join(GEMINI_DIR, "GEMINI.md")
17
+
18
+ // Tipos de agent
19
+ type AgentType = "claude" | "gemini" | "all"
20
+
21
+ // Helpers de detecção
22
+ function hasClaudeCLI(): boolean {
23
+ const result = Bun.spawnSync(["which", "claude"], { stdout: "pipe" })
24
+ return result.exitCode === 0
25
+ }
26
+
27
+ function hasGeminiCLI(): boolean {
28
+ const result = Bun.spawnSync(["which", "gemini"], { stdout: "pipe" })
29
+ return result.exitCode === 0
30
+ }
31
+
14
32
  async function installLolaMemoryMCP(): Promise<void> {
15
33
  console.log()
16
34
  console.log(pc.cyan(" Configurando lola-memory MCP..."))
@@ -61,228 +79,206 @@ async function installLolaMemoryMCP(): Promise<void> {
61
79
  console.log(pc.dim(" memory_stats - Ver estatisticas"))
62
80
  }
63
81
 
64
- async function installLola(): Promise<void> {
65
- console.log()
66
- console.log(pc.cyan(" Lola - Code Agent da nimbuslab"))
67
- console.log(pc.dim(" ==============================="))
82
+ // ============================================
83
+ // GEMINI CLI
84
+ // ============================================
85
+
86
+ async function installGeminiCLI(): Promise<boolean> {
68
87
  console.log()
88
+ console.log(pc.cyan(" Instalando Gemini CLI..."))
69
89
 
70
- const isUpdate = existsSync(LOLA_DIR)
90
+ const result = Bun.spawnSync(["npm", "install", "-g", "@google/gemini-cli"], {
91
+ stdout: "inherit",
92
+ stderr: "inherit",
93
+ })
71
94
 
72
- if (isUpdate) {
73
- console.log(pc.dim(` Lola ja instalada em ${LOLA_DIR}`))
74
- console.log(pc.cyan(" Atualizando..."))
95
+ if (result.exitCode !== 0) {
96
+ console.log(pc.red(" Erro ao instalar Gemini CLI"))
97
+ console.log(pc.dim(" Tente manualmente: npm install -g @google/gemini-cli"))
98
+ return false
99
+ }
75
100
 
76
- const result = Bun.spawnSync(["git", "pull", "--quiet"], {
77
- cwd: LOLA_DIR,
78
- stdout: "inherit",
79
- stderr: "inherit",
80
- })
101
+ console.log(pc.green(" Gemini CLI instalado!"))
102
+ return true
103
+ }
81
104
 
82
- if (result.exitCode !== 0) {
83
- console.log(pc.red(" Erro ao atualizar Lola"))
84
- process.exit(1)
85
- }
105
+ async function installGeminiMCP(): Promise<void> {
106
+ console.log()
107
+ console.log(pc.cyan(" Configurando MCP no Gemini..."))
86
108
 
87
- console.log(pc.green(" Atualizado!"))
88
- } else {
89
- console.log(pc.cyan(` Instalando Lola em ${LOLA_DIR}...`))
109
+ const settingsPath = join(GEMINI_DIR, "settings.json")
90
110
 
91
- const result = Bun.spawnSync(["git", "clone", "--quiet", LOLA_REPO, LOLA_DIR], {
92
- stdout: "inherit",
93
- stderr: "inherit",
94
- })
111
+ // Criar diretório se não existir
112
+ if (!existsSync(GEMINI_DIR)) {
113
+ await Bun.$`mkdir -p ${GEMINI_DIR}`
114
+ }
95
115
 
96
- if (result.exitCode !== 0) {
97
- console.log(pc.red(" Erro ao clonar repositorio"))
98
- console.log(pc.dim(" Verifique se tem acesso ao repo nimbuslab/lola"))
99
- process.exit(1)
116
+ // Ler settings existente ou criar novo
117
+ let settings: Record<string, unknown> = {}
118
+ if (existsSync(settingsPath)) {
119
+ try {
120
+ const content = await Bun.file(settingsPath).text()
121
+ settings = JSON.parse(content)
122
+ } catch {
123
+ // Se falhar, começa do zero
100
124
  }
125
+ }
101
126
 
102
- console.log(pc.green(" Instalado!"))
127
+ // Verificar se já tem lola-memory configurado
128
+ const mcpServers = (settings.mcpServers || {}) as Record<string, unknown>
129
+ if (mcpServers[LOLA_MEMORY_NAME]) {
130
+ console.log(pc.green(" MCP lola-memory ja configurado no Gemini"))
131
+ return
103
132
  }
104
133
 
105
- // Criar comando lola
106
- const isWindows = process.platform === "win32"
134
+ // Adicionar lola-memory
135
+ mcpServers[LOLA_MEMORY_NAME] = {
136
+ url: LOLA_MEMORY_URL
137
+ }
138
+ settings.mcpServers = mcpServers
139
+
140
+ // Salvar
141
+ await Bun.write(settingsPath, JSON.stringify(settings, null, 2))
142
+ console.log(pc.green(" MCP lola-memory adicionado ao Gemini!"))
143
+ }
144
+
145
+ async function installGeminiSystemPrompt(): Promise<void> {
146
+ console.log()
147
+ console.log(pc.cyan(" Configurando GEMINI.md..."))
148
+
149
+ // Criar diretório se não existir
150
+ if (!existsSync(GEMINI_DIR)) {
151
+ await Bun.$`mkdir -p ${GEMINI_DIR}`
152
+ }
153
+
154
+ // Copiar o agent da Lola (adaptar claude.md para gemini)
107
155
  const lolaAgent = join(LOLA_DIR, "agents", "claude.md")
108
156
 
157
+ if (!existsSync(lolaAgent)) {
158
+ console.log(pc.yellow(" Agent Lola nao encontrado"))
159
+ console.log(pc.dim(" Rode 'nimbus lola install' primeiro"))
160
+ return
161
+ }
162
+
163
+ // Ler o agent do Claude
164
+ let content = await Bun.file(lolaAgent).text()
165
+
166
+ // Remover frontmatter do Claude (não suportado no Gemini)
167
+ content = content.replace(/^---[\s\S]*?---\n/, "")
168
+
169
+ // Adaptar menções específicas
170
+ content = content.replace(/Claude Code/g, "Gemini CLI")
171
+ content = content.replace(/Claude CLI/g, "Gemini CLI")
172
+
173
+ // Adicionar header para Gemini
174
+ const geminiContent = `# Lola - Code Agent (Gemini)
175
+
176
+ > Este arquivo configura a Lola para o Gemini CLI
177
+ > Gerado automaticamente por: nimbus lola install
178
+
179
+ ---
180
+
181
+ ${content}`
182
+
183
+ await Bun.write(GEMINI_SETTINGS, geminiContent)
184
+ console.log(pc.green(" GEMINI.md criado!"))
185
+ }
186
+
187
+ async function createGeminiCommand(): Promise<void> {
188
+ const isWindows = process.platform === "win32"
189
+ const lolaAgent = GEMINI_SETTINGS
190
+
109
191
  console.log()
110
- console.log(pc.cyan(" Configurando comando lola..."))
192
+ console.log(pc.cyan(" Configurando comando lola-gemini..."))
111
193
 
112
194
  if (isWindows) {
113
195
  // Windows: adicionar função ao PowerShell profile
114
- // PowerShell 5.x usa WindowsPowerShell, PowerShell 7+ usa PowerShell
115
- const ps5ProfileDir = join(HOME, "Documents", "WindowsPowerShell")
116
196
  const ps7ProfileDir = join(HOME, "Documents", "PowerShell")
117
197
  const profileName = "Microsoft.PowerShell_profile.ps1"
198
+ const profilePath = join(ps7ProfileDir, profileName)
118
199
 
119
- const lolaFunction = `
120
- # Lola - Code Agent da nimbuslab
121
- function lola {
200
+ const lolaGeminiFunction = `
201
+ # Lola (Gemini) - Code Agent da nimbuslab
202
+ function lola-gemini {
122
203
  param([Parameter(ValueFromRemainingArguments=$true)]$args)
123
- $agent = "$env:USERPROFILE\\.lola\\agents\\claude.md"
124
- if (Test-Path $agent) {
125
- claude --append-system-prompt-file $agent @args
126
- } else {
127
- Write-Host "Agente Lola nao encontrado. Rode: nimbus lola install"
128
- }
204
+ gemini @args
129
205
  }
130
206
  `
131
207
 
132
- // Adicionar função em ambos os profiles (PS 5.x e 7+)
133
- const profiles = [
134
- { dir: ps5ProfileDir, name: "PowerShell 5.x" },
135
- { dir: ps7ProfileDir, name: "PowerShell 7+" },
136
- ]
137
-
138
- let addedToAny = false
139
-
140
- for (const { dir, name } of profiles) {
141
- const profilePath = join(dir, profileName)
142
-
143
- // Criar diretório se não existir
144
- if (!existsSync(dir)) {
145
- await Bun.$`mkdir -p ${dir}`
146
- }
147
-
148
- // Verificar se já tem a função no profile
149
- let profileContent = ""
150
- if (existsSync(profilePath)) {
151
- profileContent = await Bun.file(profilePath).text()
152
- }
208
+ if (!existsSync(ps7ProfileDir)) {
209
+ await Bun.$`mkdir -p ${ps7ProfileDir}`
210
+ }
153
211
 
154
- if (!profileContent.includes("function lola")) {
155
- await Bun.write(profilePath, profileContent + lolaFunction)
156
- console.log(pc.green(` Funcao lola adicionada ao ${name} profile`))
157
- addedToAny = true
158
- }
212
+ let profileContent = ""
213
+ if (existsSync(profilePath)) {
214
+ profileContent = await Bun.file(profilePath).text()
159
215
  }
160
216
 
161
- if (addedToAny) {
162
- console.log(pc.yellow(" Reinicie o PowerShell para usar o comando 'lola'"))
163
- console.log()
164
- console.log(pc.yellow(" IMPORTANTE (Windows):"))
165
- console.log(pc.dim(" Se o comando 'lola' nao funcionar, execute primeiro:"))
166
- console.log(pc.cyan(" Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser"))
167
- console.log(pc.dim(" Isso habilita execucao de scripts no PowerShell."))
217
+ if (!profileContent.includes("function lola-gemini")) {
218
+ await Bun.write(profilePath, profileContent + lolaGeminiFunction)
219
+ console.log(pc.green(" Funcao lola-gemini adicionada ao PowerShell"))
168
220
  } else {
169
- console.log(pc.green(" Funcao lola ja existe nos profiles do PowerShell"))
221
+ console.log(pc.green(" Funcao lola-gemini ja existe"))
170
222
  }
171
223
  } else {
172
224
  // Linux/macOS: criar script em ~/.local/bin
173
225
  const binDir = join(HOME, ".local", "bin")
174
- const lolaScript = join(binDir, "lola")
226
+ const lolaGeminiScript = join(binDir, "lola-gemini")
175
227
 
176
- if (!existsSync(lolaScript)) {
228
+ if (!existsSync(lolaGeminiScript)) {
177
229
  await Bun.$`mkdir -p ${binDir}`
178
230
 
179
231
  const unixScript = `#!/bin/bash
180
- # lola - Code Agent da nimbuslab
181
- LOLA_AGENT="${lolaAgent}"
232
+ # lola-gemini - Code Agent da nimbuslab (Gemini)
182
233
 
183
234
  if [[ "\$1" == "-h" || "\$1" == "--help" ]]; then
184
- echo "lola - Code Agent da nimbuslab"
185
- echo "Uso: lola [args]"
186
- echo " lola Abre Claude CLI com a Lola"
187
- echo " lola --resume Resume sessao anterior"
235
+ echo "lola-gemini - Code Agent da nimbuslab (Gemini)"
236
+ echo "Uso: lola-gemini [args]"
237
+ echo " lola-gemini Abre Gemini CLI com a Lola"
188
238
  exit 0
189
239
  fi
190
240
 
191
- if [[ -f "\$LOLA_AGENT" ]]; then
192
- exec claude --append-system-prompt-file "\$LOLA_AGENT" "\$@"
193
- else
194
- echo "Agente Lola nao encontrado: \$LOLA_AGENT"
195
- echo "Rode: nimbus lola install"
196
- exit 1
197
- fi
241
+ exec gemini "\$@"
198
242
  `
199
- await Bun.write(lolaScript, unixScript)
200
- await Bun.$`chmod +x ${lolaScript}`
243
+ await Bun.write(lolaGeminiScript, unixScript)
244
+ await Bun.$`chmod +x ${lolaGeminiScript}`
201
245
 
202
- console.log(pc.green(` Script lola criado em ${lolaScript}`))
203
-
204
- // Verificar se ~/.local/bin está no PATH
205
- const pathEnv = process.env.PATH || ""
206
- if (!pathEnv.includes(".local/bin")) {
207
- console.log()
208
- console.log(pc.yellow(" IMPORTANTE: Adicione ~/.local/bin ao seu PATH"))
209
- console.log(pc.dim(" Adicione ao seu ~/.bashrc ou ~/.zshrc:"))
210
- console.log(pc.dim(" export PATH=\"$HOME/.local/bin:$PATH\""))
211
- }
246
+ console.log(pc.green(` Script lola-gemini criado em ${lolaGeminiScript}`))
212
247
  } else {
213
- console.log(pc.green(" Script lola ja existe"))
248
+ console.log(pc.green(" Script lola-gemini ja existe"))
214
249
  }
215
250
  }
251
+ }
216
252
 
217
- // Instalar MCP lola-memory
218
- await installLolaMemoryMCP()
219
-
220
- // Verificar USER_MEMORY.md
221
- const claudeDir = join(HOME, ".claude")
222
- if (!existsSync(USER_MEMORY)) {
223
- console.log()
224
- console.log(pc.cyan(" Configurando USER_MEMORY.md..."))
225
-
226
- // Pegar info do git automaticamente
227
- const gitUserResult = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" })
228
- const gitEmailResult = Bun.spawnSync(["git", "config", "user.email"], { stdout: "pipe" })
229
-
230
- const gitUser = gitUserResult.stdout.toString().trim() || "Dev"
231
- const gitEmail = gitEmailResult.stdout.toString().trim() || ""
232
- const hostname = process.env.HOSTNAME || process.env.COMPUTERNAME || "local"
233
- const today = new Date().toISOString().split("T")[0]
234
-
235
- await Bun.$`mkdir -p ${claudeDir}`
236
-
237
- const content = `# User Memory
238
-
239
- Memoria persistente para sessoes Claude Code
240
-
241
- ---
242
-
243
- ## Dev
244
-
245
- **Nome:** ${gitUser}
246
- **Email:** ${gitEmail}
247
- **Maquina:** ${hostname}
248
- **Instalacao:** ${today}
249
-
250
- ---
251
-
252
- ## Configuracoes da Lola
253
-
254
- \`\`\`
255
- lola_profile: millennial
256
- \`\`\`
257
-
258
- ---
253
+ async function setupGemini(): Promise<void> {
254
+ // Verificar/instalar Gemini CLI
255
+ if (!hasGeminiCLI()) {
256
+ const installed = await installGeminiCLI()
257
+ if (!installed) return
258
+ } else {
259
+ console.log(pc.green(" Gemini CLI ja instalado"))
260
+ }
259
261
 
260
- ## Ultima Sessao
262
+ // Configurar MCP
263
+ await installGeminiMCP()
261
264
 
262
- (sera preenchido automaticamente)
265
+ // Configurar GEMINI.md
266
+ await installGeminiSystemPrompt()
263
267
 
264
- ---
265
- `
266
- await Bun.write(USER_MEMORY, content)
267
- console.log(pc.green(` USER_MEMORY.md criado para ${gitUser}!`))
268
- }
268
+ // Criar comando lola-gemini
269
+ await createGeminiCommand()
269
270
 
270
271
  console.log()
271
- console.log(pc.green(" Instalacao concluida!"))
272
- console.log()
273
- console.log(pc.bold(" Para usar a Lola:"))
274
- console.log(pc.dim(" lola ") + pc.white("# Iniciar sessao"))
272
+ console.log(pc.green(" Gemini configurado!"))
275
273
  console.log()
276
- console.log(pc.bold(" lola-memory (conhecimento compartilhado):"))
277
- console.log(pc.dim(" remember \"query\" ") + pc.white("# Buscar conhecimento"))
278
- console.log(pc.dim(" learn \"content\" ") + pc.white("# Salvar conhecimento"))
279
- console.log(pc.dim(" memory_stats ") + pc.white("# Ver estatisticas"))
280
- console.log()
281
- console.log(pc.bold(" Para mudar perfil, edite ~/.claude/USER_MEMORY.md:"))
282
- console.log(pc.dim(" lola_profile: millennial|genz|profissional|nerd|chill"))
274
+ console.log(pc.bold(" Para usar:"))
275
+ console.log(pc.dim(" lola-gemini ") + pc.white("# Iniciar sessao com Gemini"))
276
+ console.log(pc.dim(" gemini ") + pc.white("# Gemini puro (sem Lola)"))
283
277
  console.log()
278
+ console.log(pc.dim(" Na primeira execucao, faca login com sua conta Google."))
284
279
  }
285
280
 
281
+
286
282
  async function suggestImprovement(message: string): Promise<void> {
287
283
  if (!message) {
288
284
  console.log(pc.red(" Erro: forneça uma mensagem"))
@@ -394,7 +390,7 @@ async function onboardDev(): Promise<void> {
394
390
  if (!existsSync(LOLA_DIR)) {
395
391
  console.log(pc.yellow(" Lola nao instalada. Instalando primeiro..."))
396
392
  console.log()
397
- await installLola()
393
+ await installLolaBase()
398
394
  console.log()
399
395
  }
400
396
 
@@ -651,11 +647,328 @@ async function runQuiz(): Promise<void> {
651
647
  console.log()
652
648
  }
653
649
 
650
+ async function installInteractive(): Promise<void> {
651
+ console.log()
652
+ console.log(pc.cyan(" Lola - Code Agent da nimbuslab"))
653
+ console.log(pc.dim(" ==============================="))
654
+ console.log()
655
+
656
+ // Detectar CLIs instaladas
657
+ const hasClaude = hasClaudeCLI()
658
+ const hasGemini = hasGeminiCLI()
659
+
660
+ console.log(pc.dim(" Detectando agents..."))
661
+ console.log(pc.dim(` Claude CLI: ${hasClaude ? pc.green("instalado") : pc.yellow("nao encontrado")}`))
662
+ console.log(pc.dim(` Gemini CLI: ${hasGemini ? pc.green("instalado") : pc.yellow("nao encontrado")}`))
663
+ console.log()
664
+
665
+ // Perguntar qual agent configurar
666
+ const agentChoice = await p.select({
667
+ message: "Qual agent deseja configurar?",
668
+ options: [
669
+ {
670
+ value: "all",
671
+ label: "Todos (Recomendado)",
672
+ hint: "Configura Claude e Gemini",
673
+ },
674
+ {
675
+ value: "claude",
676
+ label: "Apenas Claude",
677
+ hint: hasClaude ? "Ja instalado" : "Sera instalado",
678
+ },
679
+ {
680
+ value: "gemini",
681
+ label: "Apenas Gemini",
682
+ hint: hasGemini ? "Ja instalado" : "Sera instalado",
683
+ },
684
+ ],
685
+ })
686
+
687
+ if (p.isCancel(agentChoice)) {
688
+ p.cancel("Instalacao cancelada")
689
+ process.exit(0)
690
+ }
691
+
692
+ const choice = agentChoice as AgentType
693
+
694
+ // Instalar ~/.lola primeiro (necessário para ambos)
695
+ await installLolaBase()
696
+
697
+ // Configurar agents escolhidos
698
+ if (choice === "claude" || choice === "all") {
699
+ console.log()
700
+ console.log(pc.bgBlue(pc.white(" CLAUDE ")))
701
+ await setupClaude()
702
+ }
703
+
704
+ if (choice === "gemini" || choice === "all") {
705
+ console.log()
706
+ console.log(pc.bgMagenta(pc.white(" GEMINI ")))
707
+ await setupGemini()
708
+ }
709
+
710
+ // Resumo final
711
+ console.log()
712
+ console.log(pc.green(" ==============================="))
713
+ console.log(pc.green(" Instalacao concluida!"))
714
+ console.log(pc.green(" ==============================="))
715
+ console.log()
716
+
717
+ if (choice === "claude" || choice === "all") {
718
+ console.log(pc.dim(" lola ") + pc.white("# Claude com Lola"))
719
+ }
720
+ if (choice === "gemini" || choice === "all") {
721
+ console.log(pc.dim(" lola-gemini ") + pc.white("# Gemini com Lola"))
722
+ }
723
+ console.log()
724
+ console.log(pc.bold(" lola-memory (compartilhado entre agents):"))
725
+ console.log(pc.dim(" remember, learn, memory_stats"))
726
+ console.log()
727
+ }
728
+
729
+ async function installLolaBase(): Promise<void> {
730
+ console.log()
731
+ console.log(pc.cyan(" Instalando base Lola (~/.lola)..."))
732
+
733
+ const isUpdate = existsSync(LOLA_DIR)
734
+
735
+ if (isUpdate) {
736
+ console.log(pc.dim(` Lola ja instalada em ${LOLA_DIR}`))
737
+ console.log(pc.dim(" Atualizando..."))
738
+
739
+ // Verificar se tem mudancas locais
740
+ const statusCheck = Bun.spawnSync(["git", "status", "--porcelain"], {
741
+ cwd: LOLA_DIR,
742
+ stdout: "pipe",
743
+ })
744
+ const hasLocalChanges = statusCheck.stdout.toString().trim().length > 0
745
+
746
+ // Stash se tiver mudancas locais
747
+ if (hasLocalChanges) {
748
+ console.log(pc.dim(" Salvando mudancas locais..."))
749
+ Bun.spawnSync(["git", "stash", "--quiet"], {
750
+ cwd: LOLA_DIR,
751
+ stdout: "pipe",
752
+ stderr: "pipe",
753
+ })
754
+ }
755
+
756
+ // Pull
757
+ const result = Bun.spawnSync(["git", "pull", "--quiet"], {
758
+ cwd: LOLA_DIR,
759
+ stdout: "inherit",
760
+ stderr: "inherit",
761
+ })
762
+
763
+ // Restaurar mudancas locais se tinha
764
+ if (hasLocalChanges) {
765
+ console.log(pc.dim(" Restaurando mudancas locais..."))
766
+ const stashPop = Bun.spawnSync(["git", "stash", "pop", "--quiet"], {
767
+ cwd: LOLA_DIR,
768
+ stdout: "pipe",
769
+ stderr: "pipe",
770
+ })
771
+
772
+ if (stashPop.exitCode !== 0) {
773
+ console.log(pc.yellow(" Aviso: conflito ao restaurar mudancas locais"))
774
+ console.log(pc.dim(" Verifique ~/.lola e resolva manualmente: git stash pop"))
775
+ }
776
+ }
777
+
778
+ if (result.exitCode !== 0) {
779
+ console.log(pc.red(" Erro ao atualizar Lola"))
780
+ process.exit(1)
781
+ }
782
+
783
+ console.log(pc.green(" Atualizado!"))
784
+ } else {
785
+ console.log(pc.dim(` Clonando em ${LOLA_DIR}...`))
786
+
787
+ const result = Bun.spawnSync(["git", "clone", "--quiet", LOLA_REPO, LOLA_DIR], {
788
+ stdout: "inherit",
789
+ stderr: "inherit",
790
+ })
791
+
792
+ if (result.exitCode !== 0) {
793
+ console.log(pc.red(" Erro ao clonar repositorio"))
794
+ console.log(pc.dim(" Verifique se tem acesso ao repo nimbuslab/lola"))
795
+ process.exit(1)
796
+ }
797
+
798
+ console.log(pc.green(" Instalado!"))
799
+ }
800
+ }
801
+
802
+ async function setupClaude(): Promise<void> {
803
+ if (!hasClaudeCLI()) {
804
+ console.log(pc.yellow(" Claude CLI nao encontrado"))
805
+ console.log(pc.dim(" Instale: https://claude.ai/download"))
806
+ console.log(pc.dim(" Depois rode 'nimbus lola install' novamente"))
807
+ return
808
+ }
809
+
810
+ console.log(pc.green(" Claude CLI encontrado"))
811
+
812
+ // Criar comando lola
813
+ const isWindows = process.platform === "win32"
814
+ const lolaAgent = join(LOLA_DIR, "agents", "claude.md")
815
+
816
+ console.log()
817
+ console.log(pc.cyan(" Configurando comando lola..."))
818
+
819
+ if (isWindows) {
820
+ const ps5ProfileDir = join(HOME, "Documents", "WindowsPowerShell")
821
+ const ps7ProfileDir = join(HOME, "Documents", "PowerShell")
822
+ const profileName = "Microsoft.PowerShell_profile.ps1"
823
+
824
+ const lolaFunction = `
825
+ # Lola - Code Agent da nimbuslab
826
+ function lola {
827
+ param([Parameter(ValueFromRemainingArguments=$true)]$args)
828
+ $agent = "$env:USERPROFILE\\.lola\\agents\\claude.md"
829
+ if (Test-Path $agent) {
830
+ claude --append-system-prompt-file $agent @args
831
+ } else {
832
+ Write-Host "Agente Lola nao encontrado. Rode: nimbus lola install"
833
+ }
834
+ }
835
+ `
836
+
837
+ const profiles = [
838
+ { dir: ps5ProfileDir, name: "PowerShell 5.x" },
839
+ { dir: ps7ProfileDir, name: "PowerShell 7+" },
840
+ ]
841
+
842
+ let addedToAny = false
843
+
844
+ for (const { dir, name } of profiles) {
845
+ const profilePath = join(dir, profileName)
846
+
847
+ if (!existsSync(dir)) {
848
+ await Bun.$`mkdir -p ${dir}`
849
+ }
850
+
851
+ let profileContent = ""
852
+ if (existsSync(profilePath)) {
853
+ profileContent = await Bun.file(profilePath).text()
854
+ }
855
+
856
+ if (!profileContent.includes("function lola")) {
857
+ await Bun.write(profilePath, profileContent + lolaFunction)
858
+ console.log(pc.green(` Funcao lola adicionada ao ${name} profile`))
859
+ addedToAny = true
860
+ }
861
+ }
862
+
863
+ if (addedToAny) {
864
+ console.log(pc.yellow(" Reinicie o PowerShell para usar o comando 'lola'"))
865
+ } else {
866
+ console.log(pc.green(" Funcao lola ja existe"))
867
+ }
868
+ } else {
869
+ const binDir = join(HOME, ".local", "bin")
870
+ const lolaScript = join(binDir, "lola")
871
+
872
+ if (!existsSync(lolaScript)) {
873
+ await Bun.$`mkdir -p ${binDir}`
874
+
875
+ const unixScript = `#!/bin/bash
876
+ # lola - Code Agent da nimbuslab
877
+ LOLA_AGENT="${lolaAgent}"
878
+
879
+ if [[ "\$1" == "-h" || "\$1" == "--help" ]]; then
880
+ echo "lola - Code Agent da nimbuslab"
881
+ echo "Uso: lola [args]"
882
+ echo " lola Abre Claude CLI com a Lola"
883
+ echo " lola --resume Resume sessao anterior"
884
+ exit 0
885
+ fi
886
+
887
+ if [[ -f "\$LOLA_AGENT" ]]; then
888
+ exec claude --append-system-prompt-file "\$LOLA_AGENT" "\$@"
889
+ else
890
+ echo "Agente Lola nao encontrado: \$LOLA_AGENT"
891
+ echo "Rode: nimbus lola install"
892
+ exit 1
893
+ fi
894
+ `
895
+ await Bun.write(lolaScript, unixScript)
896
+ await Bun.$`chmod +x ${lolaScript}`
897
+
898
+ console.log(pc.green(` Script lola criado em ${lolaScript}`))
899
+
900
+ const pathEnv = process.env.PATH || ""
901
+ if (!pathEnv.includes(".local/bin")) {
902
+ console.log()
903
+ console.log(pc.yellow(" IMPORTANTE: Adicione ~/.local/bin ao seu PATH"))
904
+ console.log(pc.dim(" export PATH=\"$HOME/.local/bin:$PATH\""))
905
+ }
906
+ } else {
907
+ console.log(pc.green(" Script lola ja existe"))
908
+ }
909
+ }
910
+
911
+ // Instalar MCP lola-memory
912
+ await installLolaMemoryMCP()
913
+
914
+ // Verificar USER_MEMORY.md
915
+ const claudeDir = join(HOME, ".claude")
916
+ if (!existsSync(USER_MEMORY)) {
917
+ console.log()
918
+ console.log(pc.cyan(" Configurando USER_MEMORY.md..."))
919
+
920
+ const gitUserResult = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" })
921
+ const gitEmailResult = Bun.spawnSync(["git", "config", "user.email"], { stdout: "pipe" })
922
+
923
+ const gitUser = gitUserResult.stdout.toString().trim() || "Dev"
924
+ const gitEmail = gitEmailResult.stdout.toString().trim() || ""
925
+ const hostname = process.env.HOSTNAME || process.env.COMPUTERNAME || "local"
926
+ const today = new Date().toISOString().split("T")[0]
927
+
928
+ await Bun.$`mkdir -p ${claudeDir}`
929
+
930
+ const content = `# User Memory
931
+
932
+ Memoria persistente para sessoes Claude Code
933
+
934
+ ---
935
+
936
+ ## Dev
937
+
938
+ **Nome:** ${gitUser}
939
+ **Email:** ${gitEmail}
940
+ **Maquina:** ${hostname}
941
+ **Instalacao:** ${today}
942
+
943
+ ---
944
+
945
+ ## Configuracoes da Lola
946
+
947
+ \`\`\`
948
+ lola_profile: millennial
949
+ \`\`\`
950
+
951
+ ---
952
+
953
+ ## Ultima Sessao
954
+
955
+ (sera preenchido automaticamente)
956
+
957
+ ---
958
+ `
959
+ await Bun.write(USER_MEMORY, content)
960
+ console.log(pc.green(` USER_MEMORY.md criado para ${gitUser}!`))
961
+ }
962
+
963
+ console.log()
964
+ console.log(pc.green(" Claude configurado!"))
965
+ }
966
+
654
967
  export async function lola(args: string[]) {
655
968
  const subcommand = args[0]
656
969
 
657
970
  if (!subcommand || subcommand === "install" || subcommand === "sync") {
658
- await installLola()
971
+ await installInteractive()
659
972
  } else if (subcommand === "onboard") {
660
973
  await onboardDev()
661
974
  } else if (subcommand === "quiz") {