@nimbuslab/cli 0.17.3 → 1.1.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.
Files changed (3) hide show
  1. package/README.md +27 -0
  2. package/dist/index.js +944 -1116
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -865,10 +865,666 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
865
865
  };
866
866
 
867
867
  // src/commands/create.ts
868
- var import_picocolors3 = __toESM(require_picocolors(), 1);
868
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
869
869
  var {$: $2 } = globalThis.Bun;
870
870
  import { rm, mkdir } from "fs/promises";
871
+ import { join as join2 } from "path";
872
+
873
+ // src/lib/generators/ai-docs.ts
871
874
  import { join } from "path";
875
+ async function generateAIFriendlyDocs(projectPath, config) {
876
+ await generateAgentsFile(projectPath, config);
877
+ await generateLLMsFile(projectPath, config);
878
+ await generateArchitectureDoc(projectPath, config);
879
+ await generateExamplesDoc(projectPath, config);
880
+ await createCompatibilitySymlinks(projectPath);
881
+ }
882
+ async function generateAgentsFile(projectPath, config) {
883
+ const content = `# Project Context for AI Assistants
884
+
885
+ > This file is automatically loaded by Claude Code, Cursor, GitHub Copilot, and other AI coding assistants.
886
+
887
+ ## Project Overview
888
+
889
+ **Name:** ${config.name}
890
+ **Type:** ${config.type}
891
+ **Description:** ${config.description}
892
+
893
+ ## Quick Start
894
+
895
+ \`\`\`bash
896
+ bun install
897
+ bun dev # http://localhost:3000
898
+ bun build # Production build
899
+ bun lint # ESLint
900
+ bun typecheck # TypeScript check
901
+ \`\`\`
902
+
903
+ ## Tech Stack
904
+
905
+ | Category | Technology | Why? |
906
+ |----------|-----------|------|
907
+ | Framework | ${config.stack.framework} | App Router, Turbopack, best DX |
908
+ | Styling | ${config.stack.styling} | Fast, composable, CSS-first |
909
+ | Components | ${config.stack.components} | Copy-paste, zero lock-in |
910
+ ${config.stack.forms ? `| Forms | ${config.stack.forms} | Type-safe validation |
911
+ ` : ""}${config.stack.email ? `| Email | ${config.stack.email} | Transactional emails |
912
+ ` : ""}${config.stack.auth ? `| Auth | ${config.stack.auth} | Secure authentication |
913
+ ` : ""}
914
+ ## Architecture Decisions
915
+
916
+ ### Server vs Client Components
917
+
918
+ **Default: Server Components**
919
+ - Better performance (less JS shipped)
920
+ - SEO-friendly
921
+ - Direct data access
922
+
923
+ **Use Client Components when:**
924
+ - Need \`useState\`/\`useEffect\`
925
+ - Browser APIs (\`localStorage\`, \`window\`)
926
+ - Event handlers (\`onClick\`, \`onChange\`)
927
+ - Third-party libraries that require \`'use client'\`
928
+
929
+ ### File Structure
930
+
931
+ \`\`\`
932
+ app/
933
+ \u251C\u2500\u2500 layout.tsx # Root layout
934
+ \u251C\u2500\u2500 page.tsx # Home page
935
+ ${config.features.contactForm ? `\u251C\u2500\u2500 api/
936
+ \u2502 \u2514\u2500\u2500 contact/ # Form API
937
+ ` : ""}\u2514\u2500\u2500 ...
938
+
939
+ components/
940
+ \u251C\u2500\u2500 ui/ # shadcn/ui components (DON'T EDIT)
941
+ ${config.type === "landing" ? `\u251C\u2500\u2500 sections/ # Landing sections
942
+ ` : ""}${config.type === "app" ? `\u251C\u2500\u2500 dashboard/ # Dashboard components
943
+ ` : ""}\u2514\u2500\u2500 forms/ # Form components
944
+
945
+ lib/
946
+ \u251C\u2500\u2500 utils.ts # Helpers (cn, etc)
947
+ ${config.features.contactForm ? `\u251C\u2500\u2500 validations.ts # Zod schemas
948
+ ` : ""}${config.stack.email ? `\u251C\u2500\u2500 email.ts # Email client
949
+ ` : ""}${config.stack.auth ? `\u251C\u2500\u2500 auth.ts # Auth config
950
+ ` : ""}\u2514\u2500\u2500 ...
951
+ \`\`\`
952
+
953
+ ## Coding Conventions
954
+
955
+ ### Naming
956
+ - Components: \`PascalCase\` (UserProfile.tsx)
957
+ - Files: \`kebab-case\` (user-profile.tsx)
958
+ - Hooks: \`useCamelCase\` (useAuth.ts)
959
+ - Utils: \`camelCase\` (formatDate)
960
+ - Constants: \`SCREAMING_SNAKE_CASE\`
961
+
962
+ ### Imports Order
963
+ \`\`\`typescript
964
+ // 1. External
965
+ import { useState } from 'react'
966
+ import { cn } from '@/lib/utils'
967
+
968
+ // 2. Internal components
969
+ import { Button } from '@/components/ui/button'
970
+
971
+ // 3. Local
972
+ import { schema } from './validations'
973
+
974
+ // 4. Types
975
+ import type { User } from '@/types'
976
+ \`\`\`
977
+
978
+ ### TypeScript
979
+ - Always use \`type\` for objects
980
+ - Use \`interface\` only for extendable contracts
981
+ - Prefer \`const\` over \`let\`
982
+ - Use arrow functions for components
983
+ - Explicit return types for exported functions
984
+
985
+ ## Common Tasks
986
+
987
+ ### Add a new section
988
+ \`\`\`bash
989
+ # 1. Create component
990
+ touch components/sections/pricing.tsx
991
+
992
+ # 2. Add to page
993
+ # app/page.tsx
994
+ import { Pricing } from '@/components/sections/pricing'
995
+ \`\`\`
996
+
997
+ ${config.features.contactForm ? `### Add form validation
998
+ \`\`\`typescript
999
+ // lib/validations.ts
1000
+ export const contactSchema = z.object({
1001
+ email: z.string().email('Email inv\xE1lido'),
1002
+ message: z.string().min(10, 'M\xEDnimo 10 caracteres'),
1003
+ })
1004
+
1005
+ // components/forms/contact-form.tsx
1006
+ const form = useForm<z.infer<typeof contactSchema>>({
1007
+ resolver: zodResolver(contactSchema),
1008
+ })
1009
+ \`\`\`
1010
+
1011
+ ` : ""}${config.stack.email ? `### Send email
1012
+ \`\`\`typescript
1013
+ // app/api/contact/route.ts
1014
+ import { resend } from '@/lib/email'
1015
+
1016
+ await resend.emails.send({
1017
+ from: 'noreply@example.com',
1018
+ to: 'contact@example.com',
1019
+ subject: 'Novo contato',
1020
+ react: ContactEmail({ name, email, message }),
1021
+ })
1022
+ \`\`\`
1023
+
1024
+ ` : ""}## Performance Targets
1025
+
1026
+ | Metric | Target |
1027
+ |--------|--------|
1028
+ | Lighthouse Performance | 95+ |
1029
+ | LCP | < 2.0s |
1030
+ | CLS | < 0.05 |
1031
+ | Bundle Size | < 100KB |
1032
+
1033
+ ## Environment Variables
1034
+
1035
+ \`\`\`env
1036
+ # Required
1037
+ ${config.stack.email ? `RESEND_API_KEY=re_*** # Get: https://resend.com/api-keys
1038
+ ` : ""}${config.stack.auth ? `NEXTAUTH_SECRET=*** # Generate: openssl rand -base64 32
1039
+ ` : ""}
1040
+ # Optional
1041
+ NEXT_PUBLIC_GA_ID=G-*** # Google Analytics
1042
+ \`\`\`
1043
+
1044
+ ## Testing
1045
+
1046
+ \`\`\`bash
1047
+ bun test # Unit tests
1048
+ bun test:e2e # E2E tests
1049
+ bun lint # ESLint
1050
+ bun typecheck # TypeScript
1051
+ \`\`\`
1052
+
1053
+ ## Deployment
1054
+
1055
+ Auto-deploys to Vercel on push to \`main\`.
1056
+
1057
+ **Manual:**
1058
+ \`\`\`bash
1059
+ vercel --prod
1060
+ \`\`\`
1061
+
1062
+ ## Troubleshooting
1063
+
1064
+ ### Build errors
1065
+ - Clear \`.next\`: \`rm -rf .next\`
1066
+ - Clear cache: \`bun install --force\`
1067
+
1068
+ ### Type errors
1069
+ - Restart TS server in IDE
1070
+ - Check \`tsconfig.json\` paths
1071
+
1072
+ ## Resources
1073
+
1074
+ - [Next.js Docs](https://nextjs.org/docs)
1075
+ - [Tailwind Docs](https://tailwindcss.com/docs)
1076
+ - [shadcn/ui](https://ui.shadcn.com)
1077
+ ${config.stack.email ? `- [Resend Docs](https://resend.com/docs)
1078
+ ` : ""}${config.stack.auth ? `- [NextAuth Docs](https://authjs.dev)
1079
+ ` : ""}
1080
+ ---
1081
+
1082
+ *Generated by @nimbuslab/cli*
1083
+ *Last updated: ${new Date().toISOString().split("T")[0]}*
1084
+ `;
1085
+ await Bun.write(join(projectPath, "AGENTS.md"), content);
1086
+ }
1087
+ async function generateLLMsFile(projectPath, config) {
1088
+ const content = `# ${config.name}
1089
+
1090
+ > AI-friendly documentation index
1091
+
1092
+ ## Navigation
1093
+
1094
+ - [Project Overview](./AGENTS.md)
1095
+ - [Architecture](./ARCHITECTURE.md)
1096
+ - [Examples](./EXAMPLES.md)
1097
+ - [Contributing](./CONTRIBUTING.md)
1098
+
1099
+ ## Quick Context
1100
+
1101
+ ${config.description}
1102
+
1103
+ **Stack:** ${config.stack.framework}, ${config.stack.styling}, ${config.stack.components}
1104
+
1105
+ ## Common Questions
1106
+
1107
+ ### How do I start development?
1108
+ \`\`\`bash
1109
+ bun install && bun dev
1110
+ \`\`\`
1111
+
1112
+ ${config.features.contactForm ? `### How do I configure email?
1113
+ See [AGENTS.md#send-email](./AGENTS.md#send-email)
1114
+
1115
+ ` : ""}${config.features.auth ? `### How do I set up authentication?
1116
+ See [AGENTS.md#environment-variables](./AGENTS.md#environment-variables)
1117
+
1118
+ ` : ""}### How do I deploy?
1119
+ Push to \`main\` branch - auto-deploys to Vercel.
1120
+
1121
+ ## File Structure
1122
+
1123
+ \`\`\`
1124
+ app/ # Next.js app router
1125
+ components/ # React components
1126
+ ui/ # shadcn/ui (auto-generated)
1127
+ lib/ # Utilities
1128
+ public/ # Static assets
1129
+ \`\`\`
1130
+
1131
+ ---
1132
+
1133
+ *Auto-generated for LLM consumption*
1134
+ *Learn more: https://mintlify.com/blog/simplifying-docs-with-llms-txt*
1135
+ `;
1136
+ await Bun.write(join(projectPath, "llms.txt"), content);
1137
+ }
1138
+ async function generateArchitectureDoc(projectPath, config) {
1139
+ const content = `# Architecture
1140
+
1141
+ ## Design Decisions
1142
+
1143
+ ### 1. Next.js App Router
1144
+
1145
+ **Why:**
1146
+ - React Server Components by default
1147
+ - Better performance (less client JS)
1148
+ - Simplified data fetching
1149
+ - Native TypeScript support
1150
+
1151
+ **Trade-offs:**
1152
+ - Learning curve vs Pages Router
1153
+ - Some libraries require \`'use client'\`
1154
+
1155
+ ### 2. ${config.stack.styling}
1156
+
1157
+ **Why:**
1158
+ - Zero runtime (pure CSS)
1159
+ - Better performance
1160
+ - Smaller bundle size
1161
+ - Familiar DX
1162
+
1163
+ ${config.type === "landing" ? `### 3. Landing Page Structure
1164
+
1165
+ \`\`\`
1166
+ Hero
1167
+ \u2193
1168
+ Social Proof / Features
1169
+ \u2193
1170
+ How It Works
1171
+ \u2193
1172
+ Testimonials
1173
+ \u2193
1174
+ FAQ
1175
+ \u2193
1176
+ CTA
1177
+ \u2193
1178
+ Footer
1179
+ \`\`\`
1180
+
1181
+ ` : ""}## Data Flow
1182
+
1183
+ \`\`\`
1184
+ User Action
1185
+ \u2193
1186
+ Client Component (onClick)
1187
+ \u2193
1188
+ ${config.features.contactForm ? `Server Action / API Route
1189
+ \u2193
1190
+ Validation (Zod)
1191
+ \u2193
1192
+ ` : ""}${config.stack.email ? `External API (Resend)
1193
+ \u2193
1194
+ ` : ""}Response to client
1195
+ \`\`\`
1196
+
1197
+ ## Performance Strategy
1198
+
1199
+ ### 1. Server Components First
1200
+ - Default to Server Components
1201
+ - Only use Client when needed
1202
+ - Less JavaScript shipped
1203
+
1204
+ ### 2. Image Optimization
1205
+ - Always use \`next/image\`
1206
+ - Lazy loading by default
1207
+ - Modern formats (WebP, AVIF)
1208
+
1209
+ ### 3. Code Splitting
1210
+ - Dynamic imports for heavy components
1211
+ - Route-based splitting (automatic)
1212
+
1213
+ ## Security
1214
+
1215
+ ### 1. Environment Variables
1216
+ - Never commit \`.env\`
1217
+ - Use \`.env.example\` for templates
1218
+ - Validate on startup
1219
+
1220
+ ${config.features.contactForm ? `### 2. Form Validation
1221
+ - Client + Server validation
1222
+ - Zod schemas shared
1223
+ - Sanitize inputs
1224
+
1225
+ ` : ""}### 3. Rate Limiting
1226
+ - API routes protected
1227
+ - Per-IP limits
1228
+
1229
+ ---
1230
+
1231
+ *This document explains WHY, not HOW.*
1232
+ *For HOW, see AGENTS.md*
1233
+ `;
1234
+ await Bun.write(join(projectPath, "ARCHITECTURE.md"), content);
1235
+ }
1236
+ async function generateExamplesDoc(projectPath, config) {
1237
+ const content = `# Examples
1238
+
1239
+ Common tasks with complete code examples.
1240
+
1241
+ ## Adding a New Component
1242
+
1243
+ \`\`\`tsx
1244
+ // components/ui/card.tsx
1245
+ export function Card({ children, className }: {
1246
+ children: React.ReactNode
1247
+ className?: string
1248
+ }) {
1249
+ return (
1250
+ <div className={cn("rounded-lg border p-6", className)}>
1251
+ {children}
1252
+ </div>
1253
+ )
1254
+ }
1255
+ \`\`\`
1256
+
1257
+ ${config.features.contactForm ? `## Form with Validation
1258
+
1259
+ \`\`\`tsx
1260
+ // lib/validations.ts
1261
+ export const contactSchema = z.object({
1262
+ name: z.string().min(2, 'Nome muito curto'),
1263
+ email: z.string().email('Email inv\xE1lido'),
1264
+ message: z.string().min(10, 'Mensagem muito curta'),
1265
+ })
1266
+
1267
+ // components/forms/contact.tsx
1268
+ 'use client'
1269
+
1270
+ import { useForm } from 'react-hook-form'
1271
+ import { zodResolver } from '@hookform/resolvers/zod'
1272
+
1273
+ export function ContactForm() {
1274
+ const form = useForm({
1275
+ resolver: zodResolver(contactSchema),
1276
+ })
1277
+
1278
+ async function onSubmit(data) {
1279
+ const res = await fetch('/api/contact', {
1280
+ method: 'POST',
1281
+ body: JSON.stringify(data),
1282
+ })
1283
+ // Handle response
1284
+ }
1285
+
1286
+ return <form onSubmit={form.handleSubmit(onSubmit)}>...</form>
1287
+ }
1288
+ \`\`\`
1289
+
1290
+ ` : ""}## Adding Animation
1291
+
1292
+ \`\`\`tsx
1293
+ 'use client'
1294
+
1295
+ import { motion } from 'framer-motion'
1296
+
1297
+ export function FadeIn({ children }: { children: React.ReactNode }) {
1298
+ return (
1299
+ <motion.div
1300
+ initial={{ opacity: 0, y: 20 }}
1301
+ animate={{ opacity: 1, y: 0 }}
1302
+ transition={{ duration: 0.5 }}
1303
+ >
1304
+ {children}
1305
+ </motion.div>
1306
+ )
1307
+ }
1308
+ \`\`\`
1309
+
1310
+ ## Environment Variables
1311
+
1312
+ \`\`\`typescript
1313
+ // lib/env.ts
1314
+ import { z } from 'zod'
1315
+
1316
+ const envSchema = z.object({
1317
+ ${config.stack.email ? `RESEND_API_KEY: z.string().min(1),
1318
+ ` : ""}NODE_ENV: z.enum(['development', 'production', 'test']),
1319
+ })
1320
+
1321
+ export const env = envSchema.parse(process.env)
1322
+ \`\`\`
1323
+
1324
+ ---
1325
+
1326
+ *For more examples, see the component files*
1327
+ `;
1328
+ await Bun.write(join(projectPath, "EXAMPLES.md"), content);
1329
+ }
1330
+ async function createCompatibilitySymlinks(projectPath) {
1331
+ const agentsContent = await Bun.file(join(projectPath, "AGENTS.md")).text();
1332
+ await Bun.write(join(projectPath, ".cursorrules"), agentsContent);
1333
+ const githubDir = join(projectPath, ".github");
1334
+ await Bun.$`mkdir -p ${githubDir}`.quiet();
1335
+ await Bun.write(join(githubDir, "copilot-instructions.md"), agentsContent);
1336
+ }
1337
+ // src/lib/generators/interactive-setup.ts
1338
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
1339
+ var SERVICE_INFO = {
1340
+ resend: {
1341
+ name: "Resend",
1342
+ description: "Servi\xE7o de email transacional",
1343
+ pricing: "Gr\xE1tis: 3,000 emails/m\xEAs",
1344
+ signupUrl: "https://resend.com/signup",
1345
+ apiKeyUrl: "https://resend.com/api-keys",
1346
+ keyPrefix: "re_"
1347
+ },
1348
+ googleAnalytics: {
1349
+ name: "Google Analytics",
1350
+ description: "Analytics e m\xE9tricas do site",
1351
+ pricing: "Gr\xE1tis",
1352
+ setupUrl: "https://analytics.google.com",
1353
+ keyFormat: "G-XXXXXXXXXX"
1354
+ }
1355
+ };
1356
+ async function interactiveSetup(templateType) {
1357
+ console.log();
1358
+ console.log(import_picocolors3.default.cyan(" Configura\xE7\xE3o Interativa"));
1359
+ console.log(import_picocolors3.default.dim(" ======================="));
1360
+ console.log();
1361
+ const skipSetup = await ye({
1362
+ message: "Deseja configurar integra\xE7\xF5es agora?",
1363
+ initialValue: true
1364
+ });
1365
+ if (pD(skipSetup) || !skipSetup) {
1366
+ return {
1367
+ features: {
1368
+ contactForm: false,
1369
+ newsletter: false,
1370
+ analytics: false
1371
+ },
1372
+ apiKeys: {},
1373
+ skipSetup: true
1374
+ };
1375
+ }
1376
+ const result = {
1377
+ features: {
1378
+ contactForm: false,
1379
+ newsletter: false,
1380
+ analytics: false
1381
+ },
1382
+ apiKeys: {},
1383
+ skipSetup: false
1384
+ };
1385
+ if (templateType === "landing" || templateType === "app") {
1386
+ const contactFormSetup = await setupContactForm();
1387
+ if (!pD(contactFormSetup)) {
1388
+ result.features.contactForm = contactFormSetup.enabled;
1389
+ if (contactFormSetup.apiKey) {
1390
+ result.apiKeys.resend = contactFormSetup.apiKey;
1391
+ }
1392
+ }
1393
+ }
1394
+ const analyticsSetup = await setupAnalytics();
1395
+ if (!pD(analyticsSetup)) {
1396
+ result.features.analytics = analyticsSetup.enabled;
1397
+ if (analyticsSetup.trackingId) {
1398
+ result.apiKeys.ga = analyticsSetup.trackingId;
1399
+ }
1400
+ }
1401
+ return result;
1402
+ }
1403
+ async function setupContactForm() {
1404
+ console.log();
1405
+ console.log(import_picocolors3.default.cyan(" \uD83D\uDCE7 Formul\xE1rio de Contato"));
1406
+ console.log();
1407
+ const needsForm = await ve({
1408
+ message: "Incluir formul\xE1rio de contato?",
1409
+ options: [
1410
+ { value: "now", label: "Sim, configurar agora" },
1411
+ { value: "later", label: "Sim, mas configurar depois" },
1412
+ { value: "no", label: "N\xE3o incluir" }
1413
+ ]
1414
+ });
1415
+ if (pD(needsForm) || needsForm === "no") {
1416
+ return { enabled: false };
1417
+ }
1418
+ if (needsForm === "later") {
1419
+ return { enabled: true };
1420
+ }
1421
+ showServiceInfo("resend");
1422
+ const apiKey = await he({
1423
+ message: "Resend API Key (deixe vazio para configurar depois):",
1424
+ placeholder: "re_...",
1425
+ validate: (v2) => {
1426
+ if (!v2)
1427
+ return;
1428
+ if (!v2.startsWith(SERVICE_INFO.resend.keyPrefix)) {
1429
+ return `Key inv\xE1lida (deve come\xE7ar com ${SERVICE_INFO.resend.keyPrefix})`;
1430
+ }
1431
+ return;
1432
+ }
1433
+ });
1434
+ if (pD(apiKey)) {
1435
+ return { enabled: true };
1436
+ }
1437
+ return {
1438
+ enabled: true,
1439
+ apiKey: apiKey || undefined
1440
+ };
1441
+ }
1442
+ async function setupAnalytics() {
1443
+ console.log();
1444
+ console.log(import_picocolors3.default.cyan(" \uD83D\uDCCA Analytics"));
1445
+ console.log();
1446
+ const needsAnalytics = await ye({
1447
+ message: "Incluir Google Analytics?",
1448
+ initialValue: false
1449
+ });
1450
+ if (pD(needsAnalytics) || !needsAnalytics) {
1451
+ return { enabled: false };
1452
+ }
1453
+ showServiceInfo("googleAnalytics");
1454
+ const trackingId = await he({
1455
+ message: "Google Analytics Tracking ID (deixe vazio para configurar depois):",
1456
+ placeholder: "G-XXXXXXXXXX",
1457
+ validate: (v2) => {
1458
+ if (!v2)
1459
+ return;
1460
+ if (!v2.startsWith("G-")) {
1461
+ return "ID inv\xE1lido (deve come\xE7ar com G-)";
1462
+ }
1463
+ return;
1464
+ }
1465
+ });
1466
+ if (pD(trackingId)) {
1467
+ return { enabled: false };
1468
+ }
1469
+ return {
1470
+ enabled: true,
1471
+ trackingId: trackingId || undefined
1472
+ };
1473
+ }
1474
+ function showServiceInfo(service) {
1475
+ const info = SERVICE_INFO[service];
1476
+ console.log();
1477
+ console.log(import_picocolors3.default.bold(` ${info.name}`));
1478
+ console.log(import_picocolors3.default.dim(` ${info.description}`));
1479
+ console.log(import_picocolors3.default.dim(` ${info.pricing}`));
1480
+ if ("apiKeyUrl" in info) {
1481
+ console.log(import_picocolors3.default.cyan(` ${info.apiKeyUrl}`));
1482
+ } else if ("setupUrl" in info) {
1483
+ console.log(import_picocolors3.default.cyan(` ${info.setupUrl}`));
1484
+ }
1485
+ console.log();
1486
+ }
1487
+ async function generateEnvFile(projectPath, apiKeys, features) {
1488
+ const lines = [
1489
+ "# ====================================",
1490
+ "# Environment Variables",
1491
+ "# ====================================",
1492
+ "",
1493
+ "# IMPORTANT: Add this file to .gitignore",
1494
+ "# Never commit API keys to version control!",
1495
+ ""
1496
+ ];
1497
+ if (features.contactForm) {
1498
+ lines.push("# Email (Resend)");
1499
+ lines.push("# Get your key: https://resend.com/api-keys");
1500
+ lines.push(`RESEND_API_KEY=${apiKeys.resend || "your_api_key_here"}`);
1501
+ lines.push("");
1502
+ }
1503
+ if (features.analytics) {
1504
+ lines.push("# Analytics (Google Analytics)");
1505
+ lines.push("# Get your ID: https://analytics.google.com");
1506
+ lines.push(`NEXT_PUBLIC_GA_ID=${apiKeys.ga || "G-XXXXXXXXXX"}`);
1507
+ lines.push("");
1508
+ }
1509
+ lines.push("# ====================================");
1510
+ lines.push("# Docs completa em README.md");
1511
+ lines.push("# ====================================");
1512
+ const content = lines.join(`
1513
+ `);
1514
+ await Bun.write(`${projectPath}/.env`, content);
1515
+ const exampleLines = lines.map((line) => {
1516
+ if (line.includes("RESEND_API_KEY=") && !line.startsWith("#")) {
1517
+ return "RESEND_API_KEY=re_your_key_here";
1518
+ }
1519
+ if (line.includes("NEXT_PUBLIC_GA_ID=") && !line.startsWith("#")) {
1520
+ return "NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX";
1521
+ }
1522
+ return line;
1523
+ });
1524
+ await Bun.write(`${projectPath}/.env.example`, exampleLines.join(`
1525
+ `));
1526
+ }
1527
+ // src/commands/create.ts
872
1528
  var AI_CONFIGS = {
873
1529
  claude: {
874
1530
  filename: "CLAUDE.md",
@@ -1068,7 +1724,7 @@ async function ensureRailwayCli() {
1068
1724
  const hasRailway = await $2`${checkCmd} railway`.quiet().then(() => true).catch(() => false);
1069
1725
  if (hasRailway)
1070
1726
  return true;
1071
- console.log(import_picocolors3.default.yellow("Railway CLI not found. Installing..."));
1727
+ console.log(import_picocolors4.default.yellow("Railway CLI not found. Installing..."));
1072
1728
  console.log();
1073
1729
  try {
1074
1730
  if (process.platform === "win32") {
@@ -1076,11 +1732,11 @@ async function ensureRailwayCli() {
1076
1732
  } else {
1077
1733
  await $2`curl -fsSL https://railway.app/install.sh | sh`.quiet();
1078
1734
  }
1079
- console.log(import_picocolors3.default.green("Railway CLI installed successfully!"));
1735
+ console.log(import_picocolors4.default.green("Railway CLI installed successfully!"));
1080
1736
  return true;
1081
1737
  } catch (error) {
1082
- console.log(import_picocolors3.default.red("Error installing Railway CLI."));
1083
- console.log(import_picocolors3.default.dim("Install manually: https://docs.railway.app/guides/cli"));
1738
+ console.log(import_picocolors4.default.red("Error installing Railway CLI."));
1739
+ console.log(import_picocolors4.default.dim("Install manually: https://docs.railway.app/guides/cli"));
1084
1740
  return false;
1085
1741
  }
1086
1742
  }
@@ -1108,38 +1764,38 @@ async function create(args) {
1108
1764
  const hasGit = await $2`${checkCmd} git`.quiet().then(() => true).catch(() => false);
1109
1765
  const hasGh = await $2`${checkCmd} gh`.quiet().then(() => true).catch(() => false);
1110
1766
  if (!hasBun) {
1111
- console.log(import_picocolors3.default.red("Error: Bun not found."));
1112
- console.log(import_picocolors3.default.dim("Install from: https://bun.sh"));
1767
+ console.log(import_picocolors4.default.red("Error: Bun not found."));
1768
+ console.log(import_picocolors4.default.dim("Install from: https://bun.sh"));
1113
1769
  console.log();
1114
1770
  if (process.platform === "win32") {
1115
- console.log(import_picocolors3.default.cyan('powershell -c "irm bun.sh/install.ps1 | iex"'));
1771
+ console.log(import_picocolors4.default.cyan('powershell -c "irm bun.sh/install.ps1 | iex"'));
1116
1772
  } else {
1117
- console.log(import_picocolors3.default.cyan("curl -fsSL https://bun.sh/install | bash"));
1773
+ console.log(import_picocolors4.default.cyan("curl -fsSL https://bun.sh/install | bash"));
1118
1774
  }
1119
1775
  console.log();
1120
1776
  process.exit(1);
1121
1777
  }
1122
1778
  if (!hasGit) {
1123
- console.log(import_picocolors3.default.red("Error: Git not found."));
1124
- console.log(import_picocolors3.default.dim("Install git to continue."));
1779
+ console.log(import_picocolors4.default.red("Error: Git not found."));
1780
+ console.log(import_picocolors4.default.dim("Install git to continue."));
1125
1781
  process.exit(1);
1126
1782
  }
1127
1783
  if (!hasGh) {
1128
- console.log(import_picocolors3.default.dim(" GitHub CLI not found (repo creation will be skipped)"));
1129
- console.log(import_picocolors3.default.dim(" Install from: https://cli.github.com"));
1784
+ console.log(import_picocolors4.default.dim(" GitHub CLI not found (repo creation will be skipped)"));
1785
+ console.log(import_picocolors4.default.dim(" Install from: https://cli.github.com"));
1130
1786
  console.log();
1131
1787
  }
1132
1788
  const hasRailway = await ensureRailwayCli();
1133
1789
  if (hasRailway) {
1134
1790
  const railwayAuth = await isRailwayAuthenticated();
1135
1791
  if (!railwayAuth) {
1136
- console.log(import_picocolors3.default.yellow("Railway CLI not authenticated."));
1137
- console.log(import_picocolors3.default.dim("Run: railway login"));
1792
+ console.log(import_picocolors4.default.yellow("Railway CLI not authenticated."));
1793
+ console.log(import_picocolors4.default.dim("Run: railway login"));
1138
1794
  console.log();
1139
1795
  }
1140
1796
  }
1141
1797
  const { flags, projectName } = parseFlags(args);
1142
- Ie(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" New nimbuslab Project ")));
1798
+ Ie(import_picocolors4.default.bgCyan(import_picocolors4.default.black(" New nimbuslab Project ")));
1143
1799
  let config;
1144
1800
  const hasTypeFlag = flags.landing || flags.app || flags.turborepo || flags.fast || flags.fastPlus || flags.fastTurborepo || flags.core;
1145
1801
  const typeFromFlag = flags.landing ? "landing" : flags.app ? "app" : flags.turborepo ? "turborepo" : flags.fastTurborepo ? "fast+" : flags.fastPlus ? "fast+" : flags.fast ? "fast" : flags.core ? "nimbus-core" : null;
@@ -1168,14 +1824,14 @@ async function create(args) {
1168
1824
  customTemplate: flags.template
1169
1825
  };
1170
1826
  const typeLabel = flags.turborepo ? "fast+ (monorepo)" : config.type;
1171
- console.log(import_picocolors3.default.dim(` Project: ${projectName}`));
1172
- console.log(import_picocolors3.default.dim(` Type: ${typeLabel}`));
1173
- console.log(import_picocolors3.default.dim(` Git: ${config.git ? "yes" : "no"}`));
1174
- console.log(import_picocolors3.default.dim(` Install: ${config.install ? "yes" : "no"}`));
1827
+ console.log(import_picocolors4.default.dim(` Project: ${projectName}`));
1828
+ console.log(import_picocolors4.default.dim(` Type: ${typeLabel}`));
1829
+ console.log(import_picocolors4.default.dim(` Git: ${config.git ? "yes" : "no"}`));
1830
+ console.log(import_picocolors4.default.dim(` Install: ${config.install ? "yes" : "no"}`));
1175
1831
  if (flags.railway)
1176
- console.log(import_picocolors3.default.dim(` Railway: configurar`));
1832
+ console.log(import_picocolors4.default.dim(` Railway: configurar`));
1177
1833
  if (flags.template)
1178
- console.log(import_picocolors3.default.dim(` Template: ${flags.template}`));
1834
+ console.log(import_picocolors4.default.dim(` Template: ${flags.template}`));
1179
1835
  console.log();
1180
1836
  if (flags.railway) {
1181
1837
  const railwayAuthenticated = await isRailwayAuthenticated();
@@ -1185,21 +1841,21 @@ async function create(args) {
1185
1841
  const fastProject = projects.find((p2) => p2.toLowerCase().includes("fast by nimbuslab"));
1186
1842
  if (fastProject) {
1187
1843
  config.railwayProject = fastProject;
1188
- console.log(import_picocolors3.default.green(` Railway: ${fastProject}`));
1844
+ console.log(import_picocolors4.default.green(` Railway: ${fastProject}`));
1189
1845
  }
1190
1846
  } else {
1191
- console.log(import_picocolors3.default.dim(` Creating project Railway: ${projectName}...`));
1847
+ console.log(import_picocolors4.default.dim(` Creating project Railway: ${projectName}...`));
1192
1848
  try {
1193
1849
  const result = await $2`echo "" | railway init -n ${projectName} -w nimbuslab --json`.text();
1194
1850
  const newProject = JSON.parse(result);
1195
1851
  config.railwayProject = newProject.name || projectName;
1196
- console.log(import_picocolors3.default.green(` Railway: ${config.railwayProject} criado`));
1852
+ console.log(import_picocolors4.default.green(` Railway: ${config.railwayProject} criado`));
1197
1853
  } catch {
1198
- console.log(import_picocolors3.default.yellow(` Railway: erro ao criar projeto`));
1854
+ console.log(import_picocolors4.default.yellow(` Railway: erro ao criar projeto`));
1199
1855
  }
1200
1856
  }
1201
1857
  } else {
1202
- console.log(import_picocolors3.default.yellow(` Railway: not authenticated (railway login)`));
1858
+ console.log(import_picocolors4.default.yellow(` Railway: not authenticated (railway login)`));
1203
1859
  }
1204
1860
  console.log();
1205
1861
  }
@@ -1211,13 +1867,58 @@ async function create(args) {
1211
1867
  process.exit(0);
1212
1868
  }
1213
1869
  await createProject(config);
1214
- Se(import_picocolors3.default.green("Project created successfully!"));
1870
+ const finalConfig = config;
1871
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(finalConfig.type);
1872
+ if (isPublicTemplate) {
1873
+ const s = Y2();
1874
+ s.start("Configura\xE7\xE3o de servi\xE7os...");
1875
+ const setupResult = await interactiveSetup(finalConfig.type);
1876
+ s.stop("Configura\xE7\xE3o conclu\xEDda");
1877
+ s.start("Gerando documenta\xE7\xE3o AI-friendly...");
1878
+ try {
1879
+ const generatorConfig = {
1880
+ name: finalConfig.name,
1881
+ type: finalConfig.type,
1882
+ description: finalConfig.githubDescription || `${finalConfig.type} criado com nimbus-cli`,
1883
+ stack: {
1884
+ framework: "Next.js 16 (App Router)",
1885
+ styling: "Tailwind CSS 4",
1886
+ components: "shadcn/ui (default)",
1887
+ forms: setupResult.features.contactForm ? "React Hook Form + Zod" : undefined,
1888
+ email: setupResult.features.contactForm ? "Resend" : undefined,
1889
+ auth: finalConfig.type === "app" ? "Better Auth" : undefined
1890
+ },
1891
+ features: {
1892
+ contactForm: setupResult.features.contactForm,
1893
+ newsletter: setupResult.features.newsletter,
1894
+ analytics: setupResult.features.analytics,
1895
+ auth: finalConfig.type === "app"
1896
+ }
1897
+ };
1898
+ await generateAIFriendlyDocs(finalConfig.name, generatorConfig);
1899
+ s.stop("Documenta\xE7\xE3o AI-friendly gerada");
1900
+ } catch (error) {
1901
+ s.stop("Erro ao gerar documenta\xE7\xE3o AI-friendly");
1902
+ console.log(import_picocolors4.default.dim(" Voc\xEA pode gerar manualmente depois"));
1903
+ }
1904
+ if (!setupResult.skipSetup && (setupResult.apiKeys.resend || setupResult.apiKeys.ga)) {
1905
+ s.start("Gerando arquivos .env...");
1906
+ try {
1907
+ await generateEnvFile(finalConfig.name, setupResult.apiKeys, setupResult.features);
1908
+ s.stop("Arquivos .env gerados (.env e .env.example)");
1909
+ } catch (error) {
1910
+ s.stop("Erro ao gerar .env");
1911
+ console.log(import_picocolors4.default.dim(" Voc\xEA pode criar manualmente depois"));
1912
+ }
1913
+ }
1914
+ }
1915
+ Se(import_picocolors4.default.green("Project created successfully!"));
1215
1916
  showNextSteps(config);
1216
1917
  }
1217
1918
  async function promptConfig(initialName, flags) {
1218
1919
  const { isMember, user } = await isNimbuslabMember();
1219
1920
  const greeting = user ? `Hello, ${user}!` : "Hello!";
1220
- console.log(import_picocolors3.default.dim(` ${greeting}`));
1921
+ console.log(import_picocolors4.default.dim(` ${greeting}`));
1221
1922
  console.log();
1222
1923
  const name = await he({
1223
1924
  message: "Project name:",
@@ -1276,12 +1977,12 @@ async function promptConfig(initialName, flags) {
1276
1977
  return type;
1277
1978
  const isPublicTemplate = ["landing", "app", "turborepo"].includes(type);
1278
1979
  if (!isMember && !isPublicTemplate) {
1279
- console.log(import_picocolors3.default.red("Error: Template available only for nimbuslab members"));
1980
+ console.log(import_picocolors4.default.red("Error: Template available only for nimbuslab members"));
1280
1981
  process.exit(1);
1281
1982
  }
1282
1983
  if (type === "nimbus-core") {
1283
1984
  console.log();
1284
- console.log(import_picocolors3.default.dim(" nimbus-core: Motor para projetos externos (stealth mode)"));
1985
+ console.log(import_picocolors4.default.dim(" nimbus-core: Motor para projetos externos (stealth mode)"));
1285
1986
  console.log();
1286
1987
  const repoOption = await ve({
1287
1988
  message: "Create repository for this project?",
@@ -1496,7 +2197,7 @@ async function promptConfig(initialName, flags) {
1496
2197
  const configItems = infraOptions;
1497
2198
  if (configItems.includes("urls")) {
1498
2199
  console.log();
1499
- console.log(import_picocolors3.default.dim(" Project URLs"));
2200
+ console.log(import_picocolors4.default.dim(" Project URLs"));
1500
2201
  const staging = await he({
1501
2202
  message: "Staging URL:",
1502
2203
  placeholder: defaultStagingUrl,
@@ -1516,7 +2217,7 @@ async function promptConfig(initialName, flags) {
1516
2217
  }
1517
2218
  if (configItems.includes("resend")) {
1518
2219
  console.log();
1519
- console.log(import_picocolors3.default.dim(" Resend (Email)"));
2220
+ console.log(import_picocolors4.default.dim(" Resend (Email)"));
1520
2221
  const resendKey = await he({
1521
2222
  message: "RESEND_API_KEY:",
1522
2223
  placeholder: "re_xxxxxxxxxxxx"
@@ -1545,16 +2246,16 @@ async function promptConfig(initialName, flags) {
1545
2246
  const railwayAuthenticated = await isRailwayAuthenticated();
1546
2247
  if (railwayAuthenticated) {
1547
2248
  console.log();
1548
- console.log(import_picocolors3.default.dim(" Railway"));
2249
+ console.log(import_picocolors4.default.dim(" Railway"));
1549
2250
  const projects = await listRailwayProjects();
1550
2251
  if (type === "fast") {
1551
2252
  const fastProject = projects.find((p2) => p2.toLowerCase().includes("fast by nimbuslab"));
1552
2253
  if (fastProject) {
1553
2254
  railwayProject = fastProject;
1554
- console.log(import_picocolors3.default.green(` Project: ${fastProject} (automatico)`));
2255
+ console.log(import_picocolors4.default.green(` Project: ${fastProject} (automatico)`));
1555
2256
  } else {
1556
- console.log(import_picocolors3.default.yellow(" Project 'Fast by nimbuslab' not found."));
1557
- console.log(import_picocolors3.default.dim(" Configure manually in .env"));
2257
+ console.log(import_picocolors4.default.yellow(" Project 'Fast by nimbuslab' not found."));
2258
+ console.log(import_picocolors4.default.dim(" Configure manually in .env"));
1558
2259
  }
1559
2260
  } else {
1560
2261
  const projectOptions = [
@@ -1570,26 +2271,26 @@ async function promptConfig(initialName, flags) {
1570
2271
  return selectedProject;
1571
2272
  if (selectedProject === "__new__") {
1572
2273
  const projectNameForRailway = name;
1573
- console.log(import_picocolors3.default.dim(` Creating project "${projectNameForRailway}" on Railway...`));
2274
+ console.log(import_picocolors4.default.dim(` Creating project "${projectNameForRailway}" on Railway...`));
1574
2275
  try {
1575
2276
  const result = await $2`echo "" | railway init -n ${projectNameForRailway} -w nimbuslab --json`.text();
1576
2277
  const newProject = JSON.parse(result);
1577
2278
  railwayProject = newProject.name || projectNameForRailway;
1578
- console.log(import_picocolors3.default.green(` Projeto "${railwayProject}" created successfully!`));
1579
- console.log(import_picocolors3.default.dim(` ID: ${newProject.id || "N/A"}`));
2279
+ console.log(import_picocolors4.default.green(` Projeto "${railwayProject}" created successfully!`));
2280
+ console.log(import_picocolors4.default.dim(` ID: ${newProject.id || "N/A"}`));
1580
2281
  } catch (error) {
1581
- console.log(import_picocolors3.default.yellow(" Error creating project via CLI."));
1582
- console.log(import_picocolors3.default.dim(" Create manually at: https://railway.app/new"));
2282
+ console.log(import_picocolors4.default.yellow(" Error creating project via CLI."));
2283
+ console.log(import_picocolors4.default.dim(" Create manually at: https://railway.app/new"));
1583
2284
  }
1584
2285
  } else if (selectedProject !== "__skip__") {
1585
2286
  railwayProject = selectedProject;
1586
- console.log(import_picocolors3.default.green(` Project selected: ${railwayProject}`));
2287
+ console.log(import_picocolors4.default.green(` Project selected: ${railwayProject}`));
1587
2288
  }
1588
2289
  }
1589
2290
  } else {
1590
2291
  console.log();
1591
- console.log(import_picocolors3.default.yellow(" Railway: not authenticated (railway login)"));
1592
- console.log(import_picocolors3.default.dim(" Configure manually in .env"));
2292
+ console.log(import_picocolors4.default.yellow(" Railway: not authenticated (railway login)"));
2293
+ console.log(import_picocolors4.default.dim(" Configure manually in .env"));
1593
2294
  }
1594
2295
  }
1595
2296
  const install = await ye({
@@ -1641,7 +2342,7 @@ async function createProject(config) {
1641
2342
  } else {
1642
2343
  await $2`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet();
1643
2344
  }
1644
- await rm(join(config.name, ".git"), { recursive: true, force: true });
2345
+ await rm(join2(config.name, ".git"), { recursive: true, force: true });
1645
2346
  s.stop(`Template cloned`);
1646
2347
  } catch (error) {
1647
2348
  s.stop("Error cloning template");
@@ -1662,7 +2363,7 @@ async function createProject(config) {
1662
2363
  s.stop(`Client repo cloned: workspace/${projectName}`);
1663
2364
  } catch (error) {
1664
2365
  s.stop("Error cloning client repo");
1665
- console.log(import_picocolors3.default.dim(" You can clone manually: cd workspace && git clone <url>"));
2366
+ console.log(import_picocolors4.default.dim(" You can clone manually: cd workspace && git clone <url>"));
1666
2367
  }
1667
2368
  }
1668
2369
  if (config.type !== "nimbus-core") {
@@ -1751,7 +2452,7 @@ async function createProject(config) {
1751
2452
  s.stop(`GitHub: ${repoName}`);
1752
2453
  } catch (error) {
1753
2454
  s.stop("Error creating GitHub repository");
1754
- console.log(import_picocolors3.default.dim(" You can create manually with: gh repo create"));
2455
+ console.log(import_picocolors4.default.dim(" You can create manually with: gh repo create"));
1755
2456
  }
1756
2457
  }
1757
2458
  }
@@ -1762,13 +2463,13 @@ async function createProject(config) {
1762
2463
  s.stop(`Railway linkado: ${config.railwayProject}`);
1763
2464
  } catch (error) {
1764
2465
  s.stop("Error linking Railway");
1765
- console.log(import_picocolors3.default.dim(" Run manually: railway link"));
2466
+ console.log(import_picocolors4.default.dim(" Run manually: railway link"));
1766
2467
  }
1767
2468
  }
1768
2469
  if (config.resendApiKey || config.stagingUrl) {
1769
2470
  s.start("Gerando arquivo .env...");
1770
2471
  try {
1771
- const envContent = generateEnvFile(config);
2472
+ const envContent = generateEnvFile2(config);
1772
2473
  await Bun.write(`${config.name}/.env`, envContent);
1773
2474
  s.stop("Arquivo .env criado");
1774
2475
  } catch (error) {
@@ -1785,7 +2486,7 @@ async function createProject(config) {
1785
2486
  }
1786
2487
  }
1787
2488
  }
1788
- function generateEnvFile(config) {
2489
+ function generateEnvFile2(config) {
1789
2490
  const lines = [
1790
2491
  "# Gerado automaticamente pelo nimbus-cli",
1791
2492
  "# Nao commitar este arquivo!",
@@ -1828,58 +2529,58 @@ function showNextSteps(config) {
1828
2529
  const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
1829
2530
  const needsSetup = config.type === "app";
1830
2531
  console.log();
1831
- console.log(import_picocolors3.default.bold("Next steps:"));
2532
+ console.log(import_picocolors4.default.bold("Next steps:"));
1832
2533
  console.log();
1833
- console.log(` ${import_picocolors3.default.cyan("cd")} ${config.name}`);
2534
+ console.log(` ${import_picocolors4.default.cyan("cd")} ${config.name}`);
1834
2535
  if (config.type === "nimbus-core") {
1835
2536
  console.log();
1836
- console.log(import_picocolors3.default.dim(" nimbus-core: Motor para projetos externos"));
2537
+ console.log(import_picocolors4.default.dim(" nimbus-core: Motor para projetos externos"));
1837
2538
  console.log();
1838
- console.log(import_picocolors3.default.dim(" Para usar a Lola:"));
1839
- console.log(` ${import_picocolors3.default.cyan("lola")}`);
2539
+ console.log(import_picocolors4.default.dim(" Para usar a Lola:"));
2540
+ console.log(` ${import_picocolors4.default.cyan("lola")}`);
1840
2541
  console.log();
1841
- console.log(import_picocolors3.default.yellow(" STEALTH MODE: Commits sem mencao a nimbuslab/Lola/IA"));
2542
+ console.log(import_picocolors4.default.yellow(" STEALTH MODE: Commits sem mencao a nimbuslab/Lola/IA"));
1842
2543
  console.log();
1843
2544
  if (config.github) {
1844
2545
  const repoUrl = `https://github.com/nimbuslab/${config.name}`;
1845
- console.log(import_picocolors3.default.green(` GitHub (private): ${repoUrl}`));
2546
+ console.log(import_picocolors4.default.green(` GitHub (private): ${repoUrl}`));
1846
2547
  console.log();
1847
2548
  }
1848
- console.log(import_picocolors3.default.dim(" Docs: See README.md for full instructions"));
2549
+ console.log(import_picocolors4.default.dim(" Docs: See README.md for full instructions"));
1849
2550
  console.log();
1850
2551
  return;
1851
2552
  }
1852
2553
  if (!config.install) {
1853
- console.log(` ${import_picocolors3.default.cyan("bun")} install`);
2554
+ console.log(` ${import_picocolors4.default.cyan("bun")} install`);
1854
2555
  }
1855
2556
  if (!isPublicTemplate || needsSetup) {
1856
- console.log(` ${import_picocolors3.default.cyan("bun")} setup`);
2557
+ console.log(` ${import_picocolors4.default.cyan("bun")} setup`);
1857
2558
  }
1858
- console.log(` ${import_picocolors3.default.cyan("bun")} dev`);
2559
+ console.log(` ${import_picocolors4.default.cyan("bun")} dev`);
1859
2560
  console.log();
1860
2561
  if (needsSetup && isPublicTemplate) {
1861
- console.log(import_picocolors3.default.dim(" bun setup will:"));
1862
- console.log(import_picocolors3.default.dim(" - Start PostgreSQL with Docker"));
1863
- console.log(import_picocolors3.default.dim(" - Run database migrations"));
1864
- console.log(import_picocolors3.default.dim(" - Create demo user (demo@example.com / demo1234)"));
2562
+ console.log(import_picocolors4.default.dim(" bun setup will:"));
2563
+ console.log(import_picocolors4.default.dim(" - Start PostgreSQL with Docker"));
2564
+ console.log(import_picocolors4.default.dim(" - Run database migrations"));
2565
+ console.log(import_picocolors4.default.dim(" - Create demo user (demo@example.com / demo1234)"));
1865
2566
  console.log();
1866
2567
  }
1867
2568
  if (config.git) {
1868
- console.log(import_picocolors3.default.dim(" Git: main -> staging -> develop (current branch)"));
2569
+ console.log(import_picocolors4.default.dim(" Git: main -> staging -> develop (current branch)"));
1869
2570
  if (config.github) {
1870
2571
  const repoUrl = config.githubOrg ? `https://github.com/${config.githubOrg}/${config.name}` : `https://github.com/${config.name}`;
1871
- console.log(import_picocolors3.default.green(` GitHub: ${repoUrl}`));
2572
+ console.log(import_picocolors4.default.green(` GitHub: ${repoUrl}`));
1872
2573
  }
1873
2574
  console.log();
1874
2575
  }
1875
2576
  if (isPublicTemplate) {
1876
2577
  if (config.theme !== "dark") {
1877
- console.log(import_picocolors3.default.dim(` Theme: ${config.theme}`));
2578
+ console.log(import_picocolors4.default.dim(` Theme: ${config.theme}`));
1878
2579
  }
1879
2580
  if (config.aiAssistant) {
1880
2581
  const aiConfig = AI_CONFIGS[config.aiAssistant];
1881
2582
  if (aiConfig) {
1882
- console.log(import_picocolors3.default.dim(` AI config: ${aiConfig.filename}`));
2583
+ console.log(import_picocolors4.default.dim(` AI config: ${aiConfig.filename}`));
1883
2584
  }
1884
2585
  }
1885
2586
  if (config.theme !== "dark" || config.aiAssistant) {
@@ -1887,56 +2588,56 @@ function showNextSteps(config) {
1887
2588
  }
1888
2589
  }
1889
2590
  if (config.type === "fast+") {
1890
- console.log(import_picocolors3.default.dim(" bun setup will:"));
1891
- console.log(import_picocolors3.default.dim(" - Start PostgreSQL with Docker"));
1892
- console.log(import_picocolors3.default.dim(" - Run database migrations"));
1893
- console.log(import_picocolors3.default.dim(" - Create demo user (demo@example.com / demo1234)"));
2591
+ console.log(import_picocolors4.default.dim(" bun setup will:"));
2592
+ console.log(import_picocolors4.default.dim(" - Start PostgreSQL with Docker"));
2593
+ console.log(import_picocolors4.default.dim(" - Run database migrations"));
2594
+ console.log(import_picocolors4.default.dim(" - Create demo user (demo@example.com / demo1234)"));
1894
2595
  console.log();
1895
- console.log(import_picocolors3.default.dim(" Tip: Configure DATABASE_URL and BETTER_AUTH_SECRET in .env"));
2596
+ console.log(import_picocolors4.default.dim(" Tip: Configure DATABASE_URL and BETTER_AUTH_SECRET in .env"));
1896
2597
  if (!config.railwayToken) {
1897
- console.log(import_picocolors3.default.dim(" Railway: Create a project at https://railway.app/new"));
2598
+ console.log(import_picocolors4.default.dim(" Railway: Create a project at https://railway.app/new"));
1898
2599
  }
1899
2600
  console.log();
1900
2601
  }
1901
2602
  if (!isPublicTemplate) {
1902
2603
  if (config.resendApiKey || config.stagingUrl) {
1903
- console.log(import_picocolors3.default.green(" .env configured!"));
2604
+ console.log(import_picocolors4.default.green(" .env configured!"));
1904
2605
  console.log();
1905
2606
  } else {
1906
- console.log(import_picocolors3.default.yellow(" Tip: Configure .env manually or use 'bun setup'."));
2607
+ console.log(import_picocolors4.default.yellow(" Tip: Configure .env manually or use 'bun setup'."));
1907
2608
  console.log();
1908
2609
  }
1909
2610
  }
1910
2611
  if (isPublicTemplate) {
1911
- console.log(import_picocolors3.default.dim(" Open source template (MIT) by nimbuslab"));
1912
- console.log(import_picocolors3.default.dim(` https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`));
2612
+ console.log(import_picocolors4.default.dim(" Open source template (MIT) by nimbuslab"));
2613
+ console.log(import_picocolors4.default.dim(` https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`));
1913
2614
  } else {
1914
- console.log(import_picocolors3.default.dim(" https://github.com/nimbuslab-templates"));
2615
+ console.log(import_picocolors4.default.dim(" https://github.com/nimbuslab-templates"));
1915
2616
  }
1916
2617
  console.log();
1917
2618
  }
1918
2619
 
1919
2620
  // src/commands/analyze.ts
1920
- var import_picocolors4 = __toESM(require_picocolors(), 1);
2621
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
1921
2622
  import { existsSync, readFileSync } from "fs";
1922
- import { join as join2 } from "path";
2623
+ import { join as join3 } from "path";
1923
2624
  function detectPackageManager(dir) {
1924
- if (existsSync(join2(dir, "bun.lockb")))
2625
+ if (existsSync(join3(dir, "bun.lockb")))
1925
2626
  return "bun";
1926
- if (existsSync(join2(dir, "pnpm-lock.yaml")))
2627
+ if (existsSync(join3(dir, "pnpm-lock.yaml")))
1927
2628
  return "pnpm";
1928
- if (existsSync(join2(dir, "yarn.lock")))
2629
+ if (existsSync(join3(dir, "yarn.lock")))
1929
2630
  return "yarn";
1930
- if (existsSync(join2(dir, "package-lock.json")))
2631
+ if (existsSync(join3(dir, "package-lock.json")))
1931
2632
  return "npm";
1932
2633
  return "unknown";
1933
2634
  }
1934
2635
  function detectMonorepo(dir, pkg) {
1935
- if (existsSync(join2(dir, "turbo.json")))
2636
+ if (existsSync(join3(dir, "turbo.json")))
1936
2637
  return "turborepo";
1937
- if (existsSync(join2(dir, "nx.json")))
2638
+ if (existsSync(join3(dir, "nx.json")))
1938
2639
  return "nx";
1939
- if (existsSync(join2(dir, "lerna.json")))
2640
+ if (existsSync(join3(dir, "lerna.json")))
1940
2641
  return "lerna";
1941
2642
  if (pkg.workspaces)
1942
2643
  return "workspaces";
@@ -2041,14 +2742,14 @@ function generateRecommendations(result) {
2041
2742
  }
2042
2743
  async function analyze(args) {
2043
2744
  const targetDir = args[0] || ".";
2044
- const absoluteDir = targetDir.startsWith("/") ? targetDir : join2(process.cwd(), targetDir);
2745
+ const absoluteDir = targetDir.startsWith("/") ? targetDir : join3(process.cwd(), targetDir);
2045
2746
  console.log();
2046
- console.log(import_picocolors4.default.cyan(" Analisando projeto..."));
2747
+ console.log(import_picocolors5.default.cyan(" Analisando projeto..."));
2047
2748
  console.log();
2048
- const pkgPath = join2(absoluteDir, "package.json");
2749
+ const pkgPath = join3(absoluteDir, "package.json");
2049
2750
  if (!existsSync(pkgPath)) {
2050
- console.log(import_picocolors4.default.red(" Erro: package.json nao encontrado"));
2051
- console.log(import_picocolors4.default.dim(` Diretorio: ${absoluteDir}`));
2751
+ console.log(import_picocolors5.default.red(" Erro: package.json nao encontrado"));
2752
+ console.log(import_picocolors5.default.dim(` Diretorio: ${absoluteDir}`));
2052
2753
  process.exit(1);
2053
2754
  }
2054
2755
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
@@ -2065,42 +2766,42 @@ async function analyze(args) {
2065
2766
  monorepo: detectMonorepo(absoluteDir, pkg),
2066
2767
  auth: detectAuth(deps),
2067
2768
  database: detectDatabase(deps),
2068
- typescript: existsSync(join2(absoluteDir, "tsconfig.json")),
2769
+ typescript: existsSync(join3(absoluteDir, "tsconfig.json")),
2069
2770
  dependencies: deps,
2070
2771
  devDependencies: devDeps,
2071
2772
  recommendations: []
2072
2773
  };
2073
2774
  result.recommendations = generateRecommendations(result);
2074
- console.log(import_picocolors4.default.bold(" Projeto: ") + import_picocolors4.default.cyan(result.name) + import_picocolors4.default.dim(` v${result.version}`));
2775
+ console.log(import_picocolors5.default.bold(" Projeto: ") + import_picocolors5.default.cyan(result.name) + import_picocolors5.default.dim(` v${result.version}`));
2075
2776
  console.log();
2076
- console.log(import_picocolors4.default.bold(" Stack Detectada:"));
2077
- console.log(` Framework: ${result.framework ? import_picocolors4.default.green(result.framework + "@" + result.frameworkVersion) : import_picocolors4.default.dim("nenhum")}`);
2078
- console.log(` Styling: ${result.styling.map((s) => import_picocolors4.default.green(s)).join(", ")}`);
2079
- console.log(` Package Manager: ${result.packageManager === "bun" ? import_picocolors4.default.green(result.packageManager) : import_picocolors4.default.yellow(result.packageManager)}`);
2080
- console.log(` TypeScript: ${result.typescript ? import_picocolors4.default.green("sim") : import_picocolors4.default.dim("nao")}`);
2081
- console.log(` Monorepo: ${result.monorepo ? import_picocolors4.default.green(result.monorepo) : import_picocolors4.default.dim("nao")}`);
2082
- console.log(` Auth: ${result.auth ? import_picocolors4.default.green(result.auth) : import_picocolors4.default.dim("nenhum")}`);
2083
- console.log(` Database: ${result.database ? import_picocolors4.default.green(result.database) : import_picocolors4.default.dim("nenhum")}`);
2777
+ console.log(import_picocolors5.default.bold(" Stack Detectada:"));
2778
+ console.log(` Framework: ${result.framework ? import_picocolors5.default.green(result.framework + "@" + result.frameworkVersion) : import_picocolors5.default.dim("nenhum")}`);
2779
+ console.log(` Styling: ${result.styling.map((s) => import_picocolors5.default.green(s)).join(", ")}`);
2780
+ console.log(` Package Manager: ${result.packageManager === "bun" ? import_picocolors5.default.green(result.packageManager) : import_picocolors5.default.yellow(result.packageManager)}`);
2781
+ console.log(` TypeScript: ${result.typescript ? import_picocolors5.default.green("sim") : import_picocolors5.default.dim("nao")}`);
2782
+ console.log(` Monorepo: ${result.monorepo ? import_picocolors5.default.green(result.monorepo) : import_picocolors5.default.dim("nao")}`);
2783
+ console.log(` Auth: ${result.auth ? import_picocolors5.default.green(result.auth) : import_picocolors5.default.dim("nenhum")}`);
2784
+ console.log(` Database: ${result.database ? import_picocolors5.default.green(result.database) : import_picocolors5.default.dim("nenhum")}`);
2084
2785
  console.log();
2085
2786
  if (result.recommendations.length > 0) {
2086
- console.log(import_picocolors4.default.bold(" Recomendacoes:"));
2787
+ console.log(import_picocolors5.default.bold(" Recomendacoes:"));
2087
2788
  result.recommendations.forEach((rec, i) => {
2088
- console.log(import_picocolors4.default.yellow(` ${i + 1}. ${rec}`));
2789
+ console.log(import_picocolors5.default.yellow(` ${i + 1}. ${rec}`));
2089
2790
  });
2090
2791
  console.log();
2091
2792
  } else {
2092
- console.log(import_picocolors4.default.green(" Projeto ja esta na stack recomendada!"));
2793
+ console.log(import_picocolors5.default.green(" Projeto ja esta na stack recomendada!"));
2093
2794
  console.log();
2094
2795
  }
2095
2796
  if (args.includes("--json")) {
2096
- console.log(import_picocolors4.default.dim(" JSON:"));
2797
+ console.log(import_picocolors5.default.dim(" JSON:"));
2097
2798
  console.log(JSON.stringify(result, null, 2));
2098
2799
  }
2099
2800
  return result;
2100
2801
  }
2101
2802
 
2102
2803
  // src/commands/upgrade.ts
2103
- var import_picocolors5 = __toESM(require_picocolors(), 1);
2804
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
2104
2805
  var UPGRADE_PLANS = {
2105
2806
  next: (current) => {
2106
2807
  const major = parseInt(current.replace(/[^0-9]/g, "").slice(0, 2));
@@ -2217,10 +2918,10 @@ async function upgrade(args) {
2217
2918
  const target = args.find((a) => !a.startsWith("-"));
2218
2919
  console.log();
2219
2920
  if (showPlan || !target) {
2220
- console.log(import_picocolors5.default.cyan(" Analisando projeto para plano de upgrade..."));
2921
+ console.log(import_picocolors6.default.cyan(" Analisando projeto para plano de upgrade..."));
2221
2922
  console.log();
2222
2923
  const analysis = await analyze([".", "--quiet"]);
2223
- console.log(import_picocolors5.default.bold(" Upgrades Disponiveis:"));
2924
+ console.log(import_picocolors6.default.bold(" Upgrades Disponiveis:"));
2224
2925
  console.log();
2225
2926
  let hasUpgrades = false;
2226
2927
  if (analysis.frameworkVersion && analysis.framework === "nextjs") {
@@ -2275,44 +2976,44 @@ async function upgrade(args) {
2275
2976
  }
2276
2977
  }
2277
2978
  if (!hasUpgrades) {
2278
- console.log(import_picocolors5.default.green(" Projeto ja esta atualizado!"));
2979
+ console.log(import_picocolors6.default.green(" Projeto ja esta atualizado!"));
2279
2980
  }
2280
2981
  console.log();
2281
- console.log(import_picocolors5.default.dim(" Para executar um upgrade especifico:"));
2282
- console.log(import_picocolors5.default.dim(" nimbus upgrade next"));
2283
- console.log(import_picocolors5.default.dim(" nimbus upgrade tailwind"));
2284
- console.log(import_picocolors5.default.dim(" nimbus upgrade bun"));
2982
+ console.log(import_picocolors6.default.dim(" Para executar um upgrade especifico:"));
2983
+ console.log(import_picocolors6.default.dim(" nimbus upgrade next"));
2984
+ console.log(import_picocolors6.default.dim(" nimbus upgrade tailwind"));
2985
+ console.log(import_picocolors6.default.dim(" nimbus upgrade bun"));
2285
2986
  console.log();
2286
2987
  return;
2287
2988
  }
2288
- console.log(import_picocolors5.default.yellow(` Upgrade ${target} ainda nao implementado.`));
2289
- console.log(import_picocolors5.default.dim(" Por enquanto, siga os passos do --plan manualmente."));
2989
+ console.log(import_picocolors6.default.yellow(` Upgrade ${target} ainda nao implementado.`));
2990
+ console.log(import_picocolors6.default.dim(" Por enquanto, siga os passos do --plan manualmente."));
2290
2991
  console.log();
2291
2992
  }
2292
2993
  function printUpgradePlan(name, plan) {
2293
2994
  const complexityColor = {
2294
- low: import_picocolors5.default.green,
2295
- medium: import_picocolors5.default.yellow,
2296
- high: import_picocolors5.default.red
2995
+ low: import_picocolors6.default.green,
2996
+ medium: import_picocolors6.default.yellow,
2997
+ high: import_picocolors6.default.red
2297
2998
  };
2298
- console.log(` ${import_picocolors5.default.bold(name)}`);
2299
- console.log(` ${import_picocolors5.default.dim("Atual:")} ${plan.current} ${import_picocolors5.default.dim("->")} ${import_picocolors5.default.cyan(plan.target)}`);
2300
- console.log(` ${import_picocolors5.default.dim("Complexidade:")} ${complexityColor[plan.complexity](plan.complexity)}`);
2999
+ console.log(` ${import_picocolors6.default.bold(name)}`);
3000
+ console.log(` ${import_picocolors6.default.dim("Atual:")} ${plan.current} ${import_picocolors6.default.dim("->")} ${import_picocolors6.default.cyan(plan.target)}`);
3001
+ console.log(` ${import_picocolors6.default.dim("Complexidade:")} ${complexityColor[plan.complexity](plan.complexity)}`);
2301
3002
  console.log();
2302
- console.log(` ${import_picocolors5.default.dim("Breaking Changes:")}`);
3003
+ console.log(` ${import_picocolors6.default.dim("Breaking Changes:")}`);
2303
3004
  plan.breakingChanges.forEach((bc) => {
2304
- console.log(` ${import_picocolors5.default.yellow("!")} ${bc}`);
3005
+ console.log(` ${import_picocolors6.default.yellow("!")} ${bc}`);
2305
3006
  });
2306
3007
  console.log();
2307
- console.log(` ${import_picocolors5.default.dim("Passos:")}`);
3008
+ console.log(` ${import_picocolors6.default.dim("Passos:")}`);
2308
3009
  plan.steps.forEach((step, i) => {
2309
- console.log(` ${import_picocolors5.default.dim(`${i + 1}.`)} ${step}`);
3010
+ console.log(` ${import_picocolors6.default.dim(`${i + 1}.`)} ${step}`);
2310
3011
  });
2311
3012
  console.log();
2312
3013
  }
2313
3014
 
2314
3015
  // src/commands/update.ts
2315
- var import_picocolors6 = __toESM(require_picocolors(), 1);
3016
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
2316
3017
  import { execSync, spawnSync } from "child_process";
2317
3018
  var PACKAGE_NAME = "@nimbuslab/cli";
2318
3019
  function hasBunInstall() {
@@ -2448,7 +3149,7 @@ async function update(args) {
2448
3149
  const filteredArgs = args.filter((a) => a !== "--force" && a !== "-f");
2449
3150
  const flag = filteredArgs[0];
2450
3151
  if (flag === "--list" || flag === "-l") {
2451
- Ie(import_picocolors6.default.cyan("Versoes disponiveis"));
3152
+ Ie(import_picocolors7.default.cyan("Versoes disponiveis"));
2452
3153
  const spinner2 = Y2();
2453
3154
  spinner2.start("Buscando versoes...");
2454
3155
  const versions = await getAvailableVersions();
@@ -2460,29 +3161,29 @@ async function update(args) {
2460
3161
  const current = getCurrentVersion();
2461
3162
  const pm2 = detectPackageManager2();
2462
3163
  console.log();
2463
- console.log(import_picocolors6.default.bold("Ultimas 10 versoes:"));
3164
+ console.log(import_picocolors7.default.bold("Ultimas 10 versoes:"));
2464
3165
  versions.slice(0, 10).forEach((v2, i) => {
2465
3166
  const isCurrent = v2 === current;
2466
- const prefix = isCurrent ? import_picocolors6.default.green("-> ") : " ";
2467
- const suffix = isCurrent ? import_picocolors6.default.dim(" (instalada)") : "";
2468
- const isLatest = i === 0 ? import_picocolors6.default.yellow(" (latest)") : "";
3167
+ const prefix = isCurrent ? import_picocolors7.default.green("-> ") : " ";
3168
+ const suffix = isCurrent ? import_picocolors7.default.dim(" (instalada)") : "";
3169
+ const isLatest = i === 0 ? import_picocolors7.default.yellow(" (latest)") : "";
2469
3170
  console.log(`${prefix}${v2}${suffix}${isLatest}`);
2470
3171
  });
2471
3172
  console.log();
2472
- console.log(import_picocolors6.default.dim(`Total: ${versions.length} versoes`));
2473
- console.log(import_picocolors6.default.dim(`Package manager detectado: ${pm2 === "unknown" ? "nenhum" : pm2}`));
2474
- console.log(import_picocolors6.default.dim(`Instalar versao especifica: nimbus update <versao>`));
2475
- console.log(import_picocolors6.default.dim(`Forcar reinstalacao: nimbus update --force`));
3173
+ console.log(import_picocolors7.default.dim(`Total: ${versions.length} versoes`));
3174
+ console.log(import_picocolors7.default.dim(`Package manager detectado: ${pm2 === "unknown" ? "nenhum" : pm2}`));
3175
+ console.log(import_picocolors7.default.dim(`Instalar versao especifica: nimbus update <versao>`));
3176
+ console.log(import_picocolors7.default.dim(`Forcar reinstalacao: nimbus update --force`));
2476
3177
  return;
2477
3178
  }
2478
3179
  const targetVersion = flag || "latest";
2479
3180
  const isSpecificVersion = flag && flag !== "latest" && !flag.startsWith("-");
2480
- Ie(import_picocolors6.default.cyan(`Atualizando ${PACKAGE_NAME}`));
3181
+ Ie(import_picocolors7.default.cyan(`Atualizando ${PACKAGE_NAME}`));
2481
3182
  const spinner = Y2();
2482
3183
  spinner.start("Verificando instalacoes...");
2483
3184
  const cleanup = cleanupDuplicateInstalls();
2484
3185
  if (cleanup.cleaned) {
2485
- spinner.stop(import_picocolors6.default.yellow(cleanup.message));
3186
+ spinner.stop(import_picocolors7.default.yellow(cleanup.message));
2486
3187
  } else {
2487
3188
  spinner.stop("OK");
2488
3189
  }
@@ -2500,7 +3201,7 @@ async function update(args) {
2500
3201
  spinner.stop(`Ultima versao: ${latestVersion || "desconhecida"}`);
2501
3202
  if (!forceFlag && latestVersion && latestVersion === currentVersion) {
2502
3203
  M2.success("Voce ja esta na ultima versao!");
2503
- console.log(import_picocolors6.default.dim(" Use --force para reinstalar"));
3204
+ console.log(import_picocolors7.default.dim(" Use --force para reinstalar"));
2504
3205
  return;
2505
3206
  }
2506
3207
  }
@@ -2538,953 +3239,82 @@ async function update(args) {
2538
3239
  const isWindows = process.platform === "win32";
2539
3240
  if (isWindows) {
2540
3241
  console.log();
2541
- console.log(import_picocolors6.default.yellow(" Reinicie o terminal para aplicar a atualizacao."));
3242
+ console.log(import_picocolors7.default.yellow(" Reinicie o terminal para aplicar a atualizacao."));
2542
3243
  } else if (isUsingFnm()) {
2543
3244
  console.log();
2544
- console.log(import_picocolors6.default.yellow(" fnm detectado - execute para aplicar:"));
2545
- console.log(import_picocolors6.default.cyan(" hash -r"));
2546
- console.log(import_picocolors6.default.dim(" Ou abra um novo terminal."));
3245
+ console.log(import_picocolors7.default.yellow(" fnm detectado - execute para aplicar:"));
3246
+ console.log(import_picocolors7.default.cyan(" hash -r"));
3247
+ console.log(import_picocolors7.default.dim(" Ou abra um novo terminal."));
2547
3248
  }
2548
- Se(import_picocolors6.default.green("Pronto!"));
3249
+ Se(import_picocolors7.default.green("Pronto!"));
2549
3250
  } catch (error) {
2550
3251
  spinner.stop("Erro na atualizacao");
2551
3252
  const err = error;
2552
3253
  M2.error("Falha ao atualizar");
2553
3254
  if (err.stderr) {
2554
- console.log(import_picocolors6.default.dim(err.stderr));
3255
+ console.log(import_picocolors7.default.dim(err.stderr));
2555
3256
  }
2556
3257
  console.log();
2557
- console.log(import_picocolors6.default.yellow("Tente manualmente:"));
3258
+ console.log(import_picocolors7.default.yellow("Tente manualmente:"));
2558
3259
  if (pm === "bun") {
2559
- console.log(import_picocolors6.default.cyan(` bun add -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
3260
+ console.log(import_picocolors7.default.cyan(` bun add -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
2560
3261
  } else {
2561
- console.log(import_picocolors6.default.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
3262
+ console.log(import_picocolors7.default.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
2562
3263
  }
2563
3264
  }
2564
3265
  }
2565
3266
 
2566
- // src/commands/lola.ts
2567
- var import_picocolors7 = __toESM(require_picocolors(), 1);
2568
- import { existsSync as existsSync2 } from "fs";
2569
- import { join as join3 } from "path";
2570
- import { homedir } from "os";
2571
- var HOME = homedir();
2572
- var LOLA_DIR = join3(HOME, ".lola");
2573
- var LOLA_REPO = "git@github.com:nimbuslab/lola.git";
2574
- var USER_MEMORY = join3(HOME, ".claude", "USER_MEMORY.md");
2575
- var CLAUDE_COMMANDS_DIR = join3(HOME, ".claude", "commands");
2576
- var LOLA_COMMANDS_DIR = join3(LOLA_DIR, "commands");
2577
- var LOLA_MEMORY_URL = "https://lola.nimbuslab.com.br/sse";
2578
- var LOLA_MEMORY_NAME = "lola-memory";
2579
- var GEMINI_DIR = join3(HOME, ".gemini");
2580
- var GEMINI_SETTINGS = join3(GEMINI_DIR, "GEMINI.md");
2581
- var CHECK_CMD = process.platform === "win32" ? "where" : "which";
2582
- function hasClaudeCLI() {
2583
- const result = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" });
2584
- return result.exitCode === 0;
2585
- }
2586
- function hasGeminiCLI() {
2587
- const result = Bun.spawnSync([CHECK_CMD, "gemini"], { stdout: "pipe", stderr: "pipe" });
2588
- return result.exitCode === 0;
2589
- }
2590
- async function installLolaMemoryMCP() {
2591
- console.log();
2592
- console.log(import_picocolors7.default.cyan(" Configurando lola-memory MCP..."));
2593
- const claudeCheck = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" });
2594
- if (claudeCheck.exitCode !== 0) {
2595
- console.log(import_picocolors7.default.yellow(" Claude CLI nao encontrado, pulando MCP"));
2596
- console.log(import_picocolors7.default.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"));
2597
- return;
2598
- }
2599
- const mcpList = Bun.spawnSync(["claude", "mcp", "list"], { stdout: "pipe", stderr: "pipe" });
2600
- const mcpOutput = mcpList.stdout.toString();
2601
- if (mcpOutput.includes(LOLA_MEMORY_NAME)) {
2602
- console.log(import_picocolors7.default.green(" MCP lola-memory ja configurado"));
2603
- return;
2604
- }
2605
- console.log(import_picocolors7.default.dim(" Adicionando MCP lola-memory..."));
2606
- const result = Bun.spawnSync([
2607
- "claude",
2608
- "mcp",
2609
- "add",
2610
- "-s",
2611
- "user",
2612
- LOLA_MEMORY_NAME,
2613
- "--",
2614
- "bunx",
2615
- "mcp-remote",
2616
- LOLA_MEMORY_URL
2617
- ], {
2618
- stdout: "inherit",
2619
- stderr: "inherit"
2620
- });
2621
- if (result.exitCode !== 0) {
2622
- console.log(import_picocolors7.default.yellow(" Erro ao adicionar MCP, pode ser adicionado manualmente:"));
2623
- console.log(import_picocolors7.default.dim(` claude mcp add -s user ${LOLA_MEMORY_NAME} -- bunx mcp-remote ${LOLA_MEMORY_URL}`));
2624
- return;
2625
- }
2626
- console.log(import_picocolors7.default.green(" MCP lola-memory instalado!"));
2627
- console.log();
2628
- console.log(import_picocolors7.default.dim(" Comandos disponiveis:"));
2629
- console.log(import_picocolors7.default.dim(' remember "query" - Buscar conhecimento'));
2630
- console.log(import_picocolors7.default.dim(' learn "content" - Salvar conhecimento'));
2631
- console.log(import_picocolors7.default.dim(" memory_stats - Ver estatisticas"));
2632
- }
2633
- async function installLolaCommands() {
2634
- console.log();
2635
- console.log(import_picocolors7.default.cyan(" Instalando comandos da Lola..."));
2636
- if (!existsSync2(LOLA_COMMANDS_DIR)) {
2637
- console.log(import_picocolors7.default.dim(" Pasta de comandos nao encontrada em ~/.lola/commands"));
2638
- return;
2639
- }
2640
- if (!existsSync2(CLAUDE_COMMANDS_DIR)) {
2641
- await Bun.$`mkdir -p ${CLAUDE_COMMANDS_DIR}`;
2642
- }
2643
- const glob = new Bun.Glob("*.md");
2644
- const files = Array.from(glob.scanSync({ cwd: LOLA_COMMANDS_DIR }));
2645
- if (files.length === 0) {
2646
- console.log(import_picocolors7.default.dim(" Nenhum comando encontrado"));
2647
- return;
2648
- }
2649
- let installed = 0;
2650
- for (const file of files) {
2651
- const src = join3(LOLA_COMMANDS_DIR, file);
2652
- const dest = join3(CLAUDE_COMMANDS_DIR, file);
2653
- const content = await Bun.file(src).text();
2654
- await Bun.write(dest, content);
2655
- installed++;
2656
- }
2657
- console.log(import_picocolors7.default.green(` ${installed} comandos instalados!`));
2658
- console.log(import_picocolors7.default.dim(" Comandos: /inbox, /sent, /msg, /conversation"));
2659
- }
2660
- async function installGeminiCLI() {
2661
- console.log();
2662
- console.log(import_picocolors7.default.cyan(" Instalando Gemini CLI..."));
2663
- const result = Bun.spawnSync(["npm", "install", "-g", "@google/gemini-cli"], {
2664
- stdout: "inherit",
2665
- stderr: "inherit"
2666
- });
2667
- if (result.exitCode !== 0) {
2668
- console.log(import_picocolors7.default.red(" Erro ao instalar Gemini CLI"));
2669
- console.log(import_picocolors7.default.dim(" Tente manualmente: npm install -g @google/gemini-cli"));
2670
- return false;
2671
- }
2672
- console.log(import_picocolors7.default.green(" Gemini CLI instalado!"));
2673
- return true;
2674
- }
2675
- async function installGeminiMCP() {
2676
- console.log();
2677
- console.log(import_picocolors7.default.cyan(" Configurando MCP no Gemini..."));
2678
- const settingsPath = join3(GEMINI_DIR, "settings.json");
2679
- if (!existsSync2(GEMINI_DIR)) {
2680
- await Bun.$`mkdir -p ${GEMINI_DIR}`;
2681
- }
2682
- let settings = {};
2683
- if (existsSync2(settingsPath)) {
2684
- try {
2685
- const content = await Bun.file(settingsPath).text();
2686
- settings = JSON.parse(content);
2687
- } catch {}
2688
- }
2689
- const mcpServers = settings.mcpServers || {};
2690
- if (mcpServers[LOLA_MEMORY_NAME]) {
2691
- console.log(import_picocolors7.default.green(" MCP lola-memory ja configurado no Gemini"));
2692
- return;
2693
- }
2694
- mcpServers[LOLA_MEMORY_NAME] = {
2695
- url: LOLA_MEMORY_URL
2696
- };
2697
- settings.mcpServers = mcpServers;
2698
- await Bun.write(settingsPath, JSON.stringify(settings, null, 2));
2699
- console.log(import_picocolors7.default.green(" MCP lola-memory adicionado ao Gemini!"));
2700
- }
2701
- async function installGeminiSystemPrompt() {
2702
- console.log();
2703
- console.log(import_picocolors7.default.cyan(" Configurando GEMINI.md..."));
2704
- if (!existsSync2(GEMINI_DIR)) {
2705
- await Bun.$`mkdir -p ${GEMINI_DIR}`;
2706
- }
2707
- const lolaAgent = join3(LOLA_DIR, "agents", "claude.md");
2708
- if (!existsSync2(lolaAgent)) {
2709
- console.log(import_picocolors7.default.yellow(" Agent Lola nao encontrado"));
2710
- console.log(import_picocolors7.default.dim(" Rode 'nimbus lola install' primeiro"));
2711
- return;
2712
- }
2713
- let content = await Bun.file(lolaAgent).text();
2714
- content = content.replace(/^---[\s\S]*?---\n/, "");
2715
- content = content.replace(/Claude Code/g, "Gemini CLI");
2716
- content = content.replace(/Claude CLI/g, "Gemini CLI");
2717
- const geminiContent = `# Lola - Code Agent (Gemini)
2718
-
2719
- > Este arquivo configura a Lola para o Gemini CLI
2720
- > Gerado automaticamente por: nimbus lola install
2721
-
2722
- ---
2723
-
2724
- ${content}`;
2725
- await Bun.write(GEMINI_SETTINGS, geminiContent);
2726
- console.log(import_picocolors7.default.green(" GEMINI.md criado!"));
2727
- }
2728
- async function createGeminiCommand() {
2729
- const isWindows = process.platform === "win32";
2730
- const lolaAgent = GEMINI_SETTINGS;
2731
- console.log();
2732
- console.log(import_picocolors7.default.cyan(" Configurando comando lola-gemini..."));
2733
- if (isWindows) {
2734
- const ps7ProfileDir = join3(HOME, "Documents", "PowerShell");
2735
- const profileName = "Microsoft.PowerShell_profile.ps1";
2736
- const profilePath = join3(ps7ProfileDir, profileName);
2737
- const lolaGeminiFunction = `
2738
- # Lola (Gemini) - Code Agent da nimbuslab
2739
- function lola-gemini {
2740
- param([Parameter(ValueFromRemainingArguments=$true)]$args)
2741
- gemini @args
2742
- }
2743
- `;
2744
- if (!existsSync2(ps7ProfileDir)) {
2745
- await Bun.$`mkdir -p ${ps7ProfileDir}`;
2746
- }
2747
- let profileContent = "";
2748
- if (existsSync2(profilePath)) {
2749
- profileContent = await Bun.file(profilePath).text();
2750
- }
2751
- if (!profileContent.includes("function lola-gemini")) {
2752
- await Bun.write(profilePath, profileContent + lolaGeminiFunction);
2753
- console.log(import_picocolors7.default.green(" Funcao lola-gemini adicionada ao PowerShell"));
2754
- } else {
2755
- console.log(import_picocolors7.default.green(" Funcao lola-gemini ja existe"));
2756
- }
2757
- } else {
2758
- const binDir = join3(HOME, ".local", "bin");
2759
- const lolaGeminiScript = join3(binDir, "lola-gemini");
2760
- if (!existsSync2(lolaGeminiScript)) {
2761
- await Bun.$`mkdir -p ${binDir}`;
2762
- const unixScript = `#!/bin/bash
2763
- # lola-gemini - Code Agent da nimbuslab (Gemini)
2764
-
2765
- if [[ "$1" == "-h" || "$1" == "--help" ]]; then
2766
- echo "lola-gemini - Code Agent da nimbuslab (Gemini)"
2767
- echo "Uso: lola-gemini [args]"
2768
- echo " lola-gemini Abre Gemini CLI com a Lola"
2769
- exit 0
2770
- fi
2771
-
2772
- exec gemini "$@"
2773
- `;
2774
- await Bun.write(lolaGeminiScript, unixScript);
2775
- await Bun.$`chmod +x ${lolaGeminiScript}`;
2776
- console.log(import_picocolors7.default.green(` Script lola-gemini criado em ${lolaGeminiScript}`));
2777
- } else {
2778
- console.log(import_picocolors7.default.green(" Script lola-gemini ja existe"));
2779
- }
2780
- }
2781
- }
2782
- async function setupGemini() {
2783
- if (!hasGeminiCLI()) {
2784
- const installed = await installGeminiCLI();
2785
- if (!installed)
2786
- return;
2787
- } else {
2788
- console.log(import_picocolors7.default.green(" Gemini CLI ja instalado"));
2789
- }
2790
- await installGeminiMCP();
2791
- await installGeminiSystemPrompt();
2792
- await createGeminiCommand();
2793
- console.log();
2794
- console.log(import_picocolors7.default.green(" Gemini configurado!"));
2795
- console.log();
2796
- console.log(import_picocolors7.default.bold(" Para usar:"));
2797
- console.log(import_picocolors7.default.dim(" lola-gemini ") + import_picocolors7.default.white("# Iniciar sessao com Gemini"));
2798
- console.log(import_picocolors7.default.dim(" gemini ") + import_picocolors7.default.white("# Gemini puro (sem Lola)"));
2799
- console.log();
2800
- console.log(import_picocolors7.default.dim(" Na primeira execucao, faca login com sua conta Google."));
2801
- }
2802
- async function suggestImprovement(message) {
2803
- if (!message) {
2804
- console.log(import_picocolors7.default.red(" Erro: forne\xE7a uma mensagem"));
2805
- console.log(import_picocolors7.default.dim(' Uso: nimbus lola suggest "sua sugestao aqui"'));
2806
- process.exit(1);
2807
- }
2808
- const ghCheck = Bun.spawnSync([CHECK_CMD, "gh"], { stderr: "pipe" });
2809
- if (ghCheck.exitCode !== 0) {
2810
- console.log(import_picocolors7.default.red(" Erro: GitHub CLI (gh) nao encontrado"));
2811
- console.log(import_picocolors7.default.dim(" Instale: https://cli.github.com"));
2812
- process.exit(1);
2813
- }
2814
- const authCheck = Bun.spawnSync(["gh", "auth", "status"], {
2815
- stdout: "pipe",
2816
- stderr: "pipe"
2817
- });
2818
- if (authCheck.exitCode !== 0) {
2819
- console.log(import_picocolors7.default.red(" Erro: GitHub CLI nao autenticado"));
2820
- console.log(import_picocolors7.default.dim(" Execute: gh auth login"));
2821
- process.exit(1);
2822
- }
2823
- const gitUser = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" });
2824
- const gitEmail = Bun.spawnSync(["git", "config", "user.email"], { stdout: "pipe" });
2825
- const userName = gitUser.stdout.toString().trim() || "Dev";
2826
- const userEmail = gitEmail.stdout.toString().trim() || "";
2827
- console.log();
2828
- console.log(import_picocolors7.default.cyan(" Criando sugestao..."));
2829
- const date = new Date().toISOString().split("T")[0];
2830
- const body = `## Sugestao
2831
-
2832
- ${message}
2833
-
2834
- ---
2835
-
2836
- **Enviado por:** ${userName}
2837
- **Email:** ${userEmail}
2838
- **Data:** ${date}
2839
-
2840
- ---
2841
- *Criado via \`nimbus lola suggest\`*`;
2842
- const title = `Sugestao: ${message.slice(0, 50)}${message.length > 50 ? "..." : ""}`;
2843
- const result = Bun.spawnSync([
2844
- "gh",
2845
- "issue",
2846
- "create",
2847
- "--repo",
2848
- "nimbuslab/lola",
2849
- "--title",
2850
- title,
2851
- "--body",
2852
- body,
2853
- "--label",
2854
- "sugestao"
2855
- ], {
2856
- stdout: "inherit",
2857
- stderr: "inherit"
2858
- });
2859
- if (result.exitCode !== 0) {
2860
- console.log(import_picocolors7.default.red(" Erro ao criar issue"));
2861
- process.exit(1);
2862
- }
2863
- console.log();
2864
- console.log(import_picocolors7.default.green(" Sugestao enviada! Hugo vai revisar."));
2865
- console.log();
2866
- }
2867
- var PROFILES = {
2868
- millennial: {
2869
- label: "Millennial",
2870
- hint: "Nerd 90s/2000s, DBZ, Matrix, MSN",
2871
- emoji: ""
2872
- },
2873
- genz: {
2874
- label: "Gen Z",
2875
- hint: "Direto, girias atuais, slay",
2876
- emoji: ""
2877
- },
2878
- profissional: {
2879
- label: "Profissional",
2880
- hint: "100% tecnico, sem referencias",
2881
- emoji: ""
2882
- },
2883
- nerd: {
2884
- label: "Nerd",
2885
- hint: "Star Trek, vim jokes, deep tech",
2886
- emoji: ""
2887
- },
2888
- chill: {
2889
- label: "Chill",
2890
- hint: "Relaxado, vibes cafe, positivo",
2891
- emoji: ""
2892
- }
2893
- };
2894
- async function onboardDev() {
2895
- console.log();
2896
- console.log(import_picocolors7.default.cyan(" Lola - Onboarding"));
2897
- console.log(import_picocolors7.default.dim(" ================="));
2898
- console.log();
2899
- if (!existsSync2(LOLA_DIR)) {
2900
- console.log(import_picocolors7.default.yellow(" Lola nao instalada. Instalando primeiro..."));
2901
- console.log();
2902
- await installLolaBase();
2903
- console.log();
2904
- }
2905
- const gitUser = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" });
2906
- const defaultName = gitUser.stdout.toString().trim() || "";
2907
- Ie(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" Bem-vindo a nimbuslab! ")));
2908
- const devName = await he({
2909
- message: "Qual seu nome?",
2910
- placeholder: "Seu nome",
2911
- initialValue: defaultName,
2912
- validate: (v2) => v2 ? undefined : "Nome e obrigatorio"
2913
- });
2914
- if (pD(devName)) {
2915
- xe("Onboarding cancelado");
2916
- process.exit(0);
2917
- }
2918
- const profile = await ve({
2919
- message: "Qual perfil da Lola voce prefere?",
2920
- options: Object.entries(PROFILES).map(([value, { label, hint }]) => ({
2921
- value,
2922
- label,
2923
- hint
2924
- }))
2925
- });
2926
- if (pD(profile)) {
2927
- xe("Onboarding cancelado");
2928
- process.exit(0);
2929
- }
2930
- const claudeDir = join3(HOME, ".claude");
2931
- await Bun.$`mkdir -p ${claudeDir}`;
2932
- const content = `# User Memory
2933
-
2934
- Memoria persistente para sessoes Claude Code
2935
-
2936
- ---
2937
-
2938
- ## Dev
2939
-
2940
- **Nome:** ${devName}
2941
- **Maquina:** ${process.env.HOSTNAME || "local"}
2942
- **Onboarding:** ${new Date().toISOString().split("T")[0]}
2943
-
2944
- ---
2945
-
2946
- ## Configuracoes da Lola
2947
-
2948
- \`\`\`
2949
- lola_profile: ${profile}
2950
- \`\`\`
2951
-
2952
- ---
2953
-
2954
- ## Ultima Sessao
2955
-
2956
- (sera preenchido automaticamente)
2957
-
2958
- ---
2959
- `;
2960
- await Bun.write(USER_MEMORY, content);
2961
- Se(import_picocolors7.default.green("Onboarding concluido!"));
2962
- console.log();
2963
- console.log(import_picocolors7.default.bold(" Resumo:"));
2964
- console.log(import_picocolors7.default.dim(" Nome: ") + import_picocolors7.default.white(devName));
2965
- console.log(import_picocolors7.default.dim(" Perfil: ") + import_picocolors7.default.white(PROFILES[profile].label));
2966
- console.log();
2967
- console.log(import_picocolors7.default.bold(" Proximos passos:"));
2968
- console.log(import_picocolors7.default.dim(" 1. ") + import_picocolors7.default.white("lola") + import_picocolors7.default.dim(" - Iniciar sessao com a Lola"));
2969
- console.log(import_picocolors7.default.dim(" 2. ") + import_picocolors7.default.white("nimbus create meu-projeto --fast") + import_picocolors7.default.dim(" - Criar projeto"));
2970
- console.log(import_picocolors7.default.dim(" 3. ") + import_picocolors7.default.white('lola suggest "sua ideia"') + import_picocolors7.default.dim(" - Sugerir melhoria"));
2971
- console.log();
2972
- console.log(import_picocolors7.default.dim(" Docs: ~/.lola/README.md"));
2973
- console.log();
2974
- }
2975
- var QUIZ_QUESTIONS = [
2976
- {
2977
- question: "Quais sao os 4 valores da nimbuslab?",
2978
- options: [
2979
- { value: "a", label: "Velocidade, Qualidade, Preco, Entrega" },
2980
- { value: "b", label: "Cocriacao, Inovacao, Evolucao, Humanizacao" },
2981
- { value: "c", label: "Codigo, Design, Marketing, Vendas" },
2982
- { value: "d", label: "Agil, Lean, Scrum, Kanban" }
2983
- ],
2984
- correct: "b",
2985
- explanation: "Cocriacao (construimos junto), Inovacao (buscamos o novo), Evolucao (aprendizado continuo), Humanizacao (tecnologia a servico das pessoas)."
2986
- },
2987
- {
2988
- question: "Quais sao os 4 pilares da filosofia fast?",
2989
- options: [
2990
- { value: "a", label: "Analise, Planejamento, Execucao, Documentacao" },
2991
- { value: "b", label: "Design, Codigo, Teste, Deploy" },
2992
- { value: "c", label: "Briefing, Prototipo, Desenvolvimento, Lancamento" },
2993
- { value: "d", label: "Discovery, Definition, Development, Delivery" }
2994
- ],
2995
- correct: "a",
2996
- explanation: "Filosofia fast: 1. Analise (entender), 2. Planejamento (definir caminho), 3. Execucao (implementar), 4. Documentacao (registrar)."
2997
- },
2998
- {
2999
- question: "Qual package manager a nimbuslab usa como padrao?",
3000
- options: [
3001
- { value: "a", label: "npm" },
3002
- { value: "b", label: "yarn" },
3003
- { value: "c", label: "pnpm" },
3004
- { value: "d", label: "bun" }
3005
- ],
3006
- correct: "d",
3007
- explanation: "Bun e o package manager padrao. Mais rapido e com menos dependencias."
3008
- },
3009
- {
3010
- question: "Qual o estilo padrao do shadcn/ui na nimbuslab?",
3011
- options: [
3012
- { value: "a", label: "new-york" },
3013
- { value: "b", label: "default" },
3014
- { value: "c", label: "minimal" },
3015
- { value: "d", label: "custom" }
3016
- ],
3017
- correct: "b",
3018
- explanation: "Usamos o estilo 'default' do shadcn/ui. Nunca 'new-york'."
3019
- },
3020
- {
3021
- question: "Em projetos externos (stealth mode), a Lola deve:",
3022
- options: [
3023
- { value: "a", label: "Sempre mencionar a nimbuslab nos commits" },
3024
- { value: "b", label: "Usar assinatura 'Co-authored-by: Lola'" },
3025
- { value: "c", label: "Nunca mencionar nimbuslab, Lola ou IA" },
3026
- { value: "d", label: "Adicionar badge da nimbuslab no README" }
3027
- ],
3028
- correct: "c",
3029
- explanation: "Stealth mode: commits sem mencao a nimbuslab/Lola/IA. O cliente nao precisa saber dos bastidores."
3030
- },
3031
- {
3032
- question: "Qual a versao minima do Next.js usada na stack nimbuslab?",
3033
- options: [
3034
- { value: "a", label: "Next.js 13" },
3035
- { value: "b", label: "Next.js 14" },
3036
- { value: "c", label: "Next.js 15" },
3037
- { value: "d", label: "Next.js 16" }
3038
- ],
3039
- correct: "d",
3040
- explanation: "Stack atual: Next.js 16+ com App Router e Turbopack."
3041
- },
3042
- {
3043
- question: "Quem pode aprovar e mergear mudancas no repositorio da Lola?",
3044
- options: [
3045
- { value: "a", label: "Qualquer dev da nimbuslab" },
3046
- { value: "b", label: "Apenas o Hugo" },
3047
- { value: "c", label: "Qualquer pessoa com acesso ao repo" },
3048
- { value: "d", label: "A propria Lola via automacao" }
3049
- ],
3050
- correct: "b",
3051
- explanation: "Apenas o Hugo pode aprovar e mergear. Devs sugerem via 'lola suggest', Hugo revisa."
3052
- },
3053
- {
3054
- question: "Em commits da nimbuslab, qual o idioma correto?",
3055
- options: [
3056
- { value: "a", label: "Ingles" },
3057
- { value: "b", label: "Portugues (BR)" },
3058
- { value: "c", label: "Depende do projeto" },
3059
- { value: "d", label: "Spanglish" }
3060
- ],
3061
- correct: "b",
3062
- explanation: "Commits e PRs em Portugues (BR). Codigo e comentarios em Ingles."
3063
- }
3064
- ];
3065
- async function runQuiz() {
3066
- console.log();
3067
- console.log(import_picocolors7.default.cyan(" Quiz nimbuslab"));
3068
- console.log(import_picocolors7.default.dim(" =============="));
3069
- console.log();
3070
- console.log(import_picocolors7.default.dim(" Teste seus conhecimentos sobre a nimbuslab!"));
3071
- console.log(import_picocolors7.default.dim(" 8 perguntas sobre valores, filosofia e stack."));
3072
- console.log();
3073
- let score = 0;
3074
- const results = [];
3075
- for (let i = 0;i < QUIZ_QUESTIONS.length; i++) {
3076
- const q2 = QUIZ_QUESTIONS[i];
3077
- const answer = await ve({
3078
- message: `${i + 1}. ${q2.question}`,
3079
- options: q2.options
3080
- });
3081
- if (pD(answer)) {
3082
- xe("Quiz cancelado");
3083
- process.exit(0);
3084
- }
3085
- const isCorrect = answer === q2.correct;
3086
- if (isCorrect) {
3087
- score++;
3088
- console.log(import_picocolors7.default.green(" Correto!"));
3089
- } else {
3090
- console.log(import_picocolors7.default.red(" Incorreto."));
3091
- }
3092
- console.log(import_picocolors7.default.dim(` ${q2.explanation}`));
3093
- console.log();
3094
- results.push({
3095
- question: q2.question,
3096
- correct: isCorrect,
3097
- explanation: q2.explanation
3098
- });
3099
- }
3100
- const percentage = Math.round(score / QUIZ_QUESTIONS.length * 100);
3101
- const passed = percentage >= 75;
3102
- console.log(import_picocolors7.default.bold(" Resultado:"));
3103
- console.log();
3104
- if (passed) {
3105
- console.log(import_picocolors7.default.green(` ${score}/${QUIZ_QUESTIONS.length} (${percentage}%) - Aprovado!`));
3106
- console.log();
3107
- if (percentage === 100) {
3108
- console.log(import_picocolors7.default.cyan(" Perfeito! Voce conhece bem a nimbuslab."));
3109
- } else {
3110
- console.log(import_picocolors7.default.cyan(" Muito bem! Voce esta pronto para trabalhar."));
3111
- }
3112
- } else {
3113
- console.log(import_picocolors7.default.yellow(` ${score}/${QUIZ_QUESTIONS.length} (${percentage}%) - Precisa revisar`));
3114
- console.log();
3115
- console.log(import_picocolors7.default.dim(" Revise os conceitos em:"));
3116
- console.log(import_picocolors7.default.dim(" ~/.lola/core/values.md"));
3117
- console.log(import_picocolors7.default.dim(" ~/.lola/core/philosophy.md"));
3118
- console.log(import_picocolors7.default.dim(" ~/.lola/modules/stack.md"));
3119
- }
3120
- console.log();
3121
- }
3122
- async function installInteractive() {
3123
- console.log();
3124
- console.log(import_picocolors7.default.cyan(" Lola - Code Agent da nimbuslab"));
3125
- console.log(import_picocolors7.default.dim(" ==============================="));
3126
- console.log();
3127
- const hasClaude = hasClaudeCLI();
3128
- const hasGemini = hasGeminiCLI();
3129
- console.log(import_picocolors7.default.dim(" Detectando agents..."));
3130
- console.log(import_picocolors7.default.dim(` Claude CLI: ${hasClaude ? import_picocolors7.default.green("instalado") : import_picocolors7.default.yellow("nao encontrado")}`));
3131
- console.log(import_picocolors7.default.dim(` Gemini CLI: ${hasGemini ? import_picocolors7.default.green("instalado") : import_picocolors7.default.yellow("nao encontrado")}`));
3132
- console.log();
3133
- const agentChoice = await ve({
3134
- message: "Qual agent deseja configurar?",
3135
- options: [
3136
- {
3137
- value: "all",
3138
- label: "Todos (Recomendado)",
3139
- hint: "Configura Claude e Gemini"
3140
- },
3141
- {
3142
- value: "claude",
3143
- label: "Apenas Claude",
3144
- hint: hasClaude ? "Ja instalado" : "Sera instalado"
3145
- },
3146
- {
3147
- value: "gemini",
3148
- label: "Apenas Gemini",
3149
- hint: hasGemini ? "Ja instalado" : "Sera instalado"
3150
- }
3151
- ]
3152
- });
3153
- if (pD(agentChoice)) {
3154
- xe("Instalacao cancelada");
3155
- process.exit(0);
3156
- }
3157
- const choice = agentChoice;
3158
- await installLolaBase();
3159
- if (choice === "claude" || choice === "all") {
3160
- console.log();
3161
- console.log(import_picocolors7.default.bgBlue(import_picocolors7.default.white(" CLAUDE ")));
3162
- await setupClaude();
3163
- }
3164
- if (choice === "gemini" || choice === "all") {
3165
- console.log();
3166
- console.log(import_picocolors7.default.bgMagenta(import_picocolors7.default.white(" GEMINI ")));
3167
- await setupGemini();
3168
- }
3169
- console.log();
3170
- console.log(import_picocolors7.default.green(" ==============================="));
3171
- console.log(import_picocolors7.default.green(" Instalacao concluida!"));
3172
- console.log(import_picocolors7.default.green(" ==============================="));
3173
- console.log();
3174
- if (choice === "claude" || choice === "all") {
3175
- console.log(import_picocolors7.default.dim(" lola ") + import_picocolors7.default.white("# Claude com Lola"));
3176
- }
3177
- if (choice === "gemini" || choice === "all") {
3178
- console.log(import_picocolors7.default.dim(" lola-gemini ") + import_picocolors7.default.white("# Gemini com Lola"));
3179
- }
3180
- console.log();
3181
- console.log(import_picocolors7.default.bold(" lola-memory (compartilhado entre agents):"));
3182
- console.log(import_picocolors7.default.dim(" remember, learn, memory_stats"));
3183
- console.log();
3184
- }
3185
- async function installLolaBase() {
3186
- console.log();
3187
- console.log(import_picocolors7.default.cyan(" Instalando base Lola (~/.lola)..."));
3188
- const isUpdate = existsSync2(LOLA_DIR);
3189
- if (isUpdate) {
3190
- console.log(import_picocolors7.default.dim(` Lola ja instalada em ${LOLA_DIR}`));
3191
- console.log(import_picocolors7.default.dim(" Atualizando..."));
3192
- const statusCheck = Bun.spawnSync(["git", "status", "--porcelain"], {
3193
- cwd: LOLA_DIR,
3194
- stdout: "pipe"
3195
- });
3196
- const hasLocalChanges = statusCheck.stdout.toString().trim().length > 0;
3197
- if (hasLocalChanges) {
3198
- console.log(import_picocolors7.default.dim(" Salvando mudancas locais..."));
3199
- Bun.spawnSync(["git", "stash", "--quiet"], {
3200
- cwd: LOLA_DIR,
3201
- stdout: "pipe",
3202
- stderr: "pipe"
3203
- });
3204
- }
3205
- const result = Bun.spawnSync(["git", "pull", "--quiet"], {
3206
- cwd: LOLA_DIR,
3207
- stdout: "inherit",
3208
- stderr: "inherit"
3209
- });
3210
- if (hasLocalChanges) {
3211
- console.log(import_picocolors7.default.dim(" Restaurando mudancas locais..."));
3212
- const stashPop = Bun.spawnSync(["git", "stash", "pop", "--quiet"], {
3213
- cwd: LOLA_DIR,
3214
- stdout: "pipe",
3215
- stderr: "pipe"
3216
- });
3217
- if (stashPop.exitCode !== 0) {
3218
- console.log(import_picocolors7.default.yellow(" Aviso: conflito ao restaurar mudancas locais"));
3219
- console.log(import_picocolors7.default.dim(" Verifique ~/.lola e resolva manualmente: git stash pop"));
3220
- }
3221
- }
3222
- if (result.exitCode !== 0) {
3223
- console.log(import_picocolors7.default.red(" Erro ao atualizar Lola"));
3224
- process.exit(1);
3225
- }
3226
- console.log(import_picocolors7.default.green(" Atualizado!"));
3227
- } else {
3228
- console.log(import_picocolors7.default.dim(` Clonando em ${LOLA_DIR}...`));
3229
- const result = Bun.spawnSync(["git", "clone", "--quiet", LOLA_REPO, LOLA_DIR], {
3230
- stdout: "inherit",
3231
- stderr: "inherit"
3232
- });
3233
- if (result.exitCode !== 0) {
3234
- console.log(import_picocolors7.default.red(" Erro ao clonar repositorio"));
3235
- console.log(import_picocolors7.default.dim(" Verifique se tem acesso ao repo nimbuslab/lola"));
3236
- process.exit(1);
3237
- }
3238
- console.log(import_picocolors7.default.green(" Instalado!"));
3239
- }
3240
- }
3241
- async function setupClaude() {
3242
- if (!hasClaudeCLI()) {
3243
- console.log(import_picocolors7.default.yellow(" Claude CLI nao encontrado"));
3244
- console.log(import_picocolors7.default.dim(" Instale: https://claude.ai/download"));
3245
- console.log(import_picocolors7.default.dim(" Depois rode 'nimbus lola install' novamente"));
3246
- return;
3247
- }
3248
- console.log(import_picocolors7.default.green(" Claude CLI encontrado"));
3249
- const isWindows = process.platform === "win32";
3250
- const lolaAgent = join3(LOLA_DIR, "agents", "claude.md");
3251
- console.log();
3252
- console.log(import_picocolors7.default.cyan(" Configurando comando lola..."));
3253
- if (isWindows) {
3254
- const ps5ProfileDir = join3(HOME, "Documents", "WindowsPowerShell");
3255
- const ps7ProfileDir = join3(HOME, "Documents", "PowerShell");
3256
- const profileName = "Microsoft.PowerShell_profile.ps1";
3257
- const lolaFunction = `
3258
- # Lola - Code Agent da nimbuslab
3259
- function lola {
3260
- param([Parameter(ValueFromRemainingArguments=$true)]$args)
3261
- $agent = "$env:USERPROFILE\\.lola\\agents\\claude.md"
3262
- if (Test-Path $agent) {
3263
- claude --append-system-prompt-file $agent @args
3264
- } else {
3265
- Write-Host "Agente Lola nao encontrado. Rode: nimbus lola install"
3266
- }
3267
- }
3268
- `;
3269
- const profiles = [
3270
- { dir: ps5ProfileDir, name: "PowerShell 5.x" },
3271
- { dir: ps7ProfileDir, name: "PowerShell 7+" }
3272
- ];
3273
- let addedToAny = false;
3274
- for (const { dir, name } of profiles) {
3275
- const profilePath = join3(dir, profileName);
3276
- if (!existsSync2(dir)) {
3277
- await Bun.$`mkdir -p ${dir}`;
3278
- }
3279
- let profileContent = "";
3280
- if (existsSync2(profilePath)) {
3281
- profileContent = await Bun.file(profilePath).text();
3282
- }
3283
- if (!profileContent.includes("function lola")) {
3284
- await Bun.write(profilePath, profileContent + lolaFunction);
3285
- console.log(import_picocolors7.default.green(` Funcao lola adicionada ao ${name} profile`));
3286
- addedToAny = true;
3287
- }
3288
- }
3289
- if (addedToAny) {
3290
- console.log(import_picocolors7.default.yellow(" Reinicie o PowerShell para usar o comando 'lola'"));
3291
- } else {
3292
- console.log(import_picocolors7.default.green(" Funcao lola ja existe"));
3293
- }
3294
- } else {
3295
- const binDir = join3(HOME, ".local", "bin");
3296
- const lolaScript = join3(binDir, "lola");
3297
- if (!existsSync2(lolaScript)) {
3298
- await Bun.$`mkdir -p ${binDir}`;
3299
- const unixScript = `#!/bin/bash
3300
- # lola - Code Agent da nimbuslab
3301
- LOLA_AGENT="${lolaAgent}"
3302
-
3303
- if [[ "$1" == "-h" || "$1" == "--help" ]]; then
3304
- echo "lola - Code Agent da nimbuslab"
3305
- echo "Uso: lola [args]"
3306
- echo " lola Abre Claude CLI com a Lola"
3307
- echo " lola --resume Resume sessao anterior"
3308
- exit 0
3309
- fi
3310
-
3311
- if [[ -f "$LOLA_AGENT" ]]; then
3312
- exec claude --append-system-prompt-file "$LOLA_AGENT" "$@"
3313
- else
3314
- echo "Agente Lola nao encontrado: $LOLA_AGENT"
3315
- echo "Rode: nimbus lola install"
3316
- exit 1
3317
- fi
3318
- `;
3319
- await Bun.write(lolaScript, unixScript);
3320
- await Bun.$`chmod +x ${lolaScript}`;
3321
- console.log(import_picocolors7.default.green(` Script lola criado em ${lolaScript}`));
3322
- const pathEnv = process.env.PATH || "";
3323
- if (!pathEnv.includes(".local/bin")) {
3324
- console.log();
3325
- console.log(import_picocolors7.default.yellow(" IMPORTANTE: Adicione ~/.local/bin ao seu PATH"));
3326
- console.log(import_picocolors7.default.dim(' export PATH="$HOME/.local/bin:$PATH"'));
3327
- }
3328
- } else {
3329
- console.log(import_picocolors7.default.green(" Script lola ja existe"));
3330
- }
3331
- }
3332
- await installLolaMemoryMCP();
3333
- await installLolaCommands();
3334
- const claudeDir = join3(HOME, ".claude");
3335
- if (!existsSync2(USER_MEMORY)) {
3336
- console.log();
3337
- console.log(import_picocolors7.default.cyan(" Configurando USER_MEMORY.md..."));
3338
- const gitUserResult = Bun.spawnSync(["git", "config", "user.name"], { stdout: "pipe" });
3339
- const gitEmailResult = Bun.spawnSync(["git", "config", "user.email"], { stdout: "pipe" });
3340
- const gitUser = gitUserResult.stdout.toString().trim() || "Dev";
3341
- const gitEmail = gitEmailResult.stdout.toString().trim() || "";
3342
- const hostname = process.env.HOSTNAME || process.env.COMPUTERNAME || "local";
3343
- const today = new Date().toISOString().split("T")[0];
3344
- await Bun.$`mkdir -p ${claudeDir}`;
3345
- const content = `# User Memory
3346
-
3347
- Memoria persistente para sessoes Claude Code
3348
-
3349
- ---
3350
-
3351
- ## Dev
3352
-
3353
- **Nome:** ${gitUser}
3354
- **Email:** ${gitEmail}
3355
- **Maquina:** ${hostname}
3356
- **Instalacao:** ${today}
3357
-
3358
- ---
3359
-
3360
- ## Configuracoes da Lola
3361
-
3362
- \`\`\`
3363
- lola_profile: millennial
3364
- \`\`\`
3365
-
3366
- ---
3367
-
3368
- ## Ultima Sessao
3369
-
3370
- (sera preenchido automaticamente)
3371
-
3372
- ---
3373
- `;
3374
- await Bun.write(USER_MEMORY, content);
3375
- console.log(import_picocolors7.default.green(` USER_MEMORY.md criado para ${gitUser}!`));
3376
- }
3377
- console.log();
3378
- console.log(import_picocolors7.default.green(" Claude configurado!"));
3379
- }
3380
- var SUBCOMMAND_ALIASES = {
3381
- i: "install",
3382
- s: "suggest",
3383
- o: "onboard",
3384
- q: "quiz",
3385
- h: "help",
3386
- sync: "install",
3387
- "--help": "help",
3388
- "-h": "help"
3389
- };
3390
- async function lola(args) {
3391
- const rawSubcommand = args[0];
3392
- const subcommand = rawSubcommand ? SUBCOMMAND_ALIASES[rawSubcommand] || rawSubcommand : null;
3393
- if (!subcommand || subcommand === "install") {
3394
- await installInteractive();
3395
- } else if (subcommand === "onboard") {
3396
- await onboardDev();
3397
- } else if (subcommand === "quiz") {
3398
- await runQuiz();
3399
- } else if (subcommand === "suggest") {
3400
- const message = args.slice(1).join(" ");
3401
- await suggestImprovement(message);
3402
- } else if (subcommand === "help") {
3403
- showLolaHelp();
3404
- } else {
3405
- console.log(import_picocolors7.default.red(` Subcomando desconhecido: ${rawSubcommand}`));
3406
- showLolaHelp();
3407
- process.exit(1);
3408
- }
3409
- }
3410
- function showLolaHelp() {
3411
- console.log();
3412
- console.log(import_picocolors7.default.bold(" Lola - Code Agent da nimbuslab"));
3413
- console.log();
3414
- console.log(import_picocolors7.default.bold(" Uso:") + " nimbus lola [subcomando]");
3415
- console.log();
3416
- console.log(import_picocolors7.default.bold(" Subcomandos:"));
3417
- console.log(import_picocolors7.default.dim(" install, i ") + import_picocolors7.default.white("Instalar/atualizar Lola + MCP"));
3418
- console.log(import_picocolors7.default.dim(" onboard, o ") + import_picocolors7.default.white("Configurar perfil (novos devs)"));
3419
- console.log(import_picocolors7.default.dim(" quiz, q ") + import_picocolors7.default.white("Quiz sobre a nimbuslab"));
3420
- console.log(import_picocolors7.default.dim(" suggest, s ") + import_picocolors7.default.white("Sugerir melhoria (cria issue)"));
3421
- console.log(import_picocolors7.default.dim(" help, h ") + import_picocolors7.default.white("Mostrar esta ajuda"));
3422
- console.log();
3423
- console.log(import_picocolors7.default.bold(" Exemplos:"));
3424
- console.log(import_picocolors7.default.dim(" $ nimbus lola i"));
3425
- console.log(import_picocolors7.default.dim(" $ nimbus lola o"));
3426
- console.log(import_picocolors7.default.dim(" $ nimbus lola q"));
3427
- console.log(import_picocolors7.default.dim(' $ nimbus lola s "adicionar suporte a X"'));
3428
- console.log();
3429
- console.log(import_picocolors7.default.bold(" lola-memory (dentro do Claude):"));
3430
- console.log(import_picocolors7.default.dim(' remember "query" ') + import_picocolors7.default.white("Buscar conhecimento"));
3431
- console.log(import_picocolors7.default.dim(' learn "content" ') + import_picocolors7.default.white("Salvar conhecimento"));
3432
- console.log(import_picocolors7.default.dim(" memory_stats ") + import_picocolors7.default.white("Ver estatisticas"));
3433
- console.log(import_picocolors7.default.dim(" get_context ") + import_picocolors7.default.white("Perfil + memorias recentes"));
3434
- console.log();
3435
- }
3436
-
3437
3267
  // src/commands/setup-node.ts
3438
3268
  var import_picocolors8 = __toESM(require_picocolors(), 1);
3439
3269
  import { execSync as execSync2, spawnSync as spawnSync2 } from "child_process";
3440
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
3441
- import { homedir as homedir2 } from "os";
3270
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
3271
+ import { homedir } from "os";
3442
3272
  import { join as join4 } from "path";
3443
- var HOME2 = homedir2();
3273
+ var HOME = homedir();
3444
3274
  var IS_WINDOWS = process.platform === "win32";
3445
- var CHECK_CMD2 = IS_WINDOWS ? "where" : "which";
3275
+ var CHECK_CMD = IS_WINDOWS ? "where" : "which";
3446
3276
  function detectFnm() {
3447
3277
  const result = { name: "fnm", installed: false };
3448
- const check = spawnSync2(CHECK_CMD2, ["fnm"], { encoding: "utf-8", shell: true });
3278
+ const check = spawnSync2(CHECK_CMD, ["fnm"], { encoding: "utf-8", shell: true });
3449
3279
  const fnmLocations = IS_WINDOWS ? [
3450
- join4(HOME2, "scoop", "shims", "fnm.exe"),
3451
- join4(HOME2, "scoop", "apps", "fnm", "current", "fnm.exe"),
3280
+ join4(HOME, "scoop", "shims", "fnm.exe"),
3281
+ join4(HOME, "scoop", "apps", "fnm", "current", "fnm.exe"),
3452
3282
  "C:\\ProgramData\\chocolatey\\bin\\fnm.exe",
3453
- join4(HOME2, ".cargo", "bin", "fnm.exe"),
3454
- join4(HOME2, ".fnm", "fnm.exe"),
3455
- join4(HOME2, "AppData", "Local", "fnm", "fnm.exe"),
3456
- join4(HOME2, "AppData", "Roaming", "fnm", "fnm.exe"),
3457
- join4(HOME2, "AppData", "Local", "Microsoft", "fnm", "fnm.exe"),
3458
- join4(HOME2, "AppData", "Roaming", "fnm"),
3459
- join4(HOME2, "AppData", "Local", "fnm_multishells")
3283
+ join4(HOME, ".cargo", "bin", "fnm.exe"),
3284
+ join4(HOME, ".fnm", "fnm.exe"),
3285
+ join4(HOME, "AppData", "Local", "fnm", "fnm.exe"),
3286
+ join4(HOME, "AppData", "Roaming", "fnm", "fnm.exe"),
3287
+ join4(HOME, "AppData", "Local", "Microsoft", "fnm", "fnm.exe"),
3288
+ join4(HOME, "AppData", "Roaming", "fnm"),
3289
+ join4(HOME, "AppData", "Local", "fnm_multishells")
3460
3290
  ] : [
3461
- join4(HOME2, ".local", "share", "fnm", "fnm"),
3462
- join4(HOME2, ".fnm", "fnm"),
3463
- join4(HOME2, ".local", "bin", "fnm"),
3291
+ join4(HOME, ".local", "share", "fnm", "fnm"),
3292
+ join4(HOME, ".fnm", "fnm"),
3293
+ join4(HOME, ".local", "bin", "fnm"),
3464
3294
  "/opt/homebrew/bin/fnm",
3465
3295
  "/usr/local/bin/fnm",
3466
- join4(HOME2, ".cargo", "bin", "fnm")
3296
+ join4(HOME, ".cargo", "bin", "fnm")
3467
3297
  ];
3468
3298
  let fnmPath = null;
3469
- if (check.exitCode === 0) {
3299
+ if (check.status === 0) {
3470
3300
  fnmPath = check.stdout?.trim().split(`
3471
3301
  `)[0] || null;
3472
3302
  } else {
3473
3303
  for (const loc of fnmLocations) {
3474
- if (existsSync3(loc)) {
3304
+ if (existsSync2(loc)) {
3475
3305
  fnmPath = loc;
3476
3306
  break;
3477
3307
  }
3478
3308
  }
3479
3309
  }
3480
3310
  if (!fnmPath && process.env.FNM_DIR) {
3481
- if (existsSync3(process.env.FNM_DIR)) {
3311
+ if (existsSync2(process.env.FNM_DIR)) {
3482
3312
  fnmPath = process.env.FNM_DIR;
3483
3313
  }
3484
3314
  }
3485
3315
  if (!fnmPath && IS_WINDOWS) {
3486
- const fnmMultishells = join4(HOME2, "AppData", "Local", "fnm_multishells");
3487
- if (existsSync3(fnmMultishells)) {
3316
+ const fnmMultishells = join4(HOME, "AppData", "Local", "fnm_multishells");
3317
+ if (existsSync2(fnmMultishells)) {
3488
3318
  fnmPath = fnmMultishells;
3489
3319
  }
3490
3320
  }
@@ -3499,26 +3329,26 @@ function detectFnm() {
3499
3329
  } catch {}
3500
3330
  result.configFiles = [];
3501
3331
  if (IS_WINDOWS) {
3502
- const ps5Profile = join4(HOME2, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
3503
- const ps7Profile = join4(HOME2, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
3504
- const psProfile = join4(HOME2, "Documents", "PowerShell", "profile.ps1");
3505
- if (existsSync3(ps5Profile))
3332
+ const ps5Profile = join4(HOME, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
3333
+ const ps7Profile = join4(HOME, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
3334
+ const psProfile = join4(HOME, "Documents", "PowerShell", "profile.ps1");
3335
+ if (existsSync2(ps5Profile))
3506
3336
  result.configFiles.push(ps5Profile);
3507
- if (existsSync3(ps7Profile))
3337
+ if (existsSync2(ps7Profile))
3508
3338
  result.configFiles.push(ps7Profile);
3509
- if (existsSync3(psProfile))
3339
+ if (existsSync2(psProfile))
3510
3340
  result.configFiles.push(psProfile);
3511
3341
  } else {
3512
3342
  const configs = [
3513
- join4(HOME2, ".bashrc"),
3514
- join4(HOME2, ".bash_profile"),
3515
- join4(HOME2, ".profile"),
3516
- join4(HOME2, ".zshrc"),
3517
- join4(HOME2, ".zprofile"),
3518
- join4(HOME2, ".config", "fish", "config.fish")
3343
+ join4(HOME, ".bashrc"),
3344
+ join4(HOME, ".bash_profile"),
3345
+ join4(HOME, ".profile"),
3346
+ join4(HOME, ".zshrc"),
3347
+ join4(HOME, ".zprofile"),
3348
+ join4(HOME, ".config", "fish", "config.fish")
3519
3349
  ];
3520
3350
  for (const cfg of configs) {
3521
- if (existsSync3(cfg))
3351
+ if (existsSync2(cfg))
3522
3352
  result.configFiles.push(cfg);
3523
3353
  }
3524
3354
  }
@@ -3527,20 +3357,20 @@ function detectFnm() {
3527
3357
  function detectNvm() {
3528
3358
  const result = { name: "nvm", installed: false };
3529
3359
  if (IS_WINDOWS) {
3530
- const check = spawnSync2(CHECK_CMD2, ["nvm"], { encoding: "utf-8", shell: true });
3360
+ const check = spawnSync2(CHECK_CMD, ["nvm"], { encoding: "utf-8", shell: true });
3531
3361
  const nvmWinLocations = [
3532
- join4(HOME2, "AppData", "Roaming", "nvm", "nvm.exe"),
3362
+ join4(HOME, "AppData", "Roaming", "nvm", "nvm.exe"),
3533
3363
  "C:\\Program Files\\nvm\\nvm.exe",
3534
3364
  "C:\\ProgramData\\nvm\\nvm.exe",
3535
- join4(HOME2, "nvm", "nvm.exe")
3365
+ join4(HOME, "nvm", "nvm.exe")
3536
3366
  ];
3537
3367
  let nvmPath = null;
3538
- if (check.exitCode === 0) {
3368
+ if (check.status === 0) {
3539
3369
  nvmPath = check.stdout?.trim().split(`
3540
3370
  `)[0] || null;
3541
3371
  } else {
3542
3372
  for (const loc of nvmWinLocations) {
3543
- if (existsSync3(loc)) {
3373
+ if (existsSync2(loc)) {
3544
3374
  nvmPath = loc;
3545
3375
  break;
3546
3376
  }
@@ -3556,31 +3386,31 @@ function detectNvm() {
3556
3386
  } catch {}
3557
3387
  result.configFiles = [];
3558
3388
  const configs = [
3559
- join4(HOME2, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1"),
3560
- join4(HOME2, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1"),
3561
- join4(HOME2, "Documents", "PowerShell", "profile.ps1")
3389
+ join4(HOME, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1"),
3390
+ join4(HOME, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1"),
3391
+ join4(HOME, "Documents", "PowerShell", "profile.ps1")
3562
3392
  ];
3563
3393
  for (const cfg of configs) {
3564
- if (existsSync3(cfg))
3394
+ if (existsSync2(cfg))
3565
3395
  result.configFiles.push(cfg);
3566
3396
  }
3567
3397
  } else {
3568
- const nvmDir = process.env.NVM_DIR || join4(HOME2, ".nvm");
3569
- if (!existsSync3(nvmDir))
3398
+ const nvmDir = process.env.NVM_DIR || join4(HOME, ".nvm");
3399
+ if (!existsSync2(nvmDir))
3570
3400
  return result;
3571
3401
  result.installed = true;
3572
3402
  result.path = nvmDir;
3573
3403
  result.configFiles = [];
3574
3404
  const configs = [
3575
- join4(HOME2, ".bashrc"),
3576
- join4(HOME2, ".bash_profile"),
3577
- join4(HOME2, ".profile"),
3578
- join4(HOME2, ".zshrc"),
3579
- join4(HOME2, ".zprofile"),
3580
- join4(HOME2, ".config", "fish", "config.fish")
3405
+ join4(HOME, ".bashrc"),
3406
+ join4(HOME, ".bash_profile"),
3407
+ join4(HOME, ".profile"),
3408
+ join4(HOME, ".zshrc"),
3409
+ join4(HOME, ".zprofile"),
3410
+ join4(HOME, ".config", "fish", "config.fish")
3581
3411
  ];
3582
3412
  for (const cfg of configs) {
3583
- if (existsSync3(cfg))
3413
+ if (existsSync2(cfg))
3584
3414
  result.configFiles.push(cfg);
3585
3415
  }
3586
3416
  }
@@ -3588,8 +3418,8 @@ function detectNvm() {
3588
3418
  }
3589
3419
  function detectVolta() {
3590
3420
  const result = { name: "volta", installed: false };
3591
- const check = spawnSync2(CHECK_CMD2, ["volta"], { encoding: "utf-8", shell: true });
3592
- if (check.exitCode !== 0)
3421
+ const check = spawnSync2(CHECK_CMD, ["volta"], { encoding: "utf-8", shell: true });
3422
+ if (check.status !== 0)
3593
3423
  return result;
3594
3424
  result.installed = true;
3595
3425
  result.path = check.stdout?.trim().split(`
@@ -3601,8 +3431,8 @@ function detectVolta() {
3601
3431
  return result;
3602
3432
  }
3603
3433
  function detectNode() {
3604
- const check = spawnSync2(CHECK_CMD2, ["node"], { encoding: "utf-8", shell: true });
3605
- if (check.exitCode !== 0)
3434
+ const check = spawnSync2(CHECK_CMD, ["node"], { encoding: "utf-8", shell: true });
3435
+ if (check.status !== 0)
3606
3436
  return { version: null, manager: null };
3607
3437
  const nodePath = check.stdout?.trim().split(`
3608
3438
  `)[0] || "";
@@ -3643,7 +3473,7 @@ function getGlobalPackages() {
3643
3473
  return packages;
3644
3474
  }
3645
3475
  function removeFnmFromConfig(configFile) {
3646
- if (!existsSync3(configFile))
3476
+ if (!existsSync2(configFile))
3647
3477
  return false;
3648
3478
  try {
3649
3479
  let content = readFileSync2(configFile, "utf-8");
@@ -3668,7 +3498,7 @@ function removeFnmFromConfig(configFile) {
3668
3498
  return false;
3669
3499
  }
3670
3500
  function removeNvmFromConfig(configFile) {
3671
- if (!existsSync3(configFile))
3501
+ if (!existsSync2(configFile))
3672
3502
  return false;
3673
3503
  try {
3674
3504
  let content = readFileSync2(configFile, "utf-8");
@@ -3729,16 +3559,16 @@ async function removeFnm(fnm) {
3729
3559
  } catch {}
3730
3560
  }
3731
3561
  const winFnmDirs = [
3732
- join4(HOME2, ".fnm"),
3733
- join4(HOME2, "AppData", "Local", "fnm"),
3734
- join4(HOME2, "AppData", "Roaming", "fnm"),
3735
- join4(HOME2, "AppData", "Local", "fnm_multishells"),
3736
- join4(HOME2, "AppData", "Local", "Microsoft", "fnm")
3562
+ join4(HOME, ".fnm"),
3563
+ join4(HOME, "AppData", "Local", "fnm"),
3564
+ join4(HOME, "AppData", "Roaming", "fnm"),
3565
+ join4(HOME, "AppData", "Local", "fnm_multishells"),
3566
+ join4(HOME, "AppData", "Local", "Microsoft", "fnm")
3737
3567
  ];
3738
3568
  for (const dir of winFnmDirs) {
3739
- if (existsSync3(dir)) {
3569
+ if (existsSync2(dir)) {
3740
3570
  try {
3741
- execSync2(`rmdir /s /q "${dir}"`, { stdio: "pipe", shell: true });
3571
+ execSync2(`rmdir /s /q "${dir}"`, { stdio: "pipe", shell: "cmd.exe" });
3742
3572
  console.log(import_picocolors8.default.dim(` Removido ${dir}`));
3743
3573
  removed = true;
3744
3574
  } catch {
@@ -3769,7 +3599,7 @@ async function removeFnm(fnm) {
3769
3599
  let removed = false;
3770
3600
  try {
3771
3601
  const brewCheck = spawnSync2("brew", ["list", "fnm"], { encoding: "utf-8", shell: true });
3772
- if (brewCheck.exitCode === 0) {
3602
+ if (brewCheck.status === 0) {
3773
3603
  execSync2("brew uninstall fnm", { stdio: "pipe" });
3774
3604
  console.log(import_picocolors8.default.dim(" Removido via Homebrew"));
3775
3605
  removed = true;
@@ -3782,22 +3612,22 @@ async function removeFnm(fnm) {
3782
3612
  }
3783
3613
  }
3784
3614
  const fnmDirs = [
3785
- join4(HOME2, ".fnm"),
3786
- join4(HOME2, ".local", "share", "fnm")
3615
+ join4(HOME, ".fnm"),
3616
+ join4(HOME, ".local", "share", "fnm")
3787
3617
  ];
3788
3618
  for (const fnmDir of fnmDirs) {
3789
- if (existsSync3(fnmDir)) {
3619
+ if (existsSync2(fnmDir)) {
3790
3620
  execSync2(`rm -rf "${fnmDir}"`, { stdio: "pipe" });
3791
3621
  console.log(import_picocolors8.default.dim(` Removido ${fnmDir}`));
3792
3622
  removed = true;
3793
3623
  }
3794
3624
  }
3795
3625
  const fnmBins = [
3796
- join4(HOME2, ".local", "bin", "fnm"),
3797
- join4(HOME2, ".cargo", "bin", "fnm")
3626
+ join4(HOME, ".local", "bin", "fnm"),
3627
+ join4(HOME, ".cargo", "bin", "fnm")
3798
3628
  ];
3799
3629
  for (const bin of fnmBins) {
3800
- if (existsSync3(bin)) {
3630
+ if (existsSync2(bin)) {
3801
3631
  execSync2(`rm -f "${bin}"`, { stdio: "pipe" });
3802
3632
  console.log(import_picocolors8.default.dim(` Removido ${bin}`));
3803
3633
  removed = true;
@@ -3826,14 +3656,14 @@ async function removeNvm(nvm) {
3826
3656
  }
3827
3657
  } catch {}
3828
3658
  const nvmWinDirs = [
3829
- join4(HOME2, "AppData", "Roaming", "nvm"),
3659
+ join4(HOME, "AppData", "Roaming", "nvm"),
3830
3660
  join4("C:", "Program Files", "nvm"),
3831
3661
  join4("C:", "ProgramData", "nvm")
3832
3662
  ];
3833
3663
  for (const dir of nvmWinDirs) {
3834
- if (existsSync3(dir)) {
3664
+ if (existsSync2(dir)) {
3835
3665
  try {
3836
- execSync2(`rmdir /s /q "${dir}"`, { stdio: "pipe", shell: true });
3666
+ execSync2(`rmdir /s /q "${dir}"`, { stdio: "pipe", shell: "cmd.exe" });
3837
3667
  console.log(import_picocolors8.default.dim(` Removido ${dir}`));
3838
3668
  removed = true;
3839
3669
  } catch {}
@@ -3863,8 +3693,8 @@ async function removeNvm(nvm) {
3863
3693
  removed = true;
3864
3694
  }
3865
3695
  }
3866
- const nvmDir = process.env.NVM_DIR || join4(HOME2, ".nvm");
3867
- if (existsSync3(nvmDir)) {
3696
+ const nvmDir = process.env.NVM_DIR || join4(HOME, ".nvm");
3697
+ if (existsSync2(nvmDir)) {
3868
3698
  execSync2(`rm -rf "${nvmDir}"`, { stdio: "pipe" });
3869
3699
  console.log(import_picocolors8.default.dim(` Removido ${nvmDir}`));
3870
3700
  removed = true;
@@ -3882,8 +3712,8 @@ async function installVolta() {
3882
3712
  try {
3883
3713
  if (IS_WINDOWS) {
3884
3714
  spinner.start("Verificando metodo de instalacao...");
3885
- const wingetCheck = spawnSync2(CHECK_CMD2, ["winget"], { encoding: "utf-8", shell: true });
3886
- if (wingetCheck.exitCode === 0) {
3715
+ const wingetCheck = spawnSync2(CHECK_CMD, ["winget"], { encoding: "utf-8", shell: true });
3716
+ if (wingetCheck.status === 0) {
3887
3717
  spinner.stop("winget detectado");
3888
3718
  spinner.start("Instalando Volta via winget...");
3889
3719
  try {
@@ -3892,18 +3722,18 @@ async function installVolta() {
3892
3722
  timeout: 120000
3893
3723
  });
3894
3724
  spinner.stop("Volta instalado!");
3895
- const voltaPath = join4(HOME2, ".volta", "bin");
3725
+ const voltaPath = join4(HOME, ".volta", "bin");
3896
3726
  console.log(import_picocolors8.default.dim(` Adicionando ${voltaPath} ao PATH...`));
3897
3727
  try {
3898
- execSync2(`setx PATH "%PATH%;${voltaPath}"`, { stdio: "pipe", shell: true });
3728
+ execSync2(`setx PATH "%PATH%;${voltaPath}"`, { stdio: "pipe", shell: "cmd.exe" });
3899
3729
  } catch {}
3900
3730
  return true;
3901
3731
  } catch (e2) {
3902
3732
  spinner.stop(import_picocolors8.default.yellow("winget falhou, tentando outro metodo..."));
3903
3733
  }
3904
3734
  }
3905
- const chocoCheck = spawnSync2(CHECK_CMD2, ["choco"], { encoding: "utf-8", shell: true });
3906
- if (chocoCheck.exitCode === 0) {
3735
+ const chocoCheck = spawnSync2(CHECK_CMD, ["choco"], { encoding: "utf-8", shell: true });
3736
+ if (chocoCheck.status === 0) {
3907
3737
  spinner.start("Instalando Volta via Chocolatey...");
3908
3738
  try {
3909
3739
  execSync2("choco install volta -y", { stdio: "pipe", timeout: 120000 });
@@ -3953,13 +3783,13 @@ async function installVolta() {
3953
3783
  stdio: "pipe",
3954
3784
  shell: "/bin/bash"
3955
3785
  });
3956
- const shellConfig = existsSync3(join4(HOME2, ".zshrc")) ? join4(HOME2, ".zshrc") : join4(HOME2, ".bashrc");
3786
+ const shellConfig = existsSync2(join4(HOME, ".zshrc")) ? join4(HOME, ".zshrc") : join4(HOME, ".bashrc");
3957
3787
  const voltaSetup = `
3958
3788
  # Volta - Node.js version manager
3959
3789
  export VOLTA_HOME="$HOME/.volta"
3960
3790
  export PATH="$VOLTA_HOME/bin:$PATH"
3961
3791
  `;
3962
- if (existsSync3(shellConfig)) {
3792
+ if (existsSync2(shellConfig)) {
3963
3793
  const content = readFileSync2(shellConfig, "utf-8");
3964
3794
  if (!content.includes("VOLTA_HOME")) {
3965
3795
  writeFileSync(shellConfig, content + voltaSetup);
@@ -3978,9 +3808,9 @@ export PATH="$VOLTA_HOME/bin:$PATH"
3978
3808
  async function installNodeWithVolta() {
3979
3809
  const spinner = Y2();
3980
3810
  try {
3981
- const voltaBin = IS_WINDOWS ? "volta" : join4(HOME2, ".volta", "bin", "volta");
3811
+ const voltaBin = IS_WINDOWS ? "volta" : join4(HOME, ".volta", "bin", "volta");
3982
3812
  spinner.start("Instalando Node.js LTS via Volta...");
3983
- execSync2(`"${voltaBin}" install node`, { stdio: "pipe", shell: true });
3813
+ execSync2(`"${voltaBin}" install node`, { stdio: "pipe" });
3984
3814
  spinner.stop("Node.js instalado!");
3985
3815
  return true;
3986
3816
  } catch (error) {
@@ -3992,11 +3822,11 @@ async function reinstallGlobalPackages(packages) {
3992
3822
  if (packages.length === 0)
3993
3823
  return;
3994
3824
  const spinner = Y2();
3995
- const voltaBin = IS_WINDOWS ? "volta" : join4(HOME2, ".volta", "bin", "volta");
3825
+ const voltaBin = IS_WINDOWS ? "volta" : join4(HOME, ".volta", "bin", "volta");
3996
3826
  for (const pkg of packages) {
3997
3827
  spinner.start(`Instalando ${pkg}...`);
3998
3828
  try {
3999
- execSync2(`"${voltaBin}" install ${pkg}`, { stdio: "pipe", shell: true });
3829
+ execSync2(`"${voltaBin}" install ${pkg}`, { stdio: "pipe" });
4000
3830
  spinner.stop(`${pkg} instalado!`);
4001
3831
  } catch {
4002
3832
  spinner.stop(import_picocolors8.default.yellow(`${pkg} - falha (instale manualmente)`));
@@ -4135,7 +3965,7 @@ async function setupNode(args) {
4135
3965
 
4136
3966
  // src/index.ts
4137
3967
  var PACKAGE_NAME2 = "@nimbuslab/cli";
4138
- var CURRENT_VERSION = "0.17.3";
3968
+ var CURRENT_VERSION = "1.1.0";
4139
3969
  var LOGO = `
4140
3970
  \u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
4141
3971
  \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
@@ -4196,8 +4026,6 @@ async function main() {
4196
4026
  await upgrade(args.slice(1));
4197
4027
  } else if (command === "update") {
4198
4028
  await update(args.slice(1));
4199
- } else if (command === "lola") {
4200
- await lola(args.slice(1));
4201
4029
  } else if (command === "setup") {
4202
4030
  const subcommand = args[1];
4203
4031
  if (subcommand === "node") {