lynxprompt 0.3.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -200,12 +200,7 @@ async function loginCommand() {
200
200
  pollSpinner.succeed("Authentication successful!");
201
201
  setToken(result.token);
202
202
  setUser(result.user);
203
- console.log();
204
- console.log(chalk.green(`\u2705 Logged in as ${chalk.bold(result.user.email)}`));
205
- console.log(chalk.gray(` Plan: ${result.user.plan}`));
206
- console.log(chalk.gray(` Token stored securely in config`));
207
- console.log();
208
- console.log(chalk.cyan("You're ready to use LynxPrompt CLI!"));
203
+ displayWelcome(result.user);
209
204
  return;
210
205
  }
211
206
  if (result.status === "expired") {
@@ -259,6 +254,56 @@ async function tryOpenBrowser(url) {
259
254
  function sleep(ms) {
260
255
  return new Promise((resolve) => setTimeout(resolve, ms));
261
256
  }
257
+ function displayWelcome(user) {
258
+ const plan = user.plan?.toUpperCase() || "FREE";
259
+ const name = user.name || user.email.split("@")[0];
260
+ const planConfig = {
261
+ FREE: { color: chalk.gray, emoji: "\u{1F193}", badge: "Free" },
262
+ PRO: { color: chalk.cyan, emoji: "\u26A1", badge: "Pro" },
263
+ MAX: { color: chalk.magenta, emoji: "\u{1F680}", badge: "Max" },
264
+ TEAMS: { color: chalk.yellow, emoji: "\u{1F465}", badge: "Teams" }
265
+ };
266
+ const config2 = planConfig[plan] || planConfig.FREE;
267
+ const W = 45;
268
+ const b = chalk.bold;
269
+ const pad = (s, len) => s + " ".repeat(Math.max(0, len - s.length));
270
+ console.log();
271
+ console.log(b("\u250C" + "\u2500".repeat(W) + "\u2510"));
272
+ console.log(b("\u2502") + " ".repeat(W) + b("\u2502"));
273
+ console.log(b("\u2502") + pad(` ${config2.emoji} Welcome to LynxPrompt CLI!`, W - 1) + b("\u2502"));
274
+ console.log(b("\u2502") + " ".repeat(W) + b("\u2502"));
275
+ console.log(b("\u2502") + pad(` User: ${name}`, W) + b("\u2502"));
276
+ console.log(b("\u2502") + pad(` Plan: ${config2.badge}`, W) + b("\u2502"));
277
+ console.log(b("\u2502") + " ".repeat(W) + b("\u2502"));
278
+ console.log(b("\u2514" + "\u2500".repeat(W) + "\u2518"));
279
+ console.log();
280
+ console.log(chalk.bold("\u{1F4CB} Your CLI Capabilities:"));
281
+ console.log();
282
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt init") + chalk.gray(" - Generate config files"));
283
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt wizard") + chalk.gray(" - Interactive wizard"));
284
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt list") + chalk.gray(" - List your blueprints"));
285
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt pull <id>") + chalk.gray(" - Download blueprints"));
286
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt push") + chalk.gray(" - Upload blueprints to marketplace"));
287
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt link") + chalk.gray(" - Link project to blueprint"));
288
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt sync") + chalk.gray(" - Sync linked blueprints"));
289
+ console.log(chalk.green(" \u2713") + " " + chalk.white("lynxprompt diff") + chalk.gray(" - Compare local vs remote"));
290
+ if (plan === "PRO" || plan === "MAX" || plan === "TEAMS") {
291
+ console.log();
292
+ console.log(chalk.cyan(" \u26A1") + " " + chalk.white("Advanced wizards") + chalk.gray(" - More customization options"));
293
+ console.log(chalk.cyan(" \u26A1") + " " + chalk.white("Sell blueprints") + chalk.gray(" - Monetize your configurations"));
294
+ }
295
+ if (plan === "MAX" || plan === "TEAMS") {
296
+ console.log(chalk.magenta(" \u{1F680}") + " " + chalk.white("All paid blueprints") + chalk.gray(" - Access premium content"));
297
+ console.log(chalk.magenta(" \u{1F680}") + " " + chalk.white("Priority support") + chalk.gray(" - Get help faster"));
298
+ }
299
+ if (plan === "TEAMS") {
300
+ console.log(chalk.yellow(" \u{1F465}") + " " + chalk.white("Team blueprints") + chalk.gray(" - Share with your team"));
301
+ console.log(chalk.yellow(" \u{1F465}") + " " + chalk.white("SSO integration") + chalk.gray(" - Enterprise authentication"));
302
+ }
303
+ console.log();
304
+ console.log(chalk.gray("Token stored securely. Run ") + chalk.cyan("lynxprompt --help") + chalk.gray(" to see all commands."));
305
+ console.log();
306
+ }
262
307
 
263
308
  // src/commands/logout.ts
264
309
  import chalk2 from "chalk";
@@ -1974,7 +2019,17 @@ var PLATFORM_FILES = {
1974
2019
  claude: "CLAUDE.md",
1975
2020
  copilot: ".github/copilot-instructions.md",
1976
2021
  windsurf: ".windsurfrules",
1977
- zed: ".zed/instructions.md"
2022
+ zed: ".zed/instructions.md",
2023
+ aider: ".aider.conf.yml",
2024
+ cline: ".clinerules",
2025
+ continue: ".continue/rules.md",
2026
+ cody: ".cody/rules.md",
2027
+ amazonq: ".amazonq/rules/project.md",
2028
+ tabnine: ".tabnine.yaml",
2029
+ supermaven: ".supermaven/rules.md",
2030
+ codegpt: ".codegpt/rules.md",
2031
+ void: ".void/rules.md",
2032
+ goose: ".goosehints"
1978
2033
  };
1979
2034
  var PERSONA_DESCRIPTIONS = {
1980
2035
  backend: "a senior backend developer specializing in APIs, databases, and microservices architecture",
@@ -1995,6 +2050,8 @@ var STACK_NAMES = {
1995
2050
  ruby: "Ruby",
1996
2051
  php: "PHP",
1997
2052
  swift: "Swift",
2053
+ kotlin: "Kotlin",
2054
+ cpp: "C/C++",
1998
2055
  react: "React",
1999
2056
  nextjs: "Next.js",
2000
2057
  vue: "Vue.js",
@@ -2007,10 +2064,44 @@ var STACK_NAMES = {
2007
2064
  spring: "Spring Boot",
2008
2065
  rails: "Ruby on Rails",
2009
2066
  laravel: "Laravel",
2067
+ nestjs: "NestJS",
2068
+ vite: "Vite",
2069
+ "react-native": "React Native",
2070
+ postgresql: "PostgreSQL",
2071
+ mysql: "MySQL",
2072
+ mongodb: "MongoDB",
2073
+ redis: "Redis",
2074
+ sqlite: "SQLite",
2075
+ supabase: "Supabase",
2076
+ firebase: "Firebase",
2010
2077
  prisma: "Prisma",
2011
2078
  tailwind: "Tailwind CSS",
2012
2079
  fastify: "Fastify"
2013
2080
  };
2081
+ var NAMING_DESCRIPTIONS = {
2082
+ language_default: "follow idiomatic conventions for the primary language",
2083
+ camelCase: "use camelCase for variables and functions",
2084
+ snake_case: "use snake_case for variables and functions",
2085
+ PascalCase: "use PascalCase for classes and types",
2086
+ "kebab-case": "use kebab-case for file names and CSS classes"
2087
+ };
2088
+ var AI_BEHAVIOR_DESCRIPTIONS = {
2089
+ explain_changes: "Always explain what changes you're making and why before implementing them",
2090
+ preserve_style: "Preserve and follow the existing code style in the project",
2091
+ minimal_changes: "Make minimal, focused changes - avoid unnecessary refactoring",
2092
+ no_comments: "Avoid adding unnecessary comments; code should be self-documenting",
2093
+ prefer_simple: "Prefer simpler solutions over clever ones",
2094
+ test_first: "Write tests before implementing new functionality (TDD)",
2095
+ no_console: "Remove console.log/print statements before committing",
2096
+ type_strict: "Be strict with types - avoid any/Any/Object types"
2097
+ };
2098
+ var IMPORTANT_FILES_PATHS = {
2099
+ readme: "README.md",
2100
+ package: "package.json or pyproject.toml",
2101
+ tsconfig: "tsconfig.json or similar config",
2102
+ architecture: "ARCHITECTURE.md",
2103
+ contributing: "CONTRIBUTING.md"
2104
+ };
2014
2105
  var BOUNDARIES = {
2015
2106
  conservative: {
2016
2107
  always: ["Read any file in the project", "Run lint and format commands"],
@@ -2069,6 +2160,265 @@ var BOUNDARIES = {
2069
2160
  ]
2070
2161
  }
2071
2162
  };
2163
+ var TEST_LEVEL_DESCRIPTIONS = {
2164
+ smoke: "Quick sanity checks for critical paths",
2165
+ unit: "Unit tests for individual functions and components",
2166
+ integration: "Integration tests for component interactions",
2167
+ e2e: "End-to-end tests for full user flows"
2168
+ };
2169
+ var STATIC_FILE_TEMPLATES = {
2170
+ editorconfig: () => `# EditorConfig is awesome: https://EditorConfig.org
2171
+
2172
+ root = true
2173
+
2174
+ [*]
2175
+ indent_style = space
2176
+ indent_size = 2
2177
+ end_of_line = lf
2178
+ charset = utf-8
2179
+ trim_trailing_whitespace = true
2180
+ insert_final_newline = true
2181
+
2182
+ [*.md]
2183
+ trim_trailing_whitespace = false
2184
+
2185
+ [Makefile]
2186
+ indent_style = tab
2187
+ `,
2188
+ contributing: (opts) => `# Contributing to ${opts.name}
2189
+
2190
+ Thank you for your interest in contributing!
2191
+
2192
+ ## How to Contribute
2193
+
2194
+ 1. Fork the repository
2195
+ 2. Create a feature branch (\`git checkout -b feature/amazing-feature\`)
2196
+ 3. Commit your changes${opts.conventionalCommits ? " using Conventional Commits format" : ""}
2197
+ 4. Push to the branch (\`git push origin feature/amazing-feature\`)
2198
+ 5. Open a Pull Request
2199
+
2200
+ ## Development Setup
2201
+
2202
+ \`\`\`bash
2203
+ # Clone your fork
2204
+ git clone https://github.com/YOUR_USERNAME/${opts.name}.git
2205
+ cd ${opts.name}
2206
+
2207
+ # Install dependencies
2208
+ npm install
2209
+
2210
+ # Run development server
2211
+ npm run dev
2212
+ \`\`\`
2213
+
2214
+ ## Code Style
2215
+
2216
+ Please follow the existing code style and conventions in this project.
2217
+ `,
2218
+ codeOfConduct: (opts) => `# Code of Conduct
2219
+
2220
+ ## Our Pledge
2221
+
2222
+ We pledge to make participation in the ${opts.name} project a harassment-free experience for everyone.
2223
+
2224
+ ## Our Standards
2225
+
2226
+ Examples of behavior that contributes to a positive environment:
2227
+ - Using welcoming and inclusive language
2228
+ - Being respectful of differing viewpoints
2229
+ - Gracefully accepting constructive criticism
2230
+ - Focusing on what is best for the community
2231
+
2232
+ ## Enforcement
2233
+
2234
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project team.
2235
+
2236
+ ## Attribution
2237
+
2238
+ This Code of Conduct is adapted from the Contributor Covenant, version 2.1.
2239
+ `,
2240
+ security: (opts) => `# Security Policy
2241
+
2242
+ ## Supported Versions
2243
+
2244
+ | Version | Supported |
2245
+ | ------- | ------------------ |
2246
+ | latest | :white_check_mark: |
2247
+
2248
+ ## Reporting a Vulnerability
2249
+
2250
+ If you discover a security vulnerability in ${opts.name}, please report it by emailing the maintainers.
2251
+
2252
+ **Please do not open a public issue for security vulnerabilities.**
2253
+
2254
+ We will acknowledge receipt within 48 hours and provide a detailed response within 7 days.
2255
+ `,
2256
+ roadmap: (opts) => `# Roadmap
2257
+
2258
+ ## ${opts.name} Development Roadmap
2259
+
2260
+ ### Current Version
2261
+
2262
+ - Core functionality
2263
+
2264
+ ### Planned Features
2265
+
2266
+ - [ ] Feature 1
2267
+ - [ ] Feature 2
2268
+ - [ ] Feature 3
2269
+
2270
+ ### Long-term Goals
2271
+
2272
+ - Goal 1
2273
+ - Goal 2
2274
+
2275
+ ---
2276
+ *This roadmap is subject to change based on community feedback and priorities.*
2277
+ `,
2278
+ gitignore: (opts) => {
2279
+ const patterns = ["# Dependencies", "node_modules/", ".pnpm-store/", ""];
2280
+ if (opts.stack.includes("python")) {
2281
+ patterns.push("# Python", "__pycache__/", "*.py[cod]", ".venv/", "venv/", "");
2282
+ }
2283
+ patterns.push("# Environment", ".env", ".env.local", ".env*.local", "");
2284
+ patterns.push("# Build outputs", "dist/", "build/", ".next/", "out/", "");
2285
+ patterns.push("# IDE", ".idea/", ".vscode/", "*.swp", "*.swo", "");
2286
+ patterns.push("# OS", ".DS_Store", "Thumbs.db", "");
2287
+ patterns.push("# Logs", "*.log", "npm-debug.log*", "");
2288
+ return patterns.join("\n");
2289
+ },
2290
+ funding: () => `# These are supported funding model platforms
2291
+
2292
+ github: [] # Replace with your GitHub username
2293
+ patreon: # Replace with your Patreon username
2294
+ open_collective: # Replace with your Open Collective username
2295
+ ko_fi: # Replace with your Ko-fi username
2296
+ custom: [] # Add custom funding links
2297
+ `,
2298
+ license: (opts) => {
2299
+ if (opts.license === "mit") {
2300
+ return `MIT License
2301
+
2302
+ Copyright (c) ${(/* @__PURE__ */ new Date()).getFullYear()} ${opts.name}
2303
+
2304
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2305
+ of this software and associated documentation files (the "Software"), to deal
2306
+ in the Software without restriction, including without limitation the rights
2307
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2308
+ copies of the Software, and to permit persons to whom the Software is
2309
+ furnished to do so, subject to the following conditions:
2310
+
2311
+ The above copyright notice and this permission notice shall be included in all
2312
+ copies or substantial portions of the Software.
2313
+
2314
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2315
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2316
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2317
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2318
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2319
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2320
+ SOFTWARE.
2321
+ `;
2322
+ }
2323
+ return `# License
2324
+
2325
+ This project is licensed under the ${opts.license?.toUpperCase() || "Proprietary"} license.
2326
+ `;
2327
+ },
2328
+ readme: (opts) => {
2329
+ const stackBadges = opts.stack.slice(0, 5).map((s) => STACK_NAMES[s] || s).join(" \u2022 ");
2330
+ return `# ${opts.name}
2331
+
2332
+ ${opts.description || "A project generated with LynxPrompt."}
2333
+
2334
+ ${stackBadges ? `## Tech Stack
2335
+
2336
+ ${stackBadges}
2337
+ ` : ""}
2338
+ ## Getting Started
2339
+
2340
+ \`\`\`bash
2341
+ # Clone the repository
2342
+ git clone <repository-url>
2343
+ cd ${opts.name}
2344
+
2345
+ # Install dependencies
2346
+ npm install
2347
+
2348
+ # Run development server
2349
+ npm run dev
2350
+ \`\`\`
2351
+
2352
+ ## License
2353
+
2354
+ ${opts.license && opts.license !== "none" ? `This project is licensed under the ${opts.license.toUpperCase()} License.` : "See LICENSE file for details."}
2355
+ `;
2356
+ },
2357
+ architecture: (opts) => `# Architecture
2358
+
2359
+ ## ${opts.name} Architecture Overview
2360
+
2361
+ ${opts.architecture ? `### Pattern: ${opts.architecture}
2362
+ ` : ""}
2363
+ ### Directory Structure
2364
+
2365
+ \`\`\`
2366
+ ${opts.name}/
2367
+ \u251C\u2500\u2500 src/ # Source code
2368
+ \u251C\u2500\u2500 tests/ # Test files
2369
+ \u251C\u2500\u2500 docs/ # Documentation
2370
+ \u2514\u2500\u2500 ...
2371
+ \`\`\`
2372
+
2373
+ ### Key Components
2374
+
2375
+ 1. **Component A** - Description
2376
+ 2. **Component B** - Description
2377
+ 3. **Component C** - Description
2378
+
2379
+ ### Data Flow
2380
+
2381
+ Describe how data flows through the application.
2382
+
2383
+ ---
2384
+ *Generated by LynxPrompt*
2385
+ `,
2386
+ changelog: (opts) => `# Changelog
2387
+
2388
+ All notable changes to ${opts.name} will be documented in this file.
2389
+
2390
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
2391
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2392
+
2393
+ ## [Unreleased]
2394
+
2395
+ ### Added
2396
+ - Initial project setup
2397
+
2398
+ ### Changed
2399
+
2400
+ ### Deprecated
2401
+
2402
+ ### Removed
2403
+
2404
+ ### Fixed
2405
+
2406
+ ### Security
2407
+ `
2408
+ };
2409
+ var STATIC_FILE_PATHS = {
2410
+ editorconfig: ".editorconfig",
2411
+ contributing: "CONTRIBUTING.md",
2412
+ codeOfConduct: "CODE_OF_CONDUCT.md",
2413
+ security: "SECURITY.md",
2414
+ roadmap: "ROADMAP.md",
2415
+ gitignore: ".gitignore",
2416
+ funding: ".github/FUNDING.yml",
2417
+ license: "LICENSE",
2418
+ readme: "README.md",
2419
+ architecture: "ARCHITECTURE.md",
2420
+ changelog: "CHANGELOG.md"
2421
+ };
2072
2422
  function generateConfig(options) {
2073
2423
  const files = {};
2074
2424
  for (const platform of options.platforms) {
@@ -2077,13 +2427,34 @@ function generateConfig(options) {
2077
2427
  files[filename] = generateFileContent(options, platform);
2078
2428
  }
2079
2429
  }
2430
+ if (options.staticFiles && options.staticFiles.length > 0) {
2431
+ for (const fileKey of options.staticFiles) {
2432
+ const filePath = STATIC_FILE_PATHS[fileKey];
2433
+ if (!filePath) continue;
2434
+ if (options.staticFileContents?.[fileKey]) {
2435
+ files[filePath] = options.staticFileContents[fileKey];
2436
+ } else {
2437
+ const templateFn = STATIC_FILE_TEMPLATES[fileKey];
2438
+ if (templateFn) {
2439
+ files[filePath] = templateFn(options);
2440
+ }
2441
+ }
2442
+ }
2443
+ }
2444
+ if (options.includeFunding && !options.staticFiles?.includes("funding")) {
2445
+ files[".github/FUNDING.yml"] = STATIC_FILE_TEMPLATES.funding(options);
2446
+ }
2080
2447
  return files;
2081
2448
  }
2082
2449
  function generateFileContent(options, platform) {
2083
2450
  const sections = [];
2084
2451
  const isMdc = platform === "cursor";
2085
- const isPlainText = platform === "windsurf";
2086
- const isMarkdown = !isMdc && !isPlainText;
2452
+ const isYaml = platform === "aider" || platform === "tabnine";
2453
+ const isPlainText = platform === "windsurf" || platform === "cline" || platform === "goose";
2454
+ const isMarkdown = !isMdc && !isYaml && !isPlainText;
2455
+ if (isYaml) {
2456
+ return generateYamlConfig(options, platform);
2457
+ }
2087
2458
  if (isMdc) {
2088
2459
  sections.push("---");
2089
2460
  sections.push(`description: "${options.name} - AI coding rules"`);
@@ -2098,6 +2469,23 @@ function generateFileContent(options, platform) {
2098
2469
  sections.push(`# ${options.name} - AI Assistant Configuration`);
2099
2470
  sections.push("");
2100
2471
  }
2472
+ if (options.projectType) {
2473
+ const typeContexts = {
2474
+ work: "This is a professional/enterprise project. Follow strict procedures and maintain high code quality.",
2475
+ leisure: "This is a personal/hobby project. Feel free to be more experimental and creative.",
2476
+ opensource: "This is an open-source project. Consider community guidelines and contribution standards.",
2477
+ learning: "This is an educational project. Explain concepts and be patient with learning-focused approaches."
2478
+ };
2479
+ if (typeContexts[options.projectType]) {
2480
+ if (isMarkdown || isMdc) {
2481
+ sections.push(`> **Project Context:** ${typeContexts[options.projectType]}`);
2482
+ sections.push("");
2483
+ } else {
2484
+ sections.push(`Project Context: ${typeContexts[options.projectType]}`);
2485
+ sections.push("");
2486
+ }
2487
+ }
2488
+ }
2101
2489
  const personaDesc = PERSONA_DESCRIPTIONS[options.persona] || options.persona;
2102
2490
  if (isMarkdown || isMdc) {
2103
2491
  sections.push("## Persona");
@@ -2128,7 +2516,93 @@ function generateFileContent(options, platform) {
2128
2516
  }
2129
2517
  sections.push("");
2130
2518
  }
2131
- const hasCommands = Object.values(options.commands).some(Boolean);
2519
+ if (options.letAiDecide) {
2520
+ if (isMarkdown || isMdc) {
2521
+ sections.push("> **AI Assistance:** Let AI analyze the codebase and suggest additional technologies and approaches as needed.");
2522
+ sections.push("");
2523
+ }
2524
+ }
2525
+ if (options.repoHost || options.license || options.conventionalCommits || options.semver || options.cicd || options.deploymentTargets?.length || options.buildContainer || options.exampleRepoUrl || options.documentationUrl) {
2526
+ if (isMarkdown || isMdc) {
2527
+ sections.push("## Repository & Infrastructure");
2528
+ sections.push("");
2529
+ if (options.repoHost) {
2530
+ sections.push(`- **Host:** ${options.repoHost.charAt(0).toUpperCase() + options.repoHost.slice(1)}`);
2531
+ }
2532
+ if (options.license && options.license !== "none") {
2533
+ sections.push(`- **License:** ${options.license.toUpperCase()}`);
2534
+ }
2535
+ if (options.conventionalCommits) {
2536
+ sections.push("- **Commits:** Follow [Conventional Commits](https://conventionalcommits.org) format");
2537
+ }
2538
+ if (options.semver) {
2539
+ sections.push("- **Versioning:** Follow [Semantic Versioning](https://semver.org) (semver)");
2540
+ }
2541
+ if (options.dependabot) {
2542
+ sections.push("- **Dependencies:** Dependabot/automated dependency updates enabled");
2543
+ }
2544
+ if (options.cicd) {
2545
+ const cicdNames = {
2546
+ github_actions: "GitHub Actions",
2547
+ gitlab_ci: "GitLab CI",
2548
+ jenkins: "Jenkins",
2549
+ circleci: "CircleCI",
2550
+ travis: "Travis CI",
2551
+ azure_devops: "Azure DevOps",
2552
+ bitbucket: "Bitbucket Pipelines",
2553
+ teamcity: "TeamCity",
2554
+ drone: "Drone",
2555
+ buildkite: "Buildkite"
2556
+ };
2557
+ sections.push(`- **CI/CD:** ${cicdNames[options.cicd] || options.cicd}`);
2558
+ }
2559
+ if (options.deploymentTargets && options.deploymentTargets.length > 0) {
2560
+ const targetNames = {
2561
+ vercel: "Vercel",
2562
+ netlify: "Netlify",
2563
+ aws: "AWS",
2564
+ gcp: "Google Cloud",
2565
+ azure: "Azure",
2566
+ docker: "Docker",
2567
+ kubernetes: "Kubernetes",
2568
+ heroku: "Heroku",
2569
+ digitalocean: "DigitalOcean",
2570
+ railway: "Railway",
2571
+ fly: "Fly.io",
2572
+ cloudflare: "Cloudflare"
2573
+ };
2574
+ const targets = options.deploymentTargets.map((t) => targetNames[t] || t).join(", ");
2575
+ sections.push(`- **Deployment:** ${targets}`);
2576
+ }
2577
+ if (options.buildContainer) {
2578
+ let containerInfo = "Docker container builds enabled";
2579
+ if (options.containerRegistry) {
2580
+ const registryNames = {
2581
+ dockerhub: "Docker Hub",
2582
+ ghcr: "GitHub Container Registry",
2583
+ gcr: "Google Container Registry",
2584
+ ecr: "AWS ECR",
2585
+ acr: "Azure Container Registry",
2586
+ quay: "Quay.io",
2587
+ gitlab: "GitLab Registry",
2588
+ custom: "Custom registry"
2589
+ };
2590
+ containerInfo += ` \u2192 ${registryNames[options.containerRegistry] || options.containerRegistry}`;
2591
+ }
2592
+ sections.push(`- **Containers:** ${containerInfo}`);
2593
+ }
2594
+ if (options.exampleRepoUrl) {
2595
+ sections.push(`- **Example Repo:** ${options.exampleRepoUrl} (use as reference for style/structure)`);
2596
+ }
2597
+ if (options.documentationUrl) {
2598
+ sections.push(`- **Documentation:** ${options.documentationUrl}`);
2599
+ }
2600
+ sections.push("");
2601
+ }
2602
+ }
2603
+ const hasCommands = options.commands && Object.values(options.commands).some(
2604
+ (v) => Array.isArray(v) ? v.length > 0 : Boolean(v)
2605
+ );
2132
2606
  if (hasCommands) {
2133
2607
  if (isMarkdown || isMdc) {
2134
2608
  sections.push("## Commands");
@@ -2139,24 +2613,76 @@ function generateFileContent(options, platform) {
2139
2613
  } else {
2140
2614
  sections.push("Commands:");
2141
2615
  }
2142
- if (options.commands.build) {
2143
- sections.push(isMarkdown || isMdc ? `# Build: ${options.commands.build}` : `- Build: ${options.commands.build}`);
2616
+ const cmdCategories = ["build", "test", "lint", "dev", "custom"];
2617
+ for (const cat of cmdCategories) {
2618
+ const cmd = options.commands[cat];
2619
+ if (cmd) {
2620
+ const cmds = Array.isArray(cmd) ? cmd : [cmd];
2621
+ for (const c of cmds) {
2622
+ if (c) {
2623
+ const label = cat.charAt(0).toUpperCase() + cat.slice(1);
2624
+ sections.push(isMarkdown || isMdc ? `# ${label}: ${c}` : `- ${label}: ${c}`);
2625
+ }
2626
+ }
2627
+ }
2144
2628
  }
2145
- if (options.commands.test) {
2146
- sections.push(isMarkdown || isMdc ? `# Test: ${options.commands.test}` : `- Test: ${options.commands.test}`);
2629
+ if (isMarkdown || isMdc) {
2630
+ sections.push("```");
2147
2631
  }
2148
- if (options.commands.lint) {
2149
- sections.push(isMarkdown || isMdc ? `# Lint: ${options.commands.lint}` : `- Lint: ${options.commands.lint}`);
2632
+ sections.push("");
2633
+ }
2634
+ if (options.aiBehavior && options.aiBehavior.length > 0) {
2635
+ if (isMarkdown || isMdc) {
2636
+ sections.push("## AI Behavior Rules");
2637
+ sections.push("");
2638
+ for (const rule of options.aiBehavior) {
2639
+ const desc = AI_BEHAVIOR_DESCRIPTIONS[rule];
2640
+ if (desc) {
2641
+ sections.push(`- ${desc}`);
2642
+ }
2643
+ }
2644
+ sections.push("");
2150
2645
  }
2151
- if (options.commands.dev) {
2152
- sections.push(isMarkdown || isMdc ? `# Dev: ${options.commands.dev}` : `- Dev: ${options.commands.dev}`);
2646
+ }
2647
+ if (options.importantFiles && options.importantFiles.length > 0) {
2648
+ if (isMarkdown || isMdc) {
2649
+ sections.push("## Important Files to Read");
2650
+ sections.push("");
2651
+ sections.push("Always read these files first to understand the project context:");
2652
+ sections.push("");
2653
+ for (const file of options.importantFiles) {
2654
+ const path2 = IMPORTANT_FILES_PATHS[file];
2655
+ if (path2) {
2656
+ sections.push(`- \`${path2}\``);
2657
+ }
2658
+ }
2659
+ sections.push("");
2153
2660
  }
2661
+ }
2662
+ if (options.selfImprove) {
2154
2663
  if (isMarkdown || isMdc) {
2155
- sections.push("```");
2664
+ sections.push("## Self-Improving Blueprint");
2665
+ sections.push("");
2666
+ sections.push("> **Auto-update enabled:** As you work on this project, track patterns and update this configuration file to better reflect the project's conventions and preferences.");
2667
+ sections.push("");
2156
2668
  }
2157
- sections.push("");
2158
2669
  }
2159
- const boundaries = BOUNDARIES[options.boundaries];
2670
+ if (options.includePersonalData) {
2671
+ if (isMarkdown || isMdc) {
2672
+ sections.push("## Commit Identity");
2673
+ sections.push("");
2674
+ sections.push("> **Personal data enabled:** Use my name and email for git commits when making changes.");
2675
+ sections.push("");
2676
+ }
2677
+ }
2678
+ let boundaries = BOUNDARIES[options.boundaries];
2679
+ if (options.boundaryNever?.length || options.boundaryAsk?.length) {
2680
+ boundaries = {
2681
+ ...boundaries,
2682
+ never: options.boundaryNever?.length ? options.boundaryNever : boundaries.never,
2683
+ askFirst: options.boundaryAsk?.length ? options.boundaryAsk : boundaries.askFirst
2684
+ };
2685
+ }
2160
2686
  if (boundaries) {
2161
2687
  if (isMarkdown || isMdc) {
2162
2688
  sections.push("## Boundaries");
@@ -2201,6 +2727,30 @@ function generateFileContent(options, platform) {
2201
2727
  if (isMarkdown || isMdc) {
2202
2728
  sections.push("## Code Style");
2203
2729
  sections.push("");
2730
+ if (options.namingConvention) {
2731
+ const namingDesc = NAMING_DESCRIPTIONS[options.namingConvention];
2732
+ if (namingDesc) {
2733
+ sections.push(`- **Naming:** ${namingDesc}`);
2734
+ }
2735
+ }
2736
+ if (options.errorHandling) {
2737
+ const errorStyles = {
2738
+ try_catch: "Use try/catch blocks for error handling",
2739
+ result_types: "Use Result/Either types for error handling",
2740
+ error_codes: "Use error codes with proper documentation",
2741
+ exceptions: "Use custom exception classes"
2742
+ };
2743
+ if (errorStyles[options.errorHandling]) {
2744
+ sections.push(`- **Errors:** ${errorStyles[options.errorHandling]}`);
2745
+ }
2746
+ }
2747
+ if (options.loggingConventions) {
2748
+ sections.push(`- **Logging:** ${options.loggingConventions}`);
2749
+ }
2750
+ if (options.styleNotes) {
2751
+ sections.push(`- **Notes:** ${options.styleNotes}`);
2752
+ }
2753
+ sections.push("");
2204
2754
  sections.push("Follow these conventions:");
2205
2755
  sections.push("");
2206
2756
  if (options.stack.includes("typescript") || options.stack.includes("javascript")) {
@@ -2234,6 +2784,49 @@ function generateFileContent(options, platform) {
2234
2784
  sections.push("- Keep functions focused and testable");
2235
2785
  sections.push("");
2236
2786
  }
2787
+ if (options.testLevels?.length || options.testFrameworks?.length || options.coverageTarget) {
2788
+ if (isMarkdown || isMdc) {
2789
+ sections.push("## Testing Strategy");
2790
+ sections.push("");
2791
+ if (options.testLevels?.length) {
2792
+ sections.push("### Test Levels");
2793
+ sections.push("");
2794
+ for (const level of options.testLevels) {
2795
+ const desc = TEST_LEVEL_DESCRIPTIONS[level];
2796
+ if (desc) {
2797
+ sections.push(`- **${level.charAt(0).toUpperCase() + level.slice(1)}:** ${desc}`);
2798
+ }
2799
+ }
2800
+ sections.push("");
2801
+ }
2802
+ if (options.testFrameworks?.length) {
2803
+ sections.push("### Frameworks");
2804
+ sections.push("");
2805
+ sections.push(`Use: ${options.testFrameworks.join(", ")}`);
2806
+ sections.push("");
2807
+ }
2808
+ if (options.coverageTarget) {
2809
+ sections.push(`### Coverage Target: ${options.coverageTarget}%`);
2810
+ sections.push("");
2811
+ }
2812
+ if (options.testNotes) {
2813
+ sections.push(`**Notes:** ${options.testNotes}`);
2814
+ sections.push("");
2815
+ }
2816
+ }
2817
+ }
2818
+ if (options.extraNotes) {
2819
+ if (isMarkdown || isMdc) {
2820
+ sections.push("## Additional Notes");
2821
+ sections.push("");
2822
+ sections.push(options.extraNotes);
2823
+ sections.push("");
2824
+ } else {
2825
+ sections.push("Additional Notes:");
2826
+ sections.push(options.extraNotes);
2827
+ sections.push("");
2828
+ }
2829
+ }
2237
2830
  if (isMarkdown || isMdc) {
2238
2831
  sections.push("---");
2239
2832
  sections.push("");
@@ -2241,37 +2834,82 @@ function generateFileContent(options, platform) {
2241
2834
  }
2242
2835
  return sections.join("\n");
2243
2836
  }
2837
+ function generateYamlConfig(options, platform) {
2838
+ const lines = [];
2839
+ if (platform === "aider") {
2840
+ lines.push("# Aider configuration");
2841
+ lines.push(`# Project: ${options.name}`);
2842
+ lines.push("");
2843
+ lines.push("# Model settings");
2844
+ lines.push("model: gpt-4");
2845
+ lines.push("");
2846
+ lines.push("# Code style");
2847
+ if (options.stack.includes("typescript") || options.stack.includes("javascript")) {
2848
+ lines.push("auto-lint: true");
2849
+ }
2850
+ lines.push("");
2851
+ lines.push("# Custom instructions");
2852
+ lines.push("read:");
2853
+ lines.push(" - README.md");
2854
+ if (options.importantFiles?.includes("architecture")) {
2855
+ lines.push(" - ARCHITECTURE.md");
2856
+ }
2857
+ } else if (platform === "tabnine") {
2858
+ lines.push("# Tabnine configuration");
2859
+ lines.push(`# Project: ${options.name}`);
2860
+ lines.push("");
2861
+ lines.push("version: 1.0.0");
2862
+ lines.push("");
2863
+ lines.push("project:");
2864
+ lines.push(` name: ${options.name}`);
2865
+ if (options.description) {
2866
+ lines.push(` description: "${options.description}"`);
2867
+ }
2868
+ lines.push("");
2869
+ lines.push("context:");
2870
+ lines.push(" include:");
2871
+ lines.push(' - "**/*.ts"');
2872
+ lines.push(' - "**/*.js"');
2873
+ lines.push(' - "**/*.py"');
2874
+ }
2875
+ lines.push("");
2876
+ lines.push(`# Generated by LynxPrompt CLI`);
2877
+ return lines.join("\n");
2878
+ }
2244
2879
 
2245
2880
  // src/commands/wizard.ts
2246
- var OUTPUT_FORMATS = [
2247
- {
2248
- title: "\u{1F310} AGENTS.md",
2249
- value: "agents",
2250
- description: "Universal format - Claude, Copilot, Aider, & more",
2251
- recommended: true
2252
- },
2253
- {
2254
- title: "\u{1F5B1}\uFE0F Cursor",
2255
- value: "cursor",
2256
- description: ".cursor/rules/ with MDC format"
2257
- },
2258
- {
2259
- title: "\u{1F30A} Windsurf",
2260
- value: "windsurf",
2261
- description: ".windsurfrules configuration"
2262
- },
2263
- {
2264
- title: "\u{1F916} Claude Code",
2265
- value: "claude",
2266
- description: "CLAUDE.md for Claude AI"
2267
- },
2268
- {
2269
- title: "\u{1F4E6} Multiple",
2270
- value: "multiple",
2271
- description: "Generate for multiple AI editors"
2272
- }
2881
+ var WIZARD_STEPS = [
2882
+ { id: "format", title: "Output Format", icon: "\u{1F4E4}", tier: "basic" },
2883
+ { id: "project", title: "Project Basics", icon: "\u2728", tier: "basic" },
2884
+ { id: "tech", title: "Tech Stack", icon: "\u{1F4BB}", tier: "basic" },
2885
+ { id: "repo", title: "Repository Setup", icon: "\u{1F500}", tier: "basic" },
2886
+ { id: "commands", title: "Commands", icon: "\u{1F4CB}", tier: "intermediate" },
2887
+ { id: "code_style", title: "Code Style", icon: "\u{1FA84}", tier: "intermediate" },
2888
+ { id: "ai", title: "AI Behavior", icon: "\u{1F9E0}", tier: "basic" },
2889
+ { id: "boundaries", title: "Boundaries", icon: "\u{1F6E1}\uFE0F", tier: "advanced" },
2890
+ { id: "testing", title: "Testing Strategy", icon: "\u{1F9EA}", tier: "advanced" },
2891
+ { id: "static", title: "Static Files", icon: "\u{1F4C4}", tier: "advanced" },
2892
+ { id: "extra", title: "Final Details", icon: "\u{1F4AC}", tier: "basic" }
2893
+ ];
2894
+ var ALL_PLATFORMS = [
2895
+ { id: "agents", name: "Universal (AGENTS.md)", file: "AGENTS.md", icon: "\u{1F310}", note: "Works with all AI-enabled IDEs" },
2896
+ { id: "cursor", name: "Cursor", file: ".cursor/rules/", icon: "\u26A1", note: "Native project rules format" },
2897
+ { id: "claude", name: "Claude Code", file: "CLAUDE.md", icon: "\u{1F9E0}", note: "Also works with Cursor" },
2898
+ { id: "copilot", name: "GitHub Copilot", file: ".github/copilot-instructions.md", icon: "\u{1F419}", note: "VS Code & JetBrains" },
2899
+ { id: "windsurf", name: "Windsurf", file: ".windsurfrules", icon: "\u{1F3C4}", note: "Codeium IDE" },
2900
+ { id: "zed", name: "Zed", file: ".zed/instructions.md", icon: "\u26A1", note: "Zed editor" },
2901
+ { id: "aider", name: "Aider", file: ".aider.conf.yml", icon: "\u{1F916}", note: "CLI AI pair programming" },
2902
+ { id: "cline", name: "Cline", file: ".clinerules", icon: "\u{1F527}", note: "VS Code extension" },
2903
+ { id: "continue", name: "Continue", file: ".continue/config.json", icon: "\u27A1\uFE0F", note: "Open-source autopilot" },
2904
+ { id: "cody", name: "Sourcegraph Cody", file: ".cody/config.json", icon: "\u{1F50D}", note: "Context-aware AI" },
2905
+ { id: "amazonq", name: "Amazon Q", file: ".amazonq/rules/", icon: "\u{1F4E6}", note: "AWS AI assistant" },
2906
+ { id: "tabnine", name: "Tabnine", file: ".tabnine.yaml", icon: "\u{1F4DD}", note: "AI code completion" },
2907
+ { id: "supermaven", name: "Supermaven", file: ".supermaven/config.json", icon: "\u{1F9B8}", note: "Fast AI completions" },
2908
+ { id: "codegpt", name: "CodeGPT", file: ".codegpt/config.json", icon: "\u{1F4AC}", note: "VS Code AI assistant" },
2909
+ { id: "void", name: "Void", file: ".void/config.json", icon: "\u{1F573}\uFE0F", note: "Open-source Cursor alt" },
2910
+ { id: "goose", name: "Goose", file: ".goosehints", icon: "\u{1FABF}", note: "Block AI agent" }
2273
2911
  ];
2274
- var TECH_STACKS = [
2912
+ var LANGUAGES = [
2275
2913
  { title: "\u{1F537} TypeScript", value: "typescript" },
2276
2914
  { title: "\u{1F7E1} JavaScript", value: "javascript" },
2277
2915
  { title: "\u{1F40D} Python", value: "python" },
@@ -2281,7 +2919,9 @@ var TECH_STACKS = [
2281
2919
  { title: "\u{1F49C} C#/.NET", value: "csharp" },
2282
2920
  { title: "\u{1F48E} Ruby", value: "ruby" },
2283
2921
  { title: "\u{1F418} PHP", value: "php" },
2284
- { title: "\u{1F34E} Swift", value: "swift" }
2922
+ { title: "\u{1F34E} Swift", value: "swift" },
2923
+ { title: "\u{1F536} Kotlin", value: "kotlin" },
2924
+ { title: "\u2B1B C/C++", value: "cpp" }
2285
2925
  ];
2286
2926
  var FRAMEWORKS = [
2287
2927
  { title: "\u269B\uFE0F React", value: "react" },
@@ -2300,23 +2940,169 @@ var FRAMEWORKS = [
2300
2940
  { title: "\u26A1 Vite", value: "vite" },
2301
2941
  { title: "\u{1F4F1} React Native", value: "react-native" }
2302
2942
  ];
2303
- var PLATFORMS = [
2304
- { title: "\u{1F310} AGENTS.md (Universal)", value: "agents", filename: "AGENTS.md" },
2305
- { title: "\u{1F5B1}\uFE0F Cursor", value: "cursor", filename: ".cursor/rules/project.mdc" },
2306
- { title: "\u{1F916} Claude Code", value: "claude", filename: "CLAUDE.md" },
2307
- { title: "\u{1F419} GitHub Copilot", value: "copilot", filename: ".github/copilot-instructions.md" },
2308
- { title: "\u{1F30A} Windsurf", value: "windsurf", filename: ".windsurfrules" },
2309
- { title: "\u26A1 Zed", value: "zed", filename: ".zed/instructions.md" },
2310
- { title: "\u{1F916} Cline", value: "cline", filename: ".clinerules" }
2943
+ var DATABASES = [
2944
+ { title: "\u{1F418} PostgreSQL", value: "postgresql" },
2945
+ { title: "\u{1F42C} MySQL", value: "mysql" },
2946
+ { title: "\u{1F343} MongoDB", value: "mongodb" },
2947
+ { title: "\u{1F534} Redis", value: "redis" },
2948
+ { title: "\u{1F4CA} SQLite", value: "sqlite" },
2949
+ { title: "\u2601\uFE0F Supabase", value: "supabase" },
2950
+ { title: "\u{1F525} Firebase", value: "firebase" },
2951
+ { title: "\u{1F4C2} Prisma", value: "prisma" }
2952
+ ];
2953
+ var REPO_HOSTS = [
2954
+ { id: "github", label: "GitHub", icon: "\u{1F419}" },
2955
+ { id: "gitlab", label: "GitLab", icon: "\u{1F98A}" },
2956
+ { id: "bitbucket", label: "Bitbucket", icon: "\u{1FAA3}" },
2957
+ { id: "gitea", label: "Gitea", icon: "\u{1F375}" },
2958
+ { id: "azure", label: "Azure DevOps", icon: "\u2601\uFE0F" },
2959
+ { id: "other", label: "Other", icon: "\u{1F4E6}" }
2960
+ ];
2961
+ var LICENSES = [
2962
+ { id: "mit", label: "MIT" },
2963
+ { id: "apache-2.0", label: "Apache 2.0" },
2964
+ { id: "gpl-3.0", label: "GPL 3.0" },
2965
+ { id: "lgpl-3.0", label: "LGPL 3.0" },
2966
+ { id: "agpl-3.0", label: "AGPL 3.0" },
2967
+ { id: "bsd-3", label: "BSD 3-Clause" },
2968
+ { id: "mpl-2.0", label: "MPL 2.0" },
2969
+ { id: "unlicense", label: "Unlicense" },
2970
+ { id: "none", label: "None / Proprietary" }
2971
+ ];
2972
+ var CICD_OPTIONS = [
2973
+ { id: "github_actions", label: "GitHub Actions", icon: "\u{1F419}" },
2974
+ { id: "gitlab_ci", label: "GitLab CI", icon: "\u{1F98A}" },
2975
+ { id: "jenkins", label: "Jenkins", icon: "\u{1F527}" },
2976
+ { id: "circleci", label: "CircleCI", icon: "\u26AB" },
2977
+ { id: "travis", label: "Travis CI", icon: "\u{1F528}" },
2978
+ { id: "azure_devops", label: "Azure DevOps", icon: "\u2601\uFE0F" },
2979
+ { id: "bitbucket", label: "Bitbucket Pipelines", icon: "\u{1FAA3}" },
2980
+ { id: "teamcity", label: "TeamCity", icon: "\u{1F3E2}" },
2981
+ { id: "drone", label: "Drone", icon: "\u{1F681}" },
2982
+ { id: "buildkite", label: "Buildkite", icon: "\u{1F9F1}" }
2983
+ ];
2984
+ var DEPLOYMENT_TARGETS = [
2985
+ { id: "vercel", label: "Vercel", icon: "\u25B2" },
2986
+ { id: "netlify", label: "Netlify", icon: "\u{1F310}" },
2987
+ { id: "aws", label: "AWS", icon: "\u2601\uFE0F" },
2988
+ { id: "gcp", label: "Google Cloud", icon: "\u{1F308}" },
2989
+ { id: "azure", label: "Azure", icon: "\u{1F537}" },
2990
+ { id: "docker", label: "Docker", icon: "\u{1F433}" },
2991
+ { id: "kubernetes", label: "Kubernetes", icon: "\u2638\uFE0F" },
2992
+ { id: "heroku", label: "Heroku", icon: "\u{1F7E3}" },
2993
+ { id: "digitalocean", label: "DigitalOcean", icon: "\u{1F535}" },
2994
+ { id: "railway", label: "Railway", icon: "\u{1F682}" },
2995
+ { id: "fly", label: "Fly.io", icon: "\u2708\uFE0F" },
2996
+ { id: "cloudflare", label: "Cloudflare", icon: "\u{1F536}" }
2997
+ ];
2998
+ var CONTAINER_REGISTRIES = [
2999
+ { id: "dockerhub", label: "Docker Hub", icon: "\u{1F433}" },
3000
+ { id: "ghcr", label: "GitHub Container Registry", icon: "\u{1F419}" },
3001
+ { id: "gcr", label: "Google Container Registry", icon: "\u{1F308}" },
3002
+ { id: "ecr", label: "AWS ECR", icon: "\u2601\uFE0F" },
3003
+ { id: "acr", label: "Azure Container Registry", icon: "\u{1F537}" },
3004
+ { id: "quay", label: "Quay.io", icon: "\u{1F534}" },
3005
+ { id: "gitlab", label: "GitLab Registry", icon: "\u{1F98A}" },
3006
+ { id: "custom", label: "Custom/Self-hosted", icon: "\u{1F3E0}" }
3007
+ ];
3008
+ var COMMON_COMMANDS = {
3009
+ build: [
3010
+ "npm run build",
3011
+ "pnpm build",
3012
+ "yarn build",
3013
+ "bun run build",
3014
+ "next build",
3015
+ "vite build",
3016
+ "tsc",
3017
+ "tsc --noEmit",
3018
+ "go build",
3019
+ "cargo build",
3020
+ "cargo build --release",
3021
+ "mvn package",
3022
+ "gradle build",
3023
+ "dotnet build",
3024
+ "docker build -t app .",
3025
+ "docker compose build"
3026
+ ],
3027
+ test: [
3028
+ "npm test",
3029
+ "pnpm test",
3030
+ "yarn test",
3031
+ "bun test",
3032
+ "vitest",
3033
+ "vitest run",
3034
+ "jest",
3035
+ "jest --coverage",
3036
+ "pytest",
3037
+ "pytest --cov",
3038
+ "go test ./...",
3039
+ "cargo test",
3040
+ "mvn test",
3041
+ "gradle test",
3042
+ "playwright test",
3043
+ "cypress run"
3044
+ ],
3045
+ lint: [
3046
+ "npm run lint",
3047
+ "pnpm lint",
3048
+ "eslint .",
3049
+ "eslint . --fix",
3050
+ "prettier --check .",
3051
+ "prettier --write .",
3052
+ "ruff check",
3053
+ "ruff format",
3054
+ "black .",
3055
+ "flake8",
3056
+ "golangci-lint run",
3057
+ "cargo clippy",
3058
+ "rubocop"
3059
+ ],
3060
+ dev: [
3061
+ "npm run dev",
3062
+ "pnpm dev",
3063
+ "yarn dev",
3064
+ "bun run dev",
3065
+ "next dev",
3066
+ "vite",
3067
+ "vite dev",
3068
+ "uvicorn main:app --reload",
3069
+ "flask run",
3070
+ "rails server",
3071
+ "go run .",
3072
+ "cargo run",
3073
+ "dotnet run"
3074
+ ]
3075
+ };
3076
+ var NAMING_CONVENTIONS = [
3077
+ { id: "language_default", label: "Follow language conventions", desc: "Use idiomatic style" },
3078
+ { id: "camelCase", label: "camelCase", desc: "JavaScript, TypeScript, Java" },
3079
+ { id: "snake_case", label: "snake_case", desc: "Python, Ruby, Rust, Go" },
3080
+ { id: "PascalCase", label: "PascalCase", desc: "C#, .NET classes" },
3081
+ { id: "kebab-case", label: "kebab-case", desc: "CSS, HTML, URLs" }
3082
+ ];
3083
+ var ERROR_PATTERNS = [
3084
+ { id: "try_catch", label: "try/catch blocks" },
3085
+ { id: "result_types", label: "Result/Either types" },
3086
+ { id: "error_codes", label: "Error codes" },
3087
+ { id: "exceptions", label: "Custom exceptions" },
3088
+ { id: "other", label: "Other" }
2311
3089
  ];
2312
- var PERSONAS = [
2313
- { title: "\u{1F9D1}\u200D\u{1F4BB} Full-Stack Developer", value: "fullstack", description: "Complete application development" },
2314
- { title: "\u2699\uFE0F Backend Developer", value: "backend", description: "APIs, databases, services" },
2315
- { title: "\u{1F3A8} Frontend Developer", value: "frontend", description: "UI, components, styling" },
2316
- { title: "\u{1F680} DevOps Engineer", value: "devops", description: "Infrastructure, CI/CD" },
2317
- { title: "\u{1F4CA} Data Engineer", value: "data", description: "Pipelines, ETL, analytics" },
2318
- { title: "\u{1F512} Security Engineer", value: "security", description: "Secure code, auditing" },
2319
- { title: "\u270F\uFE0F Custom...", value: "custom", description: "Define your own" }
3090
+ var AI_BEHAVIOR_RULES = [
3091
+ { id: "explain_changes", label: "Explain changes before making them", recommended: true },
3092
+ { id: "preserve_style", label: "Preserve existing code style", recommended: true },
3093
+ { id: "minimal_changes", label: "Make minimal, focused changes", recommended: true },
3094
+ { id: "no_comments", label: "Avoid adding unnecessary comments", recommended: false },
3095
+ { id: "prefer_simple", label: "Prefer simpler solutions", recommended: true },
3096
+ { id: "test_first", label: "Write tests before implementation", recommended: false },
3097
+ { id: "no_console", label: "Remove console.log/print before committing", recommended: false },
3098
+ { id: "type_strict", label: "Be strict with types (no any/Any)", recommended: false }
3099
+ ];
3100
+ var IMPORTANT_FILES = [
3101
+ { id: "readme", label: "README.md", icon: "\u{1F4D6}" },
3102
+ { id: "package", label: "package.json / pyproject.toml", icon: "\u{1F4E6}" },
3103
+ { id: "tsconfig", label: "tsconfig.json / config files", icon: "\u2699\uFE0F" },
3104
+ { id: "architecture", label: "ARCHITECTURE.md", icon: "\u{1F3D7}\uFE0F" },
3105
+ { id: "contributing", label: "CONTRIBUTING.md", icon: "\u{1F91D}" }
2320
3106
  ];
2321
3107
  var BOUNDARY_PRESETS = [
2322
3108
  {
@@ -2344,11 +3130,96 @@ var BOUNDARY_PRESETS = [
2344
3130
  never: ["Modify .env", "Access external APIs without confirmation"]
2345
3131
  }
2346
3132
  ];
2347
- function showStep(current, total, title) {
2348
- const progress = "\u25CF".repeat(current) + "\u25CB".repeat(total - current);
2349
- console.log();
2350
- console.log(chalk8.cyan(` ${progress} Step ${current}/${total}: ${title}`));
2351
- console.log();
3133
+ var BOUNDARY_OPTIONS = [
3134
+ "Delete files",
3135
+ "Create new files",
3136
+ "Rename/move files",
3137
+ "Rewrite large sections",
3138
+ "Refactor architecture",
3139
+ "Change dependencies",
3140
+ "Modify database schema",
3141
+ "Update API contracts",
3142
+ "Touch CI pipelines",
3143
+ "Modify Docker config",
3144
+ "Change environment vars",
3145
+ "Update docs automatically",
3146
+ "Edit README",
3147
+ "Handle secrets/credentials",
3148
+ "Modify auth logic",
3149
+ "Delete failing tests",
3150
+ "Skip tests temporarily"
3151
+ ];
3152
+ var TEST_FRAMEWORKS = [
3153
+ "jest",
3154
+ "vitest",
3155
+ "mocha",
3156
+ "ava",
3157
+ "tap",
3158
+ "pytest",
3159
+ "unittest",
3160
+ "nose2",
3161
+ "go test",
3162
+ "testify",
3163
+ "cargo test",
3164
+ "rstest",
3165
+ "junit",
3166
+ "testng",
3167
+ "spock",
3168
+ "rspec",
3169
+ "minitest",
3170
+ "phpunit",
3171
+ "pest",
3172
+ "playwright",
3173
+ "cypress",
3174
+ "puppeteer",
3175
+ "selenium"
3176
+ ];
3177
+ var TEST_LEVELS = [
3178
+ { id: "smoke", label: "Smoke", desc: "Quick sanity checks" },
3179
+ { id: "unit", label: "Unit", desc: "Individual functions/components" },
3180
+ { id: "integration", label: "Integration", desc: "Component interactions" },
3181
+ { id: "e2e", label: "E2E", desc: "Full user flows" }
3182
+ ];
3183
+ var PROJECT_TYPES = [
3184
+ { id: "work", label: "Work", icon: "\u{1F4BC}", description: "Professional/enterprise project" },
3185
+ { id: "leisure", label: "Leisure", icon: "\u{1F3AE}", description: "Personal/hobby project" },
3186
+ { id: "opensource", label: "Open Source", icon: "\u{1F30D}", description: "Community-driven project" },
3187
+ { id: "learning", label: "Learning", icon: "\u{1F4DA}", description: "Educational/experimental" }
3188
+ ];
3189
+ var DEV_OS_OPTIONS = [
3190
+ { id: "macos", label: "macOS", icon: "\u{1F34E}" },
3191
+ { id: "linux", label: "Linux", icon: "\u{1F427}" },
3192
+ { id: "windows", label: "Windows", icon: "\u{1FA9F}" },
3193
+ { id: "wsl", label: "WSL", icon: "\u{1F427}" },
3194
+ { id: "remote", label: "Remote/SSH", icon: "\u2601\uFE0F" }
3195
+ ];
3196
+ var ARCHITECTURE_PATTERNS = [
3197
+ { id: "monolith", label: "Monolith" },
3198
+ { id: "microservices", label: "Microservices" },
3199
+ { id: "serverless", label: "Serverless" },
3200
+ { id: "mvc", label: "MVC" },
3201
+ { id: "layered", label: "Layered/N-tier" },
3202
+ { id: "event_driven", label: "Event-driven" },
3203
+ { id: "modular", label: "Modular monolith" },
3204
+ { id: "other", label: "Other" }
3205
+ ];
3206
+ function canAccessTier(userTier, requiredTier) {
3207
+ const tierLevels = { free: 0, pro: 1, max: 2, teams: 2 };
3208
+ const requiredLevels = { basic: 0, intermediate: 1, advanced: 2 };
3209
+ return tierLevels[userTier] >= requiredLevels[requiredTier];
3210
+ }
3211
+ function getTierBadge(tier) {
3212
+ switch (tier) {
3213
+ case "intermediate":
3214
+ return { label: "PRO", color: chalk8.cyan };
3215
+ case "advanced":
3216
+ return { label: "MAX", color: chalk8.magenta };
3217
+ default:
3218
+ return null;
3219
+ }
3220
+ }
3221
+ function getAvailableSteps(userTier) {
3222
+ return WIZARD_STEPS.filter((step) => canAccessTier(userTier, step.tier));
2352
3223
  }
2353
3224
  function printBox(lines, color = chalk8.gray) {
2354
3225
  const maxLen = Math.max(...lines.map((l) => l.replace(/\x1b\[[0-9;]*m/g, "").length));
@@ -2362,11 +3233,86 @@ function printBox(lines, color = chalk8.gray) {
2362
3233
  }
2363
3234
  console.log(color(bottom));
2364
3235
  }
3236
+ function showStep(current, step, userTier) {
3237
+ const availableSteps = getAvailableSteps(userTier);
3238
+ const total = availableSteps.length;
3239
+ const progress = "\u25CF".repeat(current) + "\u25CB".repeat(total - current);
3240
+ const badge = getTierBadge(step.tier);
3241
+ console.log();
3242
+ let stepLine = chalk8.cyan(` ${progress} Step ${current}/${total}: ${step.icon} ${step.title}`);
3243
+ if (badge) {
3244
+ stepLine += " " + badge.color(`[${badge.label}]`);
3245
+ }
3246
+ console.log(stepLine);
3247
+ console.log();
3248
+ }
3249
+ function showWizardOverview(userTier) {
3250
+ console.log(chalk8.bold(" \u{1F4CB} Wizard Steps Overview:"));
3251
+ console.log();
3252
+ let stepNum = 1;
3253
+ for (const step of WIZARD_STEPS) {
3254
+ const canAccess = canAccessTier(userTier, step.tier);
3255
+ const badge = getTierBadge(step.tier);
3256
+ if (canAccess) {
3257
+ let line = chalk8.green(` ${stepNum.toString().padStart(2)}. \u2713 ${step.icon} ${step.title}`);
3258
+ if (badge) {
3259
+ line += " " + badge.color(`[${badge.label}]`);
3260
+ }
3261
+ console.log(line);
3262
+ stepNum++;
3263
+ } else {
3264
+ let line = chalk8.gray(` \u2500 \u{1F512} ${step.icon} ${step.title}`);
3265
+ if (badge) {
3266
+ line += " " + badge.color.dim(`[${badge.label}]`);
3267
+ }
3268
+ console.log(line);
3269
+ }
3270
+ }
3271
+ console.log();
3272
+ }
3273
+ var promptConfig = {
3274
+ onCancel: () => {
3275
+ console.log(chalk8.yellow("\n Cancelled. Run 'lynxp wizard' anytime to restart.\n"));
3276
+ process.exit(0);
3277
+ }
3278
+ };
2365
3279
  async function wizardCommand(options) {
2366
3280
  console.log();
2367
3281
  console.log(chalk8.cyan.bold(" \u{1F431} LynxPrompt Wizard"));
2368
3282
  console.log(chalk8.gray(" Generate AI IDE configuration in seconds"));
2369
3283
  console.log();
3284
+ const authenticated = isAuthenticated();
3285
+ const user = getUser();
3286
+ const userPlanRaw = user?.plan?.toLowerCase() || "free";
3287
+ const userTier = ["pro", "max", "teams"].includes(userPlanRaw) ? userPlanRaw : "free";
3288
+ const userPlanDisplay = user?.plan?.toUpperCase() || "FREE";
3289
+ if (!authenticated) {
3290
+ const W = 55;
3291
+ const y = chalk8.yellow;
3292
+ const pad = (s, len) => s + " ".repeat(Math.max(0, len - s.length));
3293
+ console.log(y("\u250C" + "\u2500".repeat(W) + "\u2510"));
3294
+ console.log(y("\u2502") + pad(" \u{1F4A1} Log in for full wizard features:", W - 1) + y("\u2502"));
3295
+ console.log(y("\u2502") + " ".repeat(W) + y("\u2502"));
3296
+ console.log(y("\u2502") + pad(" \u2022 Commands & Code Style [PRO]", W) + y("\u2502"));
3297
+ console.log(y("\u2502") + pad(" \u2022 Boundaries, Testing, Static Files [MAX]", W) + y("\u2502"));
3298
+ console.log(y("\u2502") + pad(" \u2022 Push configs to cloud (lynxp push)", W) + y("\u2502"));
3299
+ console.log(y("\u2502") + pad(" \u2022 Sync across devices (lynxp sync)", W) + y("\u2502"));
3300
+ console.log(y("\u2502") + " ".repeat(W) + y("\u2502"));
3301
+ console.log(y("\u2502") + pad(" Run: " + chalk8.cyan("lynxp login"), W + 10) + y("\u2502"));
3302
+ console.log(y("\u2514" + "\u2500".repeat(W) + "\u2518"));
3303
+ console.log();
3304
+ } else {
3305
+ const planEmoji = userTier === "teams" ? "\u{1F465}" : userTier === "max" ? "\u{1F680}" : userTier === "pro" ? "\u26A1" : "\u{1F193}";
3306
+ console.log(chalk8.green(` \u2713 Logged in as ${chalk8.bold(user?.name || user?.email)} ${planEmoji} ${chalk8.gray(userPlanDisplay)}`));
3307
+ console.log();
3308
+ }
3309
+ showWizardOverview(userTier);
3310
+ const accessibleSteps = getAvailableSteps(userTier);
3311
+ const lockedSteps = WIZARD_STEPS.length - accessibleSteps.length;
3312
+ if (lockedSteps > 0) {
3313
+ console.log(chalk8.gray(` ${lockedSteps} step${lockedSteps > 1 ? "s" : ""} locked. Upgrade at ${chalk8.cyan("https://lynxprompt.com/pricing")}`));
3314
+ console.log();
3315
+ }
2370
3316
  const detected = await detectProject(process.cwd());
2371
3317
  if (detected) {
2372
3318
  const detectedInfo = [
@@ -2398,7 +3344,7 @@ async function wizardCommand(options) {
2398
3344
  commands: detected?.commands || {}
2399
3345
  };
2400
3346
  } else {
2401
- config2 = await runInteractiveWizard(options, detected);
3347
+ config2 = await runInteractiveWizard(options, detected, userTier);
2402
3348
  }
2403
3349
  const spinner = ora7("Generating configuration...").start();
2404
3350
  try {
@@ -2435,14 +3381,21 @@ async function wizardCommand(options) {
2435
3381
  console.log(` ${chalk8.cyan("\u2192")} ${chalk8.bold(filename)}`);
2436
3382
  }
2437
3383
  console.log();
2438
- printBox([
3384
+ const nextStepsLines = [
2439
3385
  chalk8.gray("Your AI assistant will now follow these instructions."),
2440
3386
  "",
2441
3387
  chalk8.gray("Next steps:"),
2442
- chalk8.cyan(" lynxp check ") + chalk8.gray("Validate configuration"),
2443
- chalk8.cyan(" lynxp push ") + chalk8.gray("Sync to cloud"),
2444
- chalk8.cyan(" lynxp status ") + chalk8.gray("View current setup")
2445
- ], chalk8.gray);
3388
+ chalk8.cyan(" lynxp check ") + chalk8.gray("Validate configuration")
3389
+ ];
3390
+ if (authenticated) {
3391
+ nextStepsLines.push(chalk8.cyan(" lynxp push ") + chalk8.gray("Upload to cloud"));
3392
+ nextStepsLines.push(chalk8.cyan(" lynxp link ") + chalk8.gray("Link to a blueprint"));
3393
+ nextStepsLines.push(chalk8.cyan(" lynxp sync ") + chalk8.gray("Sync with linked blueprint"));
3394
+ } else {
3395
+ nextStepsLines.push(chalk8.gray(" lynxp login ") + chalk8.yellow("Log in to push & sync"));
3396
+ }
3397
+ nextStepsLines.push(chalk8.cyan(" lynxp status ") + chalk8.gray("View current setup"));
3398
+ printBox(nextStepsLines, chalk8.gray);
2446
3399
  console.log();
2447
3400
  } catch (error) {
2448
3401
  spinner.fail("Failed to generate files");
@@ -2454,54 +3407,49 @@ async function wizardCommand(options) {
2454
3407
  process.exit(1);
2455
3408
  }
2456
3409
  }
2457
- async function runInteractiveWizard(options, detected) {
3410
+ async function runInteractiveWizard(options, detected, userTier) {
2458
3411
  const answers = {};
2459
- const totalSteps = 5;
2460
- const promptConfig = {
2461
- onCancel: () => {
2462
- console.log(chalk8.yellow("\n Cancelled. Run 'lynxp wizard' anytime to restart.\n"));
2463
- process.exit(0);
3412
+ const availableSteps = getAvailableSteps(userTier);
3413
+ let currentStepNum = 0;
3414
+ const getCurrentStep = (stepId) => {
3415
+ const step = availableSteps.find((s) => s.id === stepId);
3416
+ if (step) {
3417
+ currentStepNum++;
3418
+ return step;
2464
3419
  }
3420
+ return null;
2465
3421
  };
2466
- showStep(1, totalSteps, "Output Format");
3422
+ const formatStep = getCurrentStep("format");
3423
+ showStep(currentStepNum, formatStep, userTier);
2467
3424
  let platforms;
2468
3425
  if (options.format) {
2469
3426
  platforms = options.format.split(",").map((f) => f.trim());
2470
3427
  console.log(chalk8.gray(` Using format from flag: ${platforms.join(", ")}`));
2471
3428
  } else {
2472
- const formatResponse = await prompts4({
2473
- type: "select",
2474
- name: "format",
2475
- message: chalk8.white("Where will you use this?"),
2476
- choices: OUTPUT_FORMATS.map((f) => ({
2477
- title: f.recommended ? `${f.title} ${chalk8.green.bold("\u2605 recommended")}` : f.title,
2478
- value: f.value,
2479
- description: chalk8.gray(f.description)
3429
+ console.log(chalk8.gray(" Select the AI editors you want to generate config for:"));
3430
+ console.log(chalk8.gray(" (AGENTS.md is recommended - works with most AI tools)"));
3431
+ console.log();
3432
+ const platformResponse = await prompts4({
3433
+ type: "multiselect",
3434
+ name: "platforms",
3435
+ message: chalk8.white("Select AI editors (16 supported):"),
3436
+ choices: ALL_PLATFORMS.map((p) => ({
3437
+ title: p.id === "agents" ? `${p.icon} ${p.name} ${chalk8.green.bold("\u2605 recommended")}` : `${p.icon} ${p.name}`,
3438
+ value: p.id,
3439
+ description: chalk8.gray(p.note),
3440
+ selected: p.id === "agents"
3441
+ // Pre-select AGENTS.md
2480
3442
  })),
2481
- initial: 0,
2482
- hint: chalk8.gray("\u2191\u2193 navigate \u2022 enter select")
3443
+ hint: chalk8.gray("space select \u2022 a toggle all \u2022 enter confirm"),
3444
+ min: 1,
3445
+ instructions: false
2483
3446
  }, promptConfig);
2484
- if (formatResponse.format === "multiple") {
2485
- console.log();
2486
- const platformResponse = await prompts4({
2487
- type: "multiselect",
2488
- name: "platforms",
2489
- message: chalk8.white("Select AI editors:"),
2490
- choices: PLATFORMS.map((p) => ({
2491
- title: p.title,
2492
- value: p.value
2493
- })),
2494
- hint: chalk8.gray("space select \u2022 a toggle all \u2022 enter confirm"),
2495
- min: 1,
2496
- instructions: false
2497
- }, promptConfig);
2498
- platforms = platformResponse.platforms || ["agents"];
2499
- } else {
2500
- platforms = [formatResponse.format || "agents"];
2501
- }
3447
+ platforms = platformResponse.platforms || ["agents"];
3448
+ console.log(chalk8.green(` \u2713 Selected ${platforms.length} platform${platforms.length === 1 ? "" : "s"}`));
2502
3449
  }
2503
3450
  answers.platforms = platforms;
2504
- showStep(2, totalSteps, "Project Info");
3451
+ const projectStep = getCurrentStep("project");
3452
+ showStep(currentStepNum, projectStep, userTier);
2505
3453
  const nameResponse = await prompts4({
2506
3454
  type: "text",
2507
3455
  name: "name",
@@ -2518,73 +3466,582 @@ async function runInteractiveWizard(options, detected) {
2518
3466
  hint: chalk8.gray("optional - helps AI understand context")
2519
3467
  }, promptConfig);
2520
3468
  answers.description = descResponse.description || "";
2521
- showStep(3, totalSteps, "Tech Stack");
2522
- const allStackOptions = [...TECH_STACKS, ...FRAMEWORKS];
2523
- const detectedStackSet = new Set(detected?.stack || []);
2524
- const preselected = allStackOptions.map((s, i) => detectedStackSet.has(s.value) ? i : -1).filter((i) => i !== -1);
2525
- if (preselected.length > 0) {
2526
- console.log(chalk8.gray(` Auto-selected: ${detected?.stack?.join(", ")}`));
3469
+ const typeResponse = await prompts4({
3470
+ type: "select",
3471
+ name: "projectType",
3472
+ message: chalk8.white("Project type:"),
3473
+ choices: [
3474
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3475
+ ...PROJECT_TYPES.map((t) => ({
3476
+ title: `${t.icon} ${t.label}`,
3477
+ value: t.id,
3478
+ description: chalk8.gray(t.description)
3479
+ }))
3480
+ ],
3481
+ initial: 0
3482
+ }, promptConfig);
3483
+ answers.projectType = typeResponse.projectType || "";
3484
+ const devOsResponse = await prompts4({
3485
+ type: "select",
3486
+ name: "devOS",
3487
+ message: chalk8.white("Development environment:"),
3488
+ choices: [
3489
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3490
+ ...DEV_OS_OPTIONS.map((o) => ({
3491
+ title: `${o.icon} ${o.label}`,
3492
+ value: o.id
3493
+ }))
3494
+ ],
3495
+ initial: 0,
3496
+ hint: chalk8.gray("Helps generate compatible commands")
3497
+ }, promptConfig);
3498
+ answers.devOS = devOsResponse.devOS || "";
3499
+ const archResponse = await prompts4({
3500
+ type: "select",
3501
+ name: "architecture",
3502
+ message: chalk8.white("Architecture pattern:"),
3503
+ choices: [
3504
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3505
+ ...ARCHITECTURE_PATTERNS.map((a) => ({
3506
+ title: a.label,
3507
+ value: a.id
3508
+ }))
3509
+ ],
3510
+ initial: 0
3511
+ }, promptConfig);
3512
+ answers.architecture = archResponse.architecture || "";
3513
+ const techStep = getCurrentStep("tech");
3514
+ showStep(currentStepNum, techStep, userTier);
3515
+ const letAiResponse = await prompts4({
3516
+ type: "toggle",
3517
+ name: "letAiDecide",
3518
+ message: chalk8.white("Let AI help choose additional technologies?"),
3519
+ initial: false,
3520
+ active: "Yes",
3521
+ inactive: "No"
3522
+ }, promptConfig);
3523
+ answers.letAiDecide = letAiResponse.letAiDecide || false;
3524
+ console.log();
3525
+ console.log(chalk8.gray(" You can also select specific technologies below:"));
3526
+ console.log();
3527
+ const allStackOptions = [...LANGUAGES, ...FRAMEWORKS, ...DATABASES];
3528
+ if (detected?.stack && detected.stack.length > 0) {
3529
+ console.log(chalk8.gray(` Detected in project: ${detected.stack.join(", ")}`));
2527
3530
  console.log();
2528
3531
  }
2529
3532
  const stackResponse = await prompts4({
2530
3533
  type: "multiselect",
2531
3534
  name: "stack",
2532
- message: chalk8.white("Tech stack:"),
3535
+ message: chalk8.white("Languages, frameworks & databases:"),
2533
3536
  choices: allStackOptions.map((s) => ({
2534
3537
  title: s.title,
2535
- value: s.value,
2536
- selected: detectedStackSet.has(s.value)
3538
+ value: s.value
3539
+ // No pre-selection - user must explicitly choose
2537
3540
  })),
2538
3541
  hint: chalk8.gray("space select \u2022 a toggle all \u2022 enter confirm"),
2539
3542
  instructions: false
2540
3543
  }, promptConfig);
2541
3544
  answers.stack = stackResponse.stack || [];
2542
- showStep(4, totalSteps, "AI Persona");
3545
+ const repoStep = getCurrentStep("repo");
3546
+ showStep(currentStepNum, repoStep, userTier);
3547
+ const repoHostResponse = await prompts4({
3548
+ type: "select",
3549
+ name: "repoHost",
3550
+ message: chalk8.white("Repository host:"),
3551
+ choices: [
3552
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3553
+ ...REPO_HOSTS.map((h) => ({
3554
+ title: `${h.icon} ${h.label}`,
3555
+ value: h.id
3556
+ }))
3557
+ ],
3558
+ initial: 0
3559
+ }, promptConfig);
3560
+ answers.repoHost = repoHostResponse.repoHost || "";
3561
+ const visibilityResponse = await prompts4({
3562
+ type: "toggle",
3563
+ name: "isPublic",
3564
+ message: chalk8.white("Public repository?"),
3565
+ initial: false,
3566
+ active: "Yes",
3567
+ inactive: "No"
3568
+ }, promptConfig);
3569
+ answers.isPublic = visibilityResponse.isPublic || false;
3570
+ const licenseResponse = await prompts4({
3571
+ type: "select",
3572
+ name: "license",
3573
+ message: chalk8.white("License:"),
3574
+ choices: [
3575
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3576
+ ...LICENSES.map((l) => ({
3577
+ title: l.label,
3578
+ value: l.id
3579
+ }))
3580
+ ],
3581
+ initial: 0
3582
+ }, promptConfig);
3583
+ answers.license = licenseResponse.license || "";
3584
+ const conventionalResponse = await prompts4({
3585
+ type: "toggle",
3586
+ name: "conventionalCommits",
3587
+ message: chalk8.white("Use Conventional Commits?"),
3588
+ initial: false,
3589
+ active: "Yes",
3590
+ inactive: "No"
3591
+ }, promptConfig);
3592
+ answers.conventionalCommits = conventionalResponse.conventionalCommits || false;
3593
+ const semverResponse = await prompts4({
3594
+ type: "toggle",
3595
+ name: "semver",
3596
+ message: chalk8.white("Use Semantic Versioning?"),
3597
+ initial: false,
3598
+ active: "Yes",
3599
+ inactive: "No"
3600
+ }, promptConfig);
3601
+ answers.semver = semverResponse.semver || false;
3602
+ if (answers.repoHost === "github" || answers.repoHost === "gitlab") {
3603
+ const dependabotResponse = await prompts4({
3604
+ type: "toggle",
3605
+ name: "dependabot",
3606
+ message: chalk8.white("Enable Dependabot/dependency updates?"),
3607
+ initial: false,
3608
+ active: "Yes",
3609
+ inactive: "No"
3610
+ }, promptConfig);
3611
+ answers.dependabot = dependabotResponse.dependabot || false;
3612
+ }
3613
+ const cicdResponse = await prompts4({
3614
+ type: "select",
3615
+ name: "cicd",
3616
+ message: chalk8.white("CI/CD Platform:"),
3617
+ choices: [
3618
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3619
+ ...CICD_OPTIONS.map((c) => ({
3620
+ title: `${c.icon} ${c.label}`,
3621
+ value: c.id
3622
+ }))
3623
+ ],
3624
+ initial: 0
3625
+ }, promptConfig);
3626
+ answers.cicd = cicdResponse.cicd || "";
3627
+ const deployResponse = await prompts4({
3628
+ type: "multiselect",
3629
+ name: "deploymentTargets",
3630
+ message: chalk8.white("Deployment targets:"),
3631
+ choices: DEPLOYMENT_TARGETS.map((t) => ({
3632
+ title: `${t.icon} ${t.label}`,
3633
+ value: t.id
3634
+ })),
3635
+ hint: chalk8.gray("space select \u2022 enter to skip/confirm"),
3636
+ instructions: false
3637
+ }, promptConfig);
3638
+ answers.deploymentTargets = deployResponse.deploymentTargets || [];
3639
+ const containerResponse = await prompts4({
3640
+ type: "toggle",
3641
+ name: "buildContainer",
3642
+ message: chalk8.white("Build container images (Docker)?"),
3643
+ initial: false,
3644
+ active: "Yes",
3645
+ inactive: "No"
3646
+ }, promptConfig);
3647
+ answers.buildContainer = containerResponse.buildContainer || false;
3648
+ if (answers.buildContainer) {
3649
+ const registryResponse = await prompts4({
3650
+ type: "select",
3651
+ name: "containerRegistry",
3652
+ message: chalk8.white("Container registry:"),
3653
+ choices: [
3654
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3655
+ ...CONTAINER_REGISTRIES.map((r) => ({
3656
+ title: `${r.icon} ${r.label}`,
3657
+ value: r.id
3658
+ }))
3659
+ ],
3660
+ initial: 0
3661
+ }, promptConfig);
3662
+ answers.containerRegistry = registryResponse.containerRegistry || "";
3663
+ }
3664
+ const exampleRepoResponse = await prompts4({
3665
+ type: "text",
3666
+ name: "exampleRepoUrl",
3667
+ message: chalk8.white("Example repository URL (optional):"),
3668
+ hint: chalk8.gray("A similar public repo for AI to learn from")
3669
+ }, promptConfig);
3670
+ answers.exampleRepoUrl = exampleRepoResponse.exampleRepoUrl || "";
3671
+ const docsUrlResponse = await prompts4({
3672
+ type: "text",
3673
+ name: "documentationUrl",
3674
+ message: chalk8.white("External documentation URL (optional):"),
3675
+ hint: chalk8.gray("Confluence, Notion, GitBook, etc.")
3676
+ }, promptConfig);
3677
+ answers.documentationUrl = docsUrlResponse.documentationUrl || "";
3678
+ if (canAccessTier(userTier, "intermediate")) {
3679
+ const commandsStep = getCurrentStep("commands");
3680
+ showStep(currentStepNum, commandsStep, userTier);
3681
+ console.log(chalk8.gray(" Select common commands for your project:"));
3682
+ console.log();
3683
+ const buildResponse = await prompts4({
3684
+ type: "multiselect",
3685
+ name: "build",
3686
+ message: chalk8.white("Build commands:"),
3687
+ choices: COMMON_COMMANDS.build.slice(0, 12).map((c) => ({
3688
+ title: chalk8.cyan(c),
3689
+ value: c,
3690
+ selected: detected?.commands?.build === c
3691
+ })),
3692
+ hint: chalk8.gray("space select \u2022 enter confirm"),
3693
+ instructions: false
3694
+ }, promptConfig);
3695
+ const testResponse = await prompts4({
3696
+ type: "multiselect",
3697
+ name: "test",
3698
+ message: chalk8.white("Test commands:"),
3699
+ choices: COMMON_COMMANDS.test.slice(0, 12).map((c) => ({
3700
+ title: chalk8.yellow(c),
3701
+ value: c,
3702
+ selected: detected?.commands?.test === c
3703
+ })),
3704
+ hint: chalk8.gray("space select \u2022 enter confirm"),
3705
+ instructions: false
3706
+ }, promptConfig);
3707
+ const lintResponse = await prompts4({
3708
+ type: "multiselect",
3709
+ name: "lint",
3710
+ message: chalk8.white("Lint/format commands:"),
3711
+ choices: COMMON_COMMANDS.lint.slice(0, 12).map((c) => ({
3712
+ title: chalk8.green(c),
3713
+ value: c,
3714
+ selected: detected?.commands?.lint === c
3715
+ })),
3716
+ hint: chalk8.gray("space select \u2022 enter confirm"),
3717
+ instructions: false
3718
+ }, promptConfig);
3719
+ const devResponse = await prompts4({
3720
+ type: "multiselect",
3721
+ name: "dev",
3722
+ message: chalk8.white("Dev server commands:"),
3723
+ choices: COMMON_COMMANDS.dev.slice(0, 12).map((c) => ({
3724
+ title: chalk8.magenta(c),
3725
+ value: c,
3726
+ selected: detected?.commands?.dev === c
3727
+ })),
3728
+ hint: chalk8.gray("space select \u2022 enter confirm"),
3729
+ instructions: false
3730
+ }, promptConfig);
3731
+ answers.commands = {
3732
+ build: buildResponse.build || [],
3733
+ test: testResponse.test || [],
3734
+ lint: lintResponse.lint || [],
3735
+ dev: devResponse.dev || []
3736
+ };
3737
+ const customCmdResponse = await prompts4({
3738
+ type: "text",
3739
+ name: "custom",
3740
+ message: chalk8.white("Additional custom command (optional):"),
3741
+ hint: chalk8.gray("e.g., npm run migrate, make deploy")
3742
+ }, promptConfig);
3743
+ if (customCmdResponse.custom) {
3744
+ answers.commands.custom = customCmdResponse.custom;
3745
+ }
3746
+ } else {
3747
+ answers.commands = detected?.commands || {};
3748
+ }
3749
+ if (canAccessTier(userTier, "intermediate")) {
3750
+ const styleStep = getCurrentStep("code_style");
3751
+ showStep(currentStepNum, styleStep, userTier);
3752
+ const namingResponse = await prompts4({
3753
+ type: "select",
3754
+ name: "naming",
3755
+ message: chalk8.white("Naming convention:"),
3756
+ choices: [
3757
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3758
+ ...NAMING_CONVENTIONS.map((n) => ({
3759
+ title: n.label,
3760
+ value: n.id,
3761
+ description: chalk8.gray(n.desc)
3762
+ }))
3763
+ ],
3764
+ initial: 0
3765
+ }, promptConfig);
3766
+ answers.namingConvention = namingResponse.naming || "";
3767
+ const errorResponse = await prompts4({
3768
+ type: "select",
3769
+ name: "errorHandling",
3770
+ message: chalk8.white("Error handling pattern:"),
3771
+ choices: [
3772
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3773
+ ...ERROR_PATTERNS.map((e) => ({
3774
+ title: e.label,
3775
+ value: e.id
3776
+ }))
3777
+ ],
3778
+ initial: 0
3779
+ }, promptConfig);
3780
+ answers.errorHandling = errorResponse.errorHandling || "";
3781
+ const loggingResponse = await prompts4({
3782
+ type: "text",
3783
+ name: "loggingConventions",
3784
+ message: chalk8.white("Logging conventions (optional):"),
3785
+ hint: chalk8.gray("e.g., use structured logging, JSON format, specific lib")
3786
+ }, promptConfig);
3787
+ answers.loggingConventions = loggingResponse.loggingConventions || "";
3788
+ const styleNotesResponse = await prompts4({
3789
+ type: "text",
3790
+ name: "styleNotes",
3791
+ message: chalk8.white("Additional style notes (optional):"),
3792
+ hint: chalk8.gray("e.g., prefer named exports, max line length 100")
3793
+ }, promptConfig);
3794
+ answers.styleNotes = styleNotesResponse.styleNotes || "";
3795
+ }
3796
+ const aiStep = getCurrentStep("ai");
3797
+ showStep(currentStepNum, aiStep, userTier);
3798
+ const aiBehaviorResponse = await prompts4({
3799
+ type: "multiselect",
3800
+ name: "aiBehavior",
3801
+ message: chalk8.white("AI behavior rules:"),
3802
+ choices: AI_BEHAVIOR_RULES.map((r) => ({
3803
+ title: r.recommended ? `${r.label} ${chalk8.green("\u2605 recommended")}` : r.label,
3804
+ value: r.id
3805
+ // No pre-selection - user must explicitly choose
3806
+ })),
3807
+ hint: chalk8.gray("space select \u2022 enter to skip/confirm"),
3808
+ instructions: false
3809
+ }, promptConfig);
3810
+ answers.aiBehavior = aiBehaviorResponse.aiBehavior || [];
3811
+ const importantFilesResponse = await prompts4({
3812
+ type: "multiselect",
3813
+ name: "importantFiles",
3814
+ message: chalk8.white("Important files AI should read:"),
3815
+ choices: IMPORTANT_FILES.map((f) => ({
3816
+ title: `${f.icon} ${f.label}`,
3817
+ value: f.id
3818
+ // No pre-selection - user must explicitly choose
3819
+ })),
3820
+ hint: chalk8.gray("space select \u2022 enter to skip/confirm"),
3821
+ instructions: false
3822
+ }, promptConfig);
3823
+ answers.importantFiles = importantFilesResponse.importantFiles || [];
3824
+ const selfImproveResponse = await prompts4({
3825
+ type: "toggle",
3826
+ name: "selfImprove",
3827
+ message: chalk8.white("Enable self-improving blueprint?"),
3828
+ initial: false,
3829
+ active: "Yes",
3830
+ inactive: "No"
3831
+ }, promptConfig);
3832
+ answers.selfImprove = selfImproveResponse.selfImprove || false;
3833
+ const includePersonalResponse = await prompts4({
3834
+ type: "toggle",
3835
+ name: "includePersonalData",
3836
+ message: chalk8.white("Include personal data (name/email for commits)?"),
3837
+ initial: false,
3838
+ active: "Yes",
3839
+ inactive: "No"
3840
+ }, promptConfig);
3841
+ answers.includePersonalData = includePersonalResponse.includePersonalData || false;
3842
+ if (canAccessTier(userTier, "advanced")) {
3843
+ const boundariesStep = getCurrentStep("boundaries");
3844
+ showStep(currentStepNum, boundariesStep, userTier);
3845
+ const presetResponse = await prompts4({
3846
+ type: "select",
3847
+ name: "boundaryPreset",
3848
+ message: chalk8.white("Boundary preset:"),
3849
+ choices: [
3850
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
3851
+ ...BOUNDARY_PRESETS.map((b) => ({
3852
+ title: b.title,
3853
+ value: b.value,
3854
+ description: chalk8.gray(b.description)
3855
+ }))
3856
+ ],
3857
+ initial: 0
3858
+ }, promptConfig);
3859
+ answers.boundaries = presetResponse.boundaryPreset || "";
3860
+ const selectedPreset = BOUNDARY_PRESETS.find((b) => b.value === answers.boundaries);
3861
+ if (selectedPreset) {
3862
+ console.log();
3863
+ console.log(chalk8.gray(" Preset details:"));
3864
+ console.log(chalk8.green(` \u2713 Always: ${selectedPreset.always.slice(0, 3).join(", ")}`));
3865
+ console.log(chalk8.yellow(` ? Ask: ${selectedPreset.askFirst.slice(0, 2).join(", ")}`));
3866
+ console.log(chalk8.red(` \u2717 Never: ${selectedPreset.never.slice(0, 2).join(", ")}`));
3867
+ }
3868
+ const customizeResponse = await prompts4({
3869
+ type: "toggle",
3870
+ name: "customize",
3871
+ message: chalk8.white("Customize specific boundaries?"),
3872
+ initial: false,
3873
+ active: "Yes",
3874
+ inactive: "No"
3875
+ }, promptConfig);
3876
+ if (customizeResponse.customize) {
3877
+ console.log();
3878
+ console.log(chalk8.gray(" Select actions AI should NEVER do:"));
3879
+ const neverResponse = await prompts4({
3880
+ type: "multiselect",
3881
+ name: "never",
3882
+ message: chalk8.white("Never allow:"),
3883
+ choices: BOUNDARY_OPTIONS.map((o) => ({
3884
+ title: chalk8.red(o),
3885
+ value: o,
3886
+ selected: selectedPreset?.never.includes(o)
3887
+ })),
3888
+ instructions: false
3889
+ }, promptConfig);
3890
+ answers.boundaryNever = neverResponse.never || [];
3891
+ console.log(chalk8.gray(" Select actions AI should ASK before doing:"));
3892
+ const askResponse = await prompts4({
3893
+ type: "multiselect",
3894
+ name: "ask",
3895
+ message: chalk8.white("Ask first:"),
3896
+ choices: BOUNDARY_OPTIONS.filter((o) => !answers.boundaryNever?.includes(o)).map((o) => ({
3897
+ title: chalk8.yellow(o),
3898
+ value: o,
3899
+ selected: selectedPreset?.askFirst.includes(o)
3900
+ })),
3901
+ instructions: false
3902
+ }, promptConfig);
3903
+ answers.boundaryAsk = askResponse.ask || [];
3904
+ }
3905
+ } else {
3906
+ answers.boundaries = options.boundaries || "standard";
3907
+ }
3908
+ if (canAccessTier(userTier, "advanced")) {
3909
+ const testingStep = getCurrentStep("testing");
3910
+ showStep(currentStepNum, testingStep, userTier);
3911
+ const testLevelsResponse = await prompts4({
3912
+ type: "multiselect",
3913
+ name: "testLevels",
3914
+ message: chalk8.white("Test levels:"),
3915
+ choices: TEST_LEVELS.map((l) => ({
3916
+ title: `${l.label} - ${chalk8.gray(l.desc)}`,
3917
+ value: l.id,
3918
+ selected: l.id === "unit" || l.id === "integration"
3919
+ })),
3920
+ instructions: false
3921
+ }, promptConfig);
3922
+ answers.testLevels = testLevelsResponse.testLevels || [];
3923
+ const detectedFrameworks = answers.stack?.includes("typescript") || answers.stack?.includes("javascript") ? ["jest", "vitest"] : answers.stack?.includes("python") ? ["pytest"] : [];
3924
+ const testFrameworkResponse = await prompts4({
3925
+ type: "multiselect",
3926
+ name: "testFrameworks",
3927
+ message: chalk8.white("Testing frameworks:"),
3928
+ choices: TEST_FRAMEWORKS.slice(0, 16).map((f) => ({
3929
+ title: f,
3930
+ value: f,
3931
+ selected: detectedFrameworks.includes(f)
3932
+ })),
3933
+ hint: chalk8.gray("space select \u2022 enter confirm"),
3934
+ instructions: false
3935
+ }, promptConfig);
3936
+ answers.testFrameworks = testFrameworkResponse.testFrameworks || [];
3937
+ const coverageResponse = await prompts4({
3938
+ type: "number",
3939
+ name: "coverage",
3940
+ message: chalk8.white("Target code coverage (%):"),
3941
+ initial: 80,
3942
+ min: 0,
3943
+ max: 100
3944
+ }, promptConfig);
3945
+ answers.coverageTarget = coverageResponse.coverage ?? 80;
3946
+ const testNotesResponse = await prompts4({
3947
+ type: "text",
3948
+ name: "testNotes",
3949
+ message: chalk8.white("Testing notes (optional):"),
3950
+ hint: chalk8.gray("e.g., run e2e on main only, use msw for mocking")
3951
+ }, promptConfig);
3952
+ answers.testNotes = testNotesResponse.testNotes || "";
3953
+ }
3954
+ if (canAccessTier(userTier, "advanced")) {
3955
+ const staticStep = getCurrentStep("static");
3956
+ showStep(currentStepNum, staticStep, userTier);
3957
+ console.log(chalk8.gray(" Generate additional project files:"));
3958
+ console.log();
3959
+ const STATIC_FILE_OPTIONS = [
3960
+ { title: "\u{1F4DD} .editorconfig", value: "editorconfig", desc: "Consistent code formatting", file: ".editorconfig" },
3961
+ { title: "\u{1F91D} CONTRIBUTING.md", value: "contributing", desc: "Contributor guidelines", file: "CONTRIBUTING.md" },
3962
+ { title: "\u{1F4DC} CODE_OF_CONDUCT.md", value: "codeOfConduct", desc: "Community standards", file: "CODE_OF_CONDUCT.md" },
3963
+ { title: "\u{1F512} SECURITY.md", value: "security", desc: "Vulnerability reporting", file: "SECURITY.md" },
3964
+ { title: "\u{1F5FA}\uFE0F ROADMAP.md", value: "roadmap", desc: "Project roadmap", file: "ROADMAP.md" },
3965
+ { title: "\u{1F4CB} .gitignore", value: "gitignore", desc: "Git ignore patterns", file: ".gitignore" },
3966
+ { title: "\u{1F4B0} FUNDING.yml", value: "funding", desc: "GitHub Sponsors config", file: ".github/FUNDING.yml" },
3967
+ { title: "\u{1F4C4} LICENSE", value: "license", desc: "License file", file: "LICENSE" },
3968
+ { title: "\u{1F4D6} README.md", value: "readme", desc: "Project readme", file: "README.md" },
3969
+ { title: "\u{1F3D7}\uFE0F ARCHITECTURE.md", value: "architecture", desc: "Architecture docs", file: "ARCHITECTURE.md" },
3970
+ { title: "\u{1F4DD} CHANGELOG.md", value: "changelog", desc: "Version history", file: "CHANGELOG.md" }
3971
+ ];
3972
+ const staticFilesResponse = await prompts4({
3973
+ type: "multiselect",
3974
+ name: "staticFiles",
3975
+ message: chalk8.white("Include static files:"),
3976
+ choices: STATIC_FILE_OPTIONS.map((f) => ({
3977
+ title: f.title,
3978
+ value: f.value,
3979
+ description: chalk8.gray(f.desc)
3980
+ })),
3981
+ hint: chalk8.gray("space select \u2022 enter to skip/confirm"),
3982
+ instructions: false
3983
+ }, promptConfig);
3984
+ answers.staticFiles = staticFilesResponse.staticFiles || [];
3985
+ if (answers.staticFiles?.length > 0) {
3986
+ console.log();
3987
+ console.log(chalk8.cyan(" \u{1F4DD} Customize file contents (press Enter to use defaults):"));
3988
+ console.log(chalk8.gray(" You can paste content or leave empty for auto-generated defaults."));
3989
+ console.log();
3990
+ answers.staticFileContents = {};
3991
+ for (const fileKey of answers.staticFiles) {
3992
+ const fileInfo = STATIC_FILE_OPTIONS.find((f) => f.value === fileKey);
3993
+ if (!fileInfo) continue;
3994
+ const contentResponse = await prompts4({
3995
+ type: "text",
3996
+ name: "content",
3997
+ message: chalk8.white(`Content for ${fileInfo.file}:`),
3998
+ hint: chalk8.gray("paste content or Enter to skip")
3999
+ }, promptConfig);
4000
+ if (contentResponse.content && contentResponse.content.trim()) {
4001
+ answers.staticFileContents[fileKey] = contentResponse.content;
4002
+ }
4003
+ }
4004
+ }
4005
+ }
4006
+ const extraStep = getCurrentStep("extra");
4007
+ showStep(currentStepNum, extraStep, userTier);
2543
4008
  const personaResponse = await prompts4({
2544
4009
  type: "select",
2545
4010
  name: "persona",
2546
- message: chalk8.white("What role should the AI take?"),
2547
- choices: PERSONAS.map((p) => ({
2548
- title: p.title,
2549
- value: p.value,
2550
- description: chalk8.gray(p.description)
2551
- })),
2552
- initial: 0,
2553
- hint: chalk8.gray("\u2191\u2193 navigate \u2022 enter select")
4011
+ message: chalk8.white("AI assistant persona:"),
4012
+ choices: [
4013
+ { title: chalk8.gray("\u23ED Skip"), value: "" },
4014
+ { title: "\u{1F9D1}\u200D\u{1F4BB} Full-Stack Developer", value: "fullstack", description: chalk8.gray("Complete application development") },
4015
+ { title: "\u2699\uFE0F Backend Developer", value: "backend", description: chalk8.gray("APIs, databases, services") },
4016
+ { title: "\u{1F3A8} Frontend Developer", value: "frontend", description: chalk8.gray("UI, components, styling") },
4017
+ { title: "\u{1F680} DevOps Engineer", value: "devops", description: chalk8.gray("Infrastructure, CI/CD") },
4018
+ { title: "\u{1F4CA} Data Engineer", value: "data", description: chalk8.gray("Pipelines, ETL, analytics") },
4019
+ { title: "\u{1F512} Security Engineer", value: "security", description: chalk8.gray("Secure code, auditing") },
4020
+ { title: "\u270F\uFE0F Custom...", value: "custom", description: chalk8.gray("Define your own") }
4021
+ ],
4022
+ initial: 0
2554
4023
  }, promptConfig);
2555
4024
  if (personaResponse.persona === "custom") {
2556
4025
  const customPersona = await prompts4({
2557
4026
  type: "text",
2558
4027
  name: "value",
2559
4028
  message: chalk8.white("Describe the custom persona:"),
2560
- hint: chalk8.gray("e.g., 'ML engineer focused on PyTorch and data pipelines'")
4029
+ hint: chalk8.gray("e.g., 'ML engineer focused on PyTorch'")
2561
4030
  }, promptConfig);
2562
- answers.persona = customPersona.value || "fullstack";
4031
+ answers.persona = customPersona.value || "";
2563
4032
  } else {
2564
- answers.persona = personaResponse.persona || "fullstack";
4033
+ answers.persona = personaResponse.persona || "";
2565
4034
  }
2566
- showStep(5, totalSteps, "AI Boundaries");
2567
- const boundaryResponse = await prompts4({
2568
- type: "select",
2569
- name: "boundaries",
2570
- message: chalk8.white("How much freedom should the AI have?"),
2571
- choices: BOUNDARY_PRESETS.map((b) => ({
2572
- title: b.title,
2573
- value: b.value,
2574
- description: chalk8.gray(b.description)
2575
- })),
2576
- initial: 0,
2577
- hint: chalk8.gray("\u2191\u2193 navigate \u2022 enter select")
4035
+ const extraNotesResponse = await prompts4({
4036
+ type: "text",
4037
+ name: "extraNotes",
4038
+ message: chalk8.white("Anything else AI should know? (optional):"),
4039
+ hint: chalk8.gray("Special requirements, gotchas, team conventions...")
2578
4040
  }, promptConfig);
2579
- answers.boundaries = boundaryResponse.boundaries || "standard";
2580
- const selectedBoundary = BOUNDARY_PRESETS.find((b) => b.value === answers.boundaries);
2581
- if (selectedBoundary) {
2582
- console.log();
2583
- console.log(chalk8.gray(" Always allowed: ") + chalk8.green(selectedBoundary.always.slice(0, 2).join(", ")));
2584
- console.log(chalk8.gray(" Ask first: ") + chalk8.yellow(selectedBoundary.askFirst.slice(0, 2).join(", ")));
2585
- console.log(chalk8.gray(" Never: ") + chalk8.red(selectedBoundary.never.slice(0, 2).join(", ")));
2586
- }
2587
- answers.commands = detected?.commands || {};
4041
+ answers.extraNotes = extraNotesResponse.extraNotes || "";
4042
+ console.log();
4043
+ console.log(chalk8.green(" \u2705 All steps completed!"));
4044
+ console.log();
2588
4045
  return {
2589
4046
  name: answers.name,
2590
4047
  description: answers.description,
@@ -2592,7 +4049,30 @@ async function runInteractiveWizard(options, detected) {
2592
4049
  platforms: answers.platforms,
2593
4050
  persona: answers.persona,
2594
4051
  boundaries: answers.boundaries,
2595
- commands: answers.commands
4052
+ commands: typeof answers.commands === "object" ? answers.commands : detected?.commands || {},
4053
+ // Extended config for Pro/Max users
4054
+ projectType: answers.projectType,
4055
+ devOS: answers.devOS,
4056
+ architecture: answers.architecture,
4057
+ repoHost: answers.repoHost,
4058
+ isPublic: answers.isPublic,
4059
+ license: answers.license,
4060
+ conventionalCommits: answers.conventionalCommits,
4061
+ namingConvention: answers.namingConvention,
4062
+ errorHandling: answers.errorHandling,
4063
+ styleNotes: answers.styleNotes,
4064
+ aiBehavior: answers.aiBehavior,
4065
+ importantFiles: answers.importantFiles,
4066
+ selfImprove: answers.selfImprove,
4067
+ boundaryNever: answers.boundaryNever,
4068
+ boundaryAsk: answers.boundaryAsk,
4069
+ testLevels: answers.testLevels,
4070
+ testFrameworks: answers.testFrameworks,
4071
+ coverageTarget: answers.coverageTarget,
4072
+ testNotes: answers.testNotes,
4073
+ staticFiles: answers.staticFiles,
4074
+ includeFunding: answers.includeFunding,
4075
+ extraNotes: answers.extraNotes
2596
4076
  };
2597
4077
  }
2598
4078