@nimbuslab/cli 0.8.0 → 0.10.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/MIGRATION-ROADMAP.md +201 -0
- package/README.md +77 -64
- package/dist/index.js +614 -20
- package/docs/analyze.md +148 -0
- package/docs/create.md +219 -0
- package/docs/migrate.md +177 -0
- package/docs/package.md +229 -0
- package/docs/upgrade.md +152 -0
- package/package.json +1 -1
- package/src/commands/analyze.ts +210 -0
- package/src/commands/lola.ts +201 -0
- package/src/commands/upgrade.ts +251 -0
- package/src/index.ts +29 -3
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import * as p from "@clack/prompts"
|
|
2
|
+
import pc from "picocolors"
|
|
3
|
+
import { existsSync } from "node:fs"
|
|
4
|
+
import { join } from "node:path"
|
|
5
|
+
|
|
6
|
+
const LOLA_DIR = join(process.env.HOME || "~", ".lola")
|
|
7
|
+
const LOLA_REPO = "git@github.com:nimbuslab/lola.git"
|
|
8
|
+
const USER_MEMORY = join(process.env.HOME || "~", ".claude", "USER_MEMORY.md")
|
|
9
|
+
|
|
10
|
+
async function installLola(): Promise<void> {
|
|
11
|
+
console.log()
|
|
12
|
+
console.log(pc.cyan(" Lola - Code Agent da nimbuslab"))
|
|
13
|
+
console.log(pc.dim(" ==============================="))
|
|
14
|
+
console.log()
|
|
15
|
+
|
|
16
|
+
const isUpdate = existsSync(LOLA_DIR)
|
|
17
|
+
|
|
18
|
+
if (isUpdate) {
|
|
19
|
+
console.log(pc.dim(` Lola ja instalada em ${LOLA_DIR}`))
|
|
20
|
+
console.log(pc.cyan(" Atualizando..."))
|
|
21
|
+
|
|
22
|
+
const result = Bun.spawnSync(["git", "pull", "--quiet"], {
|
|
23
|
+
cwd: LOLA_DIR,
|
|
24
|
+
stdout: "inherit",
|
|
25
|
+
stderr: "inherit",
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
if (result.exitCode !== 0) {
|
|
29
|
+
console.log(pc.red(" Erro ao atualizar Lola"))
|
|
30
|
+
process.exit(1)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log(pc.green(" Atualizado!"))
|
|
34
|
+
} else {
|
|
35
|
+
console.log(pc.cyan(` Instalando Lola em ${LOLA_DIR}...`))
|
|
36
|
+
|
|
37
|
+
const result = Bun.spawnSync(["git", "clone", "--quiet", LOLA_REPO, LOLA_DIR], {
|
|
38
|
+
stdout: "inherit",
|
|
39
|
+
stderr: "inherit",
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (result.exitCode !== 0) {
|
|
43
|
+
console.log(pc.red(" Erro ao clonar repositorio"))
|
|
44
|
+
console.log(pc.dim(" Verifique se tem acesso ao repo nimbuslab/lola"))
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(pc.green(" Instalado!"))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Verificar USER_MEMORY.md
|
|
52
|
+
const claudeDir = join(process.env.HOME || "~", ".claude")
|
|
53
|
+
if (!existsSync(USER_MEMORY)) {
|
|
54
|
+
console.log()
|
|
55
|
+
console.log(pc.cyan(" Criando USER_MEMORY.md..."))
|
|
56
|
+
|
|
57
|
+
await Bun.$`mkdir -p ${claudeDir}`
|
|
58
|
+
|
|
59
|
+
const content = `# User Memory
|
|
60
|
+
|
|
61
|
+
Memoria persistente para sessoes Claude Code
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Configuracoes da Lola
|
|
66
|
+
|
|
67
|
+
\`\`\`
|
|
68
|
+
lola_profile: millennial
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Ultima Sessao
|
|
74
|
+
|
|
75
|
+
(sera preenchido automaticamente)
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
`
|
|
79
|
+
await Bun.write(USER_MEMORY, content)
|
|
80
|
+
console.log(pc.green(" USER_MEMORY.md criado!"))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.log()
|
|
84
|
+
console.log(pc.green(" Instalacao concluida!"))
|
|
85
|
+
console.log()
|
|
86
|
+
console.log(pc.bold(" Para usar a Lola:"))
|
|
87
|
+
console.log(pc.dim(" lola ") + pc.white("# Iniciar sessao"))
|
|
88
|
+
console.log(pc.dim(" lola suggest \"x\" ") + pc.white("# Sugerir melhoria"))
|
|
89
|
+
console.log()
|
|
90
|
+
console.log(pc.bold(" Para mudar perfil, edite ~/.claude/USER_MEMORY.md:"))
|
|
91
|
+
console.log(pc.dim(" lola_profile: millennial|genz|profissional|nerd|chill"))
|
|
92
|
+
console.log()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function suggestImprovement(message: string): Promise<void> {
|
|
96
|
+
if (!message) {
|
|
97
|
+
console.log(pc.red(" Erro: forneça uma mensagem"))
|
|
98
|
+
console.log(pc.dim(" Uso: nimbus lola suggest \"sua sugestao aqui\""))
|
|
99
|
+
process.exit(1)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Verificar gh cli
|
|
103
|
+
const ghCheck = Bun.spawnSync(["which", "gh"])
|
|
104
|
+
if (ghCheck.exitCode !== 0) {
|
|
105
|
+
console.log(pc.red(" Erro: GitHub CLI (gh) nao encontrado"))
|
|
106
|
+
console.log(pc.dim(" Instale: https://cli.github.com"))
|
|
107
|
+
process.exit(1)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Verificar autenticacao
|
|
111
|
+
const authCheck = Bun.spawnSync(["gh", "auth", "status"], {
|
|
112
|
+
stdout: "pipe",
|
|
113
|
+
stderr: "pipe",
|
|
114
|
+
})
|
|
115
|
+
if (authCheck.exitCode !== 0) {
|
|
116
|
+
console.log(pc.red(" Erro: GitHub CLI nao autenticado"))
|
|
117
|
+
console.log(pc.dim(" Execute: gh auth login"))
|
|
118
|
+
process.exit(1)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Pegar info do usuario
|
|
122
|
+
const gitUser = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" })
|
|
123
|
+
const gitEmail = Bun.spawnSync(["git", "config", "user.email"], { stdout: "pipe" })
|
|
124
|
+
|
|
125
|
+
const userName = gitUser.stdout.toString().trim() || "Dev"
|
|
126
|
+
const userEmail = gitEmail.stdout.toString().trim() || ""
|
|
127
|
+
|
|
128
|
+
console.log()
|
|
129
|
+
console.log(pc.cyan(" Criando sugestao..."))
|
|
130
|
+
|
|
131
|
+
const date = new Date().toISOString().split("T")[0]
|
|
132
|
+
const body = `## Sugestao
|
|
133
|
+
|
|
134
|
+
${message}
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
**Enviado por:** ${userName}
|
|
139
|
+
**Email:** ${userEmail}
|
|
140
|
+
**Data:** ${date}
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
*Criado via \`nimbus lola suggest\`*`
|
|
144
|
+
|
|
145
|
+
const title = `Sugestao: ${message.slice(0, 50)}${message.length > 50 ? "..." : ""}`
|
|
146
|
+
|
|
147
|
+
const result = Bun.spawnSync([
|
|
148
|
+
"gh", "issue", "create",
|
|
149
|
+
"--repo", "nimbuslab/lola",
|
|
150
|
+
"--title", title,
|
|
151
|
+
"--body", body,
|
|
152
|
+
"--label", "sugestao",
|
|
153
|
+
], {
|
|
154
|
+
stdout: "inherit",
|
|
155
|
+
stderr: "inherit",
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
if (result.exitCode !== 0) {
|
|
159
|
+
console.log(pc.red(" Erro ao criar issue"))
|
|
160
|
+
process.exit(1)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log()
|
|
164
|
+
console.log(pc.green(" Sugestao enviada! Hugo vai revisar."))
|
|
165
|
+
console.log()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export async function lola(args: string[]) {
|
|
169
|
+
const subcommand = args[0]
|
|
170
|
+
|
|
171
|
+
if (!subcommand || subcommand === "install" || subcommand === "sync") {
|
|
172
|
+
await installLola()
|
|
173
|
+
} else if (subcommand === "suggest") {
|
|
174
|
+
const message = args.slice(1).join(" ")
|
|
175
|
+
await suggestImprovement(message)
|
|
176
|
+
} else if (subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
177
|
+
showLolaHelp()
|
|
178
|
+
} else {
|
|
179
|
+
console.log(pc.red(` Subcomando desconhecido: ${subcommand}`))
|
|
180
|
+
showLolaHelp()
|
|
181
|
+
process.exit(1)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function showLolaHelp() {
|
|
186
|
+
console.log()
|
|
187
|
+
console.log(pc.bold(" Lola - Code Agent da nimbuslab"))
|
|
188
|
+
console.log()
|
|
189
|
+
console.log(pc.bold(" Uso:") + " nimbus lola [subcomando]")
|
|
190
|
+
console.log()
|
|
191
|
+
console.log(pc.bold(" Subcomandos:"))
|
|
192
|
+
console.log(pc.dim(" install ") + pc.white("Instalar/atualizar Lola"))
|
|
193
|
+
console.log(pc.dim(" sync ") + pc.white("Alias para install"))
|
|
194
|
+
console.log(pc.dim(" suggest \"msg\" ") + pc.white("Sugerir melhoria (cria issue)"))
|
|
195
|
+
console.log(pc.dim(" help ") + pc.white("Mostrar esta ajuda"))
|
|
196
|
+
console.log()
|
|
197
|
+
console.log(pc.bold(" Exemplos:"))
|
|
198
|
+
console.log(pc.dim(" $ nimbus lola install"))
|
|
199
|
+
console.log(pc.dim(" $ nimbus lola suggest \"adicionar suporte a X\""))
|
|
200
|
+
console.log()
|
|
201
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import * as p from "@clack/prompts"
|
|
2
|
+
import pc from "picocolors"
|
|
3
|
+
import { analyze } from "./analyze"
|
|
4
|
+
|
|
5
|
+
interface UpgradePlan {
|
|
6
|
+
current: string
|
|
7
|
+
target: string
|
|
8
|
+
breakingChanges: string[]
|
|
9
|
+
steps: string[]
|
|
10
|
+
complexity: "low" | "medium" | "high"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const UPGRADE_PLANS: Record<string, (currentVersion: string) => UpgradePlan | null> = {
|
|
14
|
+
next: (current) => {
|
|
15
|
+
const major = parseInt(current.replace(/[^0-9]/g, "").slice(0, 2))
|
|
16
|
+
if (major >= 16) return null
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
current: current,
|
|
20
|
+
target: "16.x",
|
|
21
|
+
complexity: major < 15 ? "high" : "medium",
|
|
22
|
+
breakingChanges: [
|
|
23
|
+
"next/image: Mudancas na API de otimizacao",
|
|
24
|
+
"Middleware: Novo formato de config",
|
|
25
|
+
"next.config: Algumas opcoes depreciadas",
|
|
26
|
+
"Turbopack: Agora e o bundler padrao",
|
|
27
|
+
],
|
|
28
|
+
steps: [
|
|
29
|
+
"Atualizar next para ^16.0.0",
|
|
30
|
+
"Atualizar react para ^19.0.0",
|
|
31
|
+
"Atualizar react-dom para ^19.0.0",
|
|
32
|
+
"Revisar next.config.ts",
|
|
33
|
+
"Testar build: bun run build",
|
|
34
|
+
"Testar dev: bun dev",
|
|
35
|
+
],
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
react: (current) => {
|
|
40
|
+
if (current.startsWith("19") || current.startsWith("^19")) return null
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
current: current,
|
|
44
|
+
target: "19.x",
|
|
45
|
+
complexity: "medium",
|
|
46
|
+
breakingChanges: [
|
|
47
|
+
"forwardRef: Nao mais necessario, ref e prop regular",
|
|
48
|
+
"useContext: Pode ser substituido por use(Context)",
|
|
49
|
+
"Suspense: Mudancas em fallback behavior",
|
|
50
|
+
"Async components: Novo suporte nativo",
|
|
51
|
+
],
|
|
52
|
+
steps: [
|
|
53
|
+
"Atualizar react para ^19.0.0",
|
|
54
|
+
"Atualizar react-dom para ^19.0.0",
|
|
55
|
+
"Atualizar @types/react para ^19.0.0",
|
|
56
|
+
"Remover forwardRef (usar ref como prop)",
|
|
57
|
+
"Revisar Suspense boundaries",
|
|
58
|
+
"Testar todos os componentes",
|
|
59
|
+
],
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
tailwind: (current) => {
|
|
64
|
+
if (current.startsWith("4") || current.startsWith("^4")) return null
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
current: current,
|
|
68
|
+
target: "4.x",
|
|
69
|
+
complexity: "medium",
|
|
70
|
+
breakingChanges: [
|
|
71
|
+
"Config: Agora e CSS-first (nao mais tailwind.config.js)",
|
|
72
|
+
"@apply: Sintaxe mudou",
|
|
73
|
+
"Cores: Novo sistema de tokens",
|
|
74
|
+
"Plugins: API diferente",
|
|
75
|
+
],
|
|
76
|
+
steps: [
|
|
77
|
+
"Atualizar tailwindcss para ^4.0.0",
|
|
78
|
+
"Converter tailwind.config.js para CSS",
|
|
79
|
+
"Atualizar globals.css com @import 'tailwindcss'",
|
|
80
|
+
"Revisar @apply usages",
|
|
81
|
+
"Atualizar plugins para v4",
|
|
82
|
+
"Testar todas as paginas",
|
|
83
|
+
],
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
bun: () => ({
|
|
88
|
+
current: "pnpm/npm/yarn",
|
|
89
|
+
target: "bun",
|
|
90
|
+
complexity: "low",
|
|
91
|
+
breakingChanges: [
|
|
92
|
+
"Lockfile: Formato diferente (bun.lockb)",
|
|
93
|
+
"Scripts: Alguns podem precisar ajuste",
|
|
94
|
+
"Workspaces: Sintaxe levemente diferente",
|
|
95
|
+
],
|
|
96
|
+
steps: [
|
|
97
|
+
"Remover node_modules",
|
|
98
|
+
"Remover pnpm-lock.yaml / package-lock.json / yarn.lock",
|
|
99
|
+
"Executar: bun install",
|
|
100
|
+
"Atualizar scripts no package.json (npx -> bunx)",
|
|
101
|
+
"Atualizar CI/CD configs",
|
|
102
|
+
"Testar: bun dev, bun build",
|
|
103
|
+
],
|
|
104
|
+
}),
|
|
105
|
+
|
|
106
|
+
drizzle: () => ({
|
|
107
|
+
current: "prisma",
|
|
108
|
+
target: "drizzle",
|
|
109
|
+
complexity: "high",
|
|
110
|
+
breakingChanges: [
|
|
111
|
+
"Schema: Formato TypeScript (nao mais .prisma)",
|
|
112
|
+
"Queries: API completamente diferente",
|
|
113
|
+
"Migrations: Sistema diferente",
|
|
114
|
+
"Relations: Declaracao diferente",
|
|
115
|
+
],
|
|
116
|
+
steps: [
|
|
117
|
+
"Instalar drizzle-orm e drizzle-kit",
|
|
118
|
+
"Converter schema.prisma para drizzle/schema.ts",
|
|
119
|
+
"Configurar drizzle.config.ts",
|
|
120
|
+
"Gerar migrations: bunx drizzle-kit generate",
|
|
121
|
+
"Atualizar todas as queries",
|
|
122
|
+
"Atualizar auth config (se usar)",
|
|
123
|
+
"Remover @prisma/client e prisma",
|
|
124
|
+
"Testar todas as operacoes de banco",
|
|
125
|
+
],
|
|
126
|
+
}),
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function upgrade(args: string[]) {
|
|
130
|
+
const showPlan = args.includes("--plan")
|
|
131
|
+
const target = args.find(a => !a.startsWith("-"))
|
|
132
|
+
|
|
133
|
+
console.log()
|
|
134
|
+
|
|
135
|
+
if (showPlan || !target) {
|
|
136
|
+
// Analyze first
|
|
137
|
+
console.log(pc.cyan(" Analisando projeto para plano de upgrade..."))
|
|
138
|
+
console.log()
|
|
139
|
+
|
|
140
|
+
const analysis = await analyze([".", "--quiet"])
|
|
141
|
+
|
|
142
|
+
console.log(pc.bold(" Upgrades Disponiveis:"))
|
|
143
|
+
console.log()
|
|
144
|
+
|
|
145
|
+
let hasUpgrades = false
|
|
146
|
+
|
|
147
|
+
// Check Next.js
|
|
148
|
+
if (analysis.frameworkVersion && analysis.framework === "nextjs") {
|
|
149
|
+
const planFn = UPGRADE_PLANS["next"]
|
|
150
|
+
if (planFn) {
|
|
151
|
+
const plan = planFn(analysis.frameworkVersion)
|
|
152
|
+
if (plan) {
|
|
153
|
+
hasUpgrades = true
|
|
154
|
+
printUpgradePlan("Next.js", plan)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Check React
|
|
160
|
+
if (analysis.dependencies["react"]) {
|
|
161
|
+
const planFn = UPGRADE_PLANS["react"]
|
|
162
|
+
if (planFn) {
|
|
163
|
+
const plan = planFn(analysis.dependencies["react"])
|
|
164
|
+
if (plan) {
|
|
165
|
+
hasUpgrades = true
|
|
166
|
+
printUpgradePlan("React", plan)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Check Tailwind
|
|
172
|
+
const tailwindDep = analysis.dependencies["tailwindcss"] || analysis.devDependencies["tailwindcss"]
|
|
173
|
+
if (tailwindDep) {
|
|
174
|
+
const planFn = UPGRADE_PLANS["tailwind"]
|
|
175
|
+
if (planFn) {
|
|
176
|
+
const plan = planFn(tailwindDep)
|
|
177
|
+
if (plan) {
|
|
178
|
+
hasUpgrades = true
|
|
179
|
+
printUpgradePlan("Tailwind CSS", plan)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Check package manager
|
|
185
|
+
if (analysis.packageManager !== "bun") {
|
|
186
|
+
const planFn = UPGRADE_PLANS["bun"]
|
|
187
|
+
if (planFn) {
|
|
188
|
+
const plan = planFn("")
|
|
189
|
+
if (plan) {
|
|
190
|
+
hasUpgrades = true
|
|
191
|
+
printUpgradePlan("Package Manager", plan)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check Prisma -> Drizzle
|
|
197
|
+
if (analysis.database === "prisma") {
|
|
198
|
+
const planFn = UPGRADE_PLANS["drizzle"]
|
|
199
|
+
if (planFn) {
|
|
200
|
+
const plan = planFn("")
|
|
201
|
+
if (plan) {
|
|
202
|
+
hasUpgrades = true
|
|
203
|
+
printUpgradePlan("Database", plan)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!hasUpgrades) {
|
|
209
|
+
console.log(pc.green(" Projeto ja esta atualizado!"))
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
console.log()
|
|
213
|
+
console.log(pc.dim(" Para executar um upgrade especifico:"))
|
|
214
|
+
console.log(pc.dim(" nimbus upgrade next"))
|
|
215
|
+
console.log(pc.dim(" nimbus upgrade tailwind"))
|
|
216
|
+
console.log(pc.dim(" nimbus upgrade bun"))
|
|
217
|
+
console.log()
|
|
218
|
+
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Execute specific upgrade
|
|
223
|
+
console.log(pc.yellow(` Upgrade ${target} ainda nao implementado.`))
|
|
224
|
+
console.log(pc.dim(" Por enquanto, siga os passos do --plan manualmente."))
|
|
225
|
+
console.log()
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function printUpgradePlan(name: string, plan: UpgradePlan) {
|
|
229
|
+
const complexityColor = {
|
|
230
|
+
low: pc.green,
|
|
231
|
+
medium: pc.yellow,
|
|
232
|
+
high: pc.red,
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
console.log(` ${pc.bold(name)}`)
|
|
236
|
+
console.log(` ${pc.dim("Atual:")} ${plan.current} ${pc.dim("->")} ${pc.cyan(plan.target)}`)
|
|
237
|
+
console.log(` ${pc.dim("Complexidade:")} ${complexityColor[plan.complexity](plan.complexity)}`)
|
|
238
|
+
console.log()
|
|
239
|
+
|
|
240
|
+
console.log(` ${pc.dim("Breaking Changes:")}`)
|
|
241
|
+
plan.breakingChanges.forEach(bc => {
|
|
242
|
+
console.log(` ${pc.yellow("!")} ${bc}`)
|
|
243
|
+
})
|
|
244
|
+
console.log()
|
|
245
|
+
|
|
246
|
+
console.log(` ${pc.dim("Passos:")}`)
|
|
247
|
+
plan.steps.forEach((step, i) => {
|
|
248
|
+
console.log(` ${pc.dim(`${i + 1}.`)} ${step}`)
|
|
249
|
+
})
|
|
250
|
+
console.log()
|
|
251
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
import * as p from "@clack/prompts"
|
|
4
4
|
import pc from "picocolors"
|
|
5
5
|
import { create } from "./commands/create"
|
|
6
|
+
import { analyze } from "./commands/analyze"
|
|
7
|
+
import { upgrade } from "./commands/upgrade"
|
|
8
|
+
import { lola } from "./commands/lola"
|
|
6
9
|
|
|
7
10
|
const PACKAGE_NAME = "@nimbuslab/cli"
|
|
8
|
-
const CURRENT_VERSION = "0.
|
|
11
|
+
const CURRENT_VERSION = "0.9.0"
|
|
9
12
|
|
|
10
13
|
const LOGO = `
|
|
11
14
|
███╗ ██╗██╗███╗ ███╗██████╗ ██╗ ██╗███████╗
|
|
@@ -74,6 +77,12 @@ async function main() {
|
|
|
74
77
|
|
|
75
78
|
if (!command || command === "create") {
|
|
76
79
|
await create(args.slice(1))
|
|
80
|
+
} else if (command === "analyze") {
|
|
81
|
+
await analyze(args.slice(1))
|
|
82
|
+
} else if (command === "upgrade") {
|
|
83
|
+
await upgrade(args.slice(1))
|
|
84
|
+
} else if (command === "lola") {
|
|
85
|
+
await lola(args.slice(1))
|
|
77
86
|
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
78
87
|
showHelp()
|
|
79
88
|
} else if (command === "version" || command === "--version" || command === "-v") {
|
|
@@ -91,24 +100,41 @@ ${pc.bold("Usage:")} nimbus [command] [options]
|
|
|
91
100
|
|
|
92
101
|
${pc.bold("Commands:")}
|
|
93
102
|
create [name] Create a new project
|
|
103
|
+
analyze [dir] Analyze project stack
|
|
104
|
+
upgrade [target] Upgrade dependencies
|
|
105
|
+
lola [action] Lola - Code Agent
|
|
94
106
|
help Show this help
|
|
95
107
|
version Show version
|
|
96
108
|
|
|
97
109
|
${pc.bold("Templates:")}
|
|
98
110
|
--landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
|
|
99
|
-
--app Web app (Landing + Better Auth +
|
|
111
|
+
--app Web app (Landing + Better Auth + Drizzle)
|
|
100
112
|
--turborepo Monorepo (Turborepo + apps/packages)
|
|
101
113
|
|
|
114
|
+
${pc.bold("Analyze & Upgrade:")}
|
|
115
|
+
analyze . Detect stack and show recommendations
|
|
116
|
+
analyze --json Output as JSON
|
|
117
|
+
upgrade --plan Show upgrade plan
|
|
118
|
+
upgrade next Upgrade Next.js
|
|
119
|
+
upgrade tailwind Upgrade Tailwind CSS
|
|
120
|
+
|
|
102
121
|
${pc.bold("Options:")}
|
|
103
122
|
-y, --yes Accept defaults
|
|
104
123
|
--no-git Don't initialize Git
|
|
105
124
|
--no-install Don't install dependencies
|
|
106
125
|
--template <url> Use custom template
|
|
107
126
|
|
|
127
|
+
${pc.bold("Lola (Code Agent):")}
|
|
128
|
+
lola install Install/update Lola
|
|
129
|
+
lola suggest Suggest improvement (creates issue)
|
|
130
|
+
|
|
108
131
|
${pc.bold("Examples:")}
|
|
109
132
|
${pc.dim("$")} nimbus create my-landing --landing
|
|
110
133
|
${pc.dim("$")} nimbus create my-app --app
|
|
111
|
-
${pc.dim("$")} nimbus
|
|
134
|
+
${pc.dim("$")} nimbus analyze ./my-project
|
|
135
|
+
${pc.dim("$")} nimbus upgrade --plan
|
|
136
|
+
${pc.dim("$")} nimbus lola install
|
|
137
|
+
${pc.dim("$")} nimbus lola suggest "add support for X"
|
|
112
138
|
`)
|
|
113
139
|
}
|
|
114
140
|
|